Основные регистры -8,16, 32 битные использование, характеристики




Название Разрядность Основное назначение
EAX   Аккумулятор
EBX   База
ECX   Счётчик
EDX   Регистр данных
EBP   Указатель базы
ESP   Указатель стека
ESI   Индекс источника
EDI   Индекс приёмника
EFLAGS   Регистр флагов
EIP   Указатель инструкции (команды)
CS   Сегментный регистр
DS   Сегментный регистр
ES   Сегментный регистр
FS   Сегментный регистр
GS   Сегментный регистр
SS   Сегментный регистр

Регистры EAX, EBX, ECX, EDX – это регистры общего назначения. Они имеют определённое назначение (так уж сложилось исторически), однако в них можно хранить любую информацию.

Регистры EBP, ESP, ESI, EDI – это также регистры общего назначения. Они имеют уже более конкретное назначение. В них также можно хранить пользовательские данные, но делать это нужно уже более осторожно, чтобы не получить «неожиданный» результат.

Регистр флагов и сегментные регистры требуют отдельного описания и будут более подробно рассмотрены далее.

Пока для вас здесь слишком много непонятных слов, но со временем всё прояснится)))

Когда-то процессоры были 16-разрядными, и, соответственно, все их регистры были также 16-разрядными. Для совместимости со старыми программами, а также для удобства программирования некоторые регистры разделены на 2 или 4 «маленьких» регистра, у каждого из которых есть свои имена. В таблице 2.2 перечислены такие регистры.

Вот пример такого регистра.

Из этого следует, что вы можете написать в своей программе, например, такие команды:

MOV AX, 1

MOV EAX, 1

Обе команды поместят в регистр AX число 1. Разница будет заключаться только в том, что вторая команда обнулит старшие разряды регистра EAX, то есть после выполнения второй команды в регистре EAX будет число 1. А первая команда оставит в старших разрядах регистра EAX старые данные. И если там были данные, отличные от нуля, то после выполнения первой команды в регистре EAX будет какое-то число, но не 1. А вот в регистре AX будет число 1. Сложно? Ну это пока… Со временем вы к таким вещам привыкните.

Мы пока не говорили о разрядах (битах). Эту тему мы обсудим в разделах, посвящённых системам счисления. А сейчас пока вам достаточно знать, что нулевой разряд (бит) – это младший бит. Он крайний справа. Старший бит – крайний слева. Номер старшего бита зависит от разрядности числа/регистра. Например, в 32-разрядном регистре старшим битом является 31-й бит (потому что отсчёт начинается с 0, а не с 1).

Ниже приведён список регистров общего назначения, которые можно поделить описанным выше способом и при этом к «половинкам» и «четвертинкам» этих регистров можно обращаться в программе как к отдельному регистру.

 

Регистр Старшие разряды Имена 16-ти и 8-ми битных регистров
31…16 15…8 7…0
EAX ... AX
AH AL
EBX ... BX
BH BL
ECX ... CX
CH CL
EDX ... DX
DH DL
ESI ... SI
EDI ... DI
EBP ... BP
ESP ... SP
EIP ... IP

Циклы.

Синтаксис объявления меток

Метка представляет собой символическое имя, вместо которого компилятор подставляет адрес. В программе на ассемблере можно присвоить имя любому адресу в коде или данных. Обычно метки используются для организации переходов, циклов или каких-то манипуляций с данными. По сути имена переменных, объявленных с помощью директив объявления данных, тоже являются метками. Но с ними компилятор дополнительно связывает размер переменной. Метка объявляется очень просто: достаточно в начале строки написать имя и поставить двоеточие. Например:

m1: mov ax,4C00h int 21h

Теперь вместо имени m1 компилятор везде будет подставлять адрес комады mov ax,4C00h. Можно объявлять метку на пустой строке перед командой:

exit_app: mov ax,4C00h int 21h

Имя метки может состоять из латинских букв, цифр и символов подчёркивания, но должно начинаться с буквы. Имя метки должно быть уникальным. В качестве имени метки нельзя использовать директивы и ключевые слова компилятора, названия команд и регистров (в этом случае FASM покажет сообщение об ошибке). FASM различает регистр символов в именах меток. Можно также объявлять несколько меток на один адрес. Например:

no_error: exit_app: m1: mov ax,4C00h

Подробнее о синтаксисе объявления меток рассказывается в части 27.

Команда LOOP

Для организации цикла предназначена команда LOOP. У этой команды один операнд — имя метки, на которую осуществляется переход. В качестве счётчика цикла используется регистр CX. Команда LOOPвыполняет декремент CX, а затем проверяет его значение. Если содержимое CX не равно нулю, то осуществляется переход на метку, иначе управление переходит к следующей после LOOP команде.

Содержимое CX интерпретируется командой как число без знака. В CX нужно помещать число, равное требуемому количеству повторений цикла. Понятно, что максимально может быть 65535 повторений. Ещё одно ограничение связано с дальность перехода. Метка должна находиться в диапазоне -127…+128 байт от команды LOOP (если это не так, FASM сообщит об ошибке).

Пример цикла

В качестве примера я приведу простую программу, которая будет печатать все буквы английского алфавита. ASCII-коды этих символов расположены последовательно, поэтому можно выводить их в цикле. Для вывода символа на экран используется функция DOS 02h (выводимый байт должен находиться в регистре DL).

  use16 ;Генерировать 16-битный код org 100h ;Программа начинается с адреса 100h   mov ah,02h ;Для вызова функции DOS 02h - вывод символа mov dl,'A' ;Первый выводимый символ mov cx,26 ;Счётчик повторений цикла metka: int 21h ;Обращение к функции DOS inc dl ;Следующий символ loop metka ;Команда цикла   mov ah,09h ;Функция DOS 09h - вывод строки mov dx,press ;В DX адрес строки int 21h ;Обращение к функции DOS   mov ah,08h ;Функция DOS 08h - ввод символа без эха int 21h ;Обращение к функции DOS   mov ax,4C00h ;\ int 21h ;/ Завершение программы ;------------------------------------------------------- press: db 13,10,'Press any key...$'

Условные операторы.

Условный оператор if-else используется для принятия решения о дальнейшем пути

исполнения программы. Синтаксис условного оператора в нотации языков С и C++:

if (выражение) оператор_1;

else оператор_2

Алгоритм работы условного оператора — вычисляется логическое значение выражения: если оно истинно, то выполняется оператор_1, в противном случае — оператор_2.

В общем случае условный оператор может состоять из одного блока if (без бло­ка else):

if (выражение) оператор_1;

В программе на ассемблере данные варианты условного оператора можно реа­лизовать следующим образом:

короткий вариант оператора if (выражение) оператор_1; cmp opl,op2 вычисление выражения jne endif

;... последовательность команд, соответствующая оператор_1

endif:;конец коротково условново оператора

Строго говоря, использование команды СМР при реализации условного оператора не является обязательным. В данном случае она скорее обозначает место вычисления некоторого условия в программе, по результатам которого принимается решение о ветвлении. Вместо данной команды можно использовать любую команду, изменяющую флаг, который будет анализироваться последующим оператором условного перехода. Эти же рассуждения касаются и команды JNE, вместо которой может сто­ять требуемая в данном вычислительном контексте команда условного перехода:

:полный вариант оператора if (выражение) оператор_1; else оператор_2 cmp opl,op2 вычисление выражения jne elsel

;... последовательность команд, соответствующая оператор і

jmp endif elsel:

;... последовательность команд, соответствующая оператор_2

endif:;конец полного условного оператора.

Процедуры.

Команды CALL и RET

Для работы с процедурами предназначены команды CALL и RET. С помощью команды CALL выполняется вызов процедуры. Эта команда работает почти также, как команда безусловного перехода (JMP), но с одним отличием — одновременно в стек сохраняется текущее значение регистра IP. Это позволяет потом вернуться к тому месту в коде, откуда была вызвана процедура. В качестве операнда указывается адрес перехода, который может быть непосредственным значением (меткой), 16-разрядным регистром (кроме сегментных) или ячейкой памяти, содержащей адрес.

Возврат из процедуры выполняется командой RET. Эта команда восстанавливает значение из вершины стека в регистр IP. Таким образом, выполнение программы продолжается с команды, следующей сразу после команды CALL. Обычно код процедуры заканчивается этой командой. Команды CALL и RET не изменяют значения флагов (кроме некоторых особых случаев в защищенном режиме). Небольшой пример разных способов вызова процедуры:

  use16 ;Генерировать 16-битный код org 100h ;Программа начинается с адреса 100h   mov ax,myproc mov bx,myproc_addr xor si,si   call myproc ;Вызов процедуры (адрес перехода - myproc) call ax ;Вызов процедуры по адресу в AX call [myproc_addr] ;Вызов процедуры по адресу в переменной call word [bx+si] ;Более сложный способ задания адреса;)   mov ax,4C00h ;\ int 21h ;/ Завершение программы   ;---------------------------------------------------------------------- ;Процедура, которая ничего не делает myproc: nop ;Код процедуры ret ;Возврат из процедуры ;---------------------------------------------------------------------- myproc_addr dw myproc ;Переменная с адресом процедуры


Поделиться:




Поиск по сайту

©2015-2024 poisk-ru.ru
Все права принадлежать их авторам. Данный сайт не претендует на авторства, а предоставляет бесплатное использование.
Дата создания страницы: 2016-02-16 Нарушение авторских прав и Нарушение персональных данных


Поиск по сайту: