1. Адресация операндов 1.1 Неявная адресация В случае неявной адресации, адрес операнда подразумевается в коде команды. Т.е. команда работает только с однозначно определенным операндом. Примеры: AAA – скорректировать регистр AL после сложения, т.е. подразумевается работа с операндом, который находится в аккумуляторе. STD – установить в 1 флаг направления, т.е. подразумевается, что операнд находится в регистре флагов. 1.2 Регистровая адресация В командах с таким режимом адресации операнд или операнды находятся в регистрах процессора, как правило, в регистрах общего назначения (РОНах – SI,DI и т.д.). Наименование регистра, в котором хранится операнд, явно указывается в коде команды. Примеры: INC AX – увеличить содержимое аккумулятора (регистр AX) на единицу. XOR EDX,EDX – обнулить регистр EDX. SUB EDX,EDX – обнулить регистр EDX. 1.3 Непосредственная адресация В командах с таким режимом адресации операнд, длиной 8,16 или 32 бита, находится в теле самой команды и является константой. Примеры: MOV AX,100 – загрузка в аккумулятор (регистр AX) числа 100.. AND BH,0Ah – произвести побитовую операцию «и» содержимого регистра BH с числом 0Ah. Следует отметить, что в приведенных выше двух примерах первый операнд указан с помощью регистровой адресации, а второй – с помощью непосредственной. 1.4 Адресация операндов в памяти 1.4.1 Прямая адресация Эффективный адрес задается в теле самой команды. Эффективный адрес – это смещение от начала соответствующего сегмента. Адрес сегмента обычно располагается в регистре DS, но с помощью префикса замены сегмента можно обратиться к любому другому сегменту. Примеры: MOV AX, [1000h] – загрузка в аккумулятор слова из памяти по адресу DS*16+1000h ADD AX, mas1 – сложение с содержимым аккумулятора первого элемента массива, находящегося в памяти по адресу:DS*16+mas1 INC WORD PTR[24Ch] – увеличение на единицу слова находящегося в памяти 1.4.2 Косвенная адресация 1.4.2.1 Косвенная регистровая адресация (базовая) 1.4.2.2 Базовая адресация со смещением (регистровая относительная) Этот режим отличается от предыдущего тем, что к эффективному адресу операнда, находящемуся в выше указанных регистрах, прибавляется смещение, явно указанное в теле команды. Пример: MOV AX, [BX+4] – загрузка в аккумулятор слова из памяти эффективный адрес которого хранится в виде суммы BX+4. 1.4.23 Индексная адресация со смещением (прямая индексная) Индексный – любой из общих регистров кроме [ E ]SP. Данный способ удобен при работе с массивами, когда прямой адрес определяет начало массива. В этом режиме эффективный адрес операнда находится в любом из РОНов, кроме ESP. Использование в качестве базового регистра EBP определяет смещение относительно SS, т.е. в стеке, остальные – в DS. Пример: MOV AX, [BX] – загрузка в аккумулятор слова из памяти, эффективный адрес которого хранится в BX. 1.4.2.2 Базовая адресация со смещением (регистровая относительная) Этот режим отличается от предыдущего тем, что к эффективному адресу операнда, находящемуся в выше указанных регистрах, прибавляется смещение, явно указанное в теле команды. Пример: MOV AX, [BX+4] – загрузка в аккумулятор слова из памяти эффективный адрес которого хранится в виде суммы BX+4. 1.4.2.3 Индексная адресация со смещением (прямая индексная) Индексный – любой из общих регистров кроме [ E ]SP. Данный способ удобен при работе с массивами, когда прямой адрес определяет начало массива. Пример. Определить сумму 100 элементов массива ( mas dw 100 dup (?)): xor si, si mov cx, 100 sub ax, ax m1: add ax, mas[si] add si, 2 loop m1 Индексная со смещением: mov ax, array[si + 2]. 1.4.2.4 Базовая индексная адресация со смещением mov ax, [bx][si] +8 т.е. эффективный адрес вычисляется как сумма содержимого регистров bx, si и смещения 8 в самой команде: EA = [bx] + [si] +8 Базовая индексная: add dx, [bx][di] В процессорах от 386 значение индекса разрешается масштабировать, что упрощает работу с массивами. Н: mov eax, [ebx][ecx * N] + 8, где N = { 1, 2 ,4, 8 } Для предыдущего фрагмента можно заменить так: m1: add ax, mas[si * 2] inc si Замечание: Если регистр EBP указывается с масштабированием, он не вызывает обращения к сегменту стека, в остальных случаях (если нет префикса замены сегмента) он считается базовым и ссылается на сегмент стека. Пример: mov ax, mas1[bp] - ссылка на стек, mov eax, [ecx][ebp *4] - ссылка на сегмент данных, адрес которого в DS. Предложения Программа на языке assembler состоит из последовательности предложений, каждое из которых должно занимать 1 строку длиной < 132 символов. Переносить предложение на другую строку или записывать в строке 2 и более предложений нельзя. Предложения могут быть: комментарии; команды; директивы (указания компилятору). Комментарии: начинаются с ; ( точки с запятой) Пример: ;загрузка DS MOV ax, DATA MOV ds, ax ; через ax Команды: символьная форма записи машинных команд. Формат: [<метка:>] мнемокод [<операнды>] [;комментарии] мнемокод – символическое имя машинной команды; метка – идентификатор (указатель) команды, который отделяется от команды (;), в одной строке – 1 метка; операндов может быть несколько ( до трёх ), они отделяются друг от друга запятыми. Пример: MET1: MET2: LEA bx, ARRAY ; загрузить эффективный адрес массива ARRAY в регистр bx. INC al ; регистр al++ CBW ; расширение знака из al в ah; Директивы: Формат: это указания действию транслятора по обработке ассемблерной программы. [< имя >] директива [ < операнды >] [; комментарии] Директивы распределения памяти В директивах распределения памяти операнды, если их несколько, разделяются запятыми. Директива DB – определить байт. По этой директиве компилятор выделяет в памяти байт под каждый операнд и, если требуется, инициализирует соответствующим значением операнда. Примеры: A DB 7 ; В байт, которому присвоен символический адрес А, записывается число 7. mas db 1, 2, 3, 4, 5 mas db db db db db 1 2 3 4 5 ; unsigned char mas[] = {1,2,3,4,5} ; данный вариант аналогичен предыдущему X DB ? ; по этой директиве будет выделен байт памяти, но его значение не определено ( char X; ). mas2 DB mas3 DB ; выделяется 100 байт памяти под массив. DUP – префикс повторения. ; выделяется 256 байт памяти, каждый из которых 100 DUP ( ? ) 100h DUP (0) обнулен. Str DB ‘ABCD’, “FOR”, ‘имя’, 10, 13, ‘$’ ; строки с переводом на новую строку для функции 09h прерывания 21h DOS. ARR2 DB 10 DUP( 10 DUP(?)) : char ARR2[10][10]; DW - определить слово; DD - определить двойное слово (32 бита); DQ - определить квадрослово (64 бита). Директивы эквивалентности и присваивания < имя > EQU < операнд > Примеры: DIEZ EQU ‘#’ ; define DIEZ ‘#’ T DB DIEZ ; T DB ‘#’ < имя > = < константное выражение > N=8 R DW N N=N+4 : R DW 8 R2 DW N ; R2 DW 12 Формат машинной команды Префиксы (байт со специальным кодированием) Повторения 0 -1 REP mod 2 бита Размер адреса 0 - 1 Размер операнда 0 - 1 Замена сегмента 0 - 1 Блокировка шины 0 - 1 UZER (16,32) UZER (16,32) ES:, FS:,GS: LOCK Reg/ко п 3 R/m ss index base 3 2 бита 3 3 Код операции mod/r/m sib Смещение в команде 1-2 0-1 0 -1 0, 1, 2, 4 Непосредст венный операнд 0, 1, 2, 4 Обзор системы машинных команд Все команды можно разделить на: 1. 2. 3. 4. 5. 6. 7. 8. 9. Команды передачи (пересылки) данных Арифметические команды Команды передачи управления Команды обработки цепочек (цепочечные команды) Команды поразрядной обработки (логические, сдвигов) Передачи адресных объектов Команды ввода – вывода Поддержки языков высокого уровня Команды управления процессором Команды передачи данных MOV операнд1, операнд2 ; [оп2] --> [оп1] Операнд1 в reg, mem – 8, 16, 32 бита; Операнд2 в reg, mem, непосредственный – 8, 16, 32 бита; Примеры: mov ax, dx MOV mem1, cx mov cx, 100 mov bx, mas[si] Пересылка память – память запрещена ( кроме цепочечных команд типа MOVS и т. п.). Разрядность операндов должна совпадать, иначе компилятор зафиксирует ошибку (нельзя mov ax, bh ). В случае непосредственного операнда он расширяется знаковым разрядом до величипы операнда – приёмника (если больше – ошибка ). Числа размером слово и больше хранятся в оперативной памяти в перевёрнутом виде ( младший байт по младшему адресу). Команда MOV при выборке из ОП в регистр учитывает это и пересылает в нормальном виде. Примеры: A DW 1234h ; инициализация переменной А шестнадцатеричным числом 1234h. В памяти с адреса А будет 3412h. mov al, A ; нельзя из-за несовпадения ;размерности, но можно так: mov al, byte ptr A ; в al 34h mov ax, A ; в ax будет 1234h Напомним приведение типа операндов в памяти: < byte > < word > < dword > ptr имя Если объявлено B12 DD 12345678h, то mov al, byte ptr B12 ; в al посылается 78h Примечание: 1. Только с помощью команды MOV ( и стековых команд ) можно загружать и сохранять сегментные регистры (+ команды загрузки сегментных регистров); 2. Нельзя загружать в сегментные регистры константы, только через общие регистры ( например, через AX ). 3. Использование в команде аккумулятора ( ax ) уменьшает длину команды на 1 байт. 4. Если приёмником является регистр SS, то прерывания должны быть запрещены до окончания следующей команды ( обычно mov (E)SP, op2 ) Команда обмена XCHG op1, op2 Пример: ; Производится обмен содержимого по адресам op1 и op2 mov ax, 10 mov bx, 5 xchg ax, bx op1-reg op2 – reg/ mem; ; ax = 5, bx = 10 op1 – reg/mem op2 – reg Команда табличного преобразования XLAT op ; в этом случае op – фиктивный операнд, ассоциируемый с именем таблицы (может использоваться для замены сегмента). Команда копирует байт из таблицы, адресуемой DS:BX или DS:EBX + исходное содержимое регистра AL как беззнаковое смещение в таблице в регистр AL. Если таблица, адресуемая (Е)ВХ уже находится в сегменте DS, то можно использовать безоперандную форму команды XLATB.