Arkhitektura_EVM_uchebnoe_posobie
.pdfНепосредственная адресация применяется, когда операнд длиной в байт или слово находится в ассемблерной команде:
mov AX,4Ch
При использовании косвенной адресации исполнительный адрес формируется исходя из сегментного адреса в одном из сегментных регистров и смещения в регистрах ВХ, ВР, SI или DI, например:
mov AL,[ВХ] |
; |
База находится в регистре |
DS, смещение – в |
|
mov АН,[SI] |
; |
регистре |
ВХ |
SI |
; |
База – в |
DS, смещение – в |
||
mov AX,[DI] |
; |
База – в |
DS, смещение – в |
DI |
mov AX,ES:[DI] ; |
База – в |
ES, смещение – в |
DI |
|
mov DX,[ВР] |
; |
База – в |
SS, смещение – в |
ВР |
В случае применения базовой адресации исполнительный адрес является суммой значения смещения и содержимого регистра ВР или ВХ, например:
mov АХ,[ВР+6] |
; |
База – SS, |
смещение определяется |
|
; |
содержимым |
ВР, которое складывается с 6 |
mov [ВХ+Delta],АХ ; |
База – DS, |
смещение – содержимое |
|
mov АХ,[ВР]+4 |
; |
ВХ+смещение Delta |
|
; |
База – SS, |
смещение – содержимое ВР+4 |
|
mov DX,8[BX] |
; |
База – DS, |
смещение – содержимое ВХ+8 |
При индексной адресации исполнительный адрес определяется как сумма значений указанного смещения и содержимого регистра SI или DI так же, как и при базовой адресации, например:
mov |
DX,[SI+5] |
; |
База |
– |
DS, |
смещение |
– |
содержимое |
– |
SI+5 |
mov |
ES:[DI]+6, AL |
; |
База |
– |
ES, |
смещение |
– |
содержимое |
– |
DI+6 |
Базово-индексная адресация подразумевает использование для вычисления исполнительного адреса суммы содержимого базового и индексного регистров, а также смещения, находящегося в операторе, например:
mov BX,[BP][SI] |
|
|
mov ES:[BX+DI],AX |
|
|
mov Array[BX][SI],12h |
|
|
mov AX,[BP+6+DI] |
; ошибка – два базовых |
регистра |
mov Array [BP+BX] |
||
mov Array [BP+DI+SI] |
; ошибка – два индексных регистра |
3.4.2. Кодирование команд
Машинная команда помимо байта кода операции, может содержать один байт префикса команды, один байт, задающий переопределение сегмента, байт ModR/M, определяющий режим адресации, один или два байта, задающих адрес операнда в памяти, и один или два байта, содержащих непосредственные дан-
ные (рис. 3.5).
70
Префикс |
Перекрытие |
Код |
ModR/M |
Адрес |
Данные |
|
сегмента |
операции |
|||||
|
|
|
|
|||
1 байт |
1 байт |
1 байт |
1 байт |
2 байта |
2 байта |
Рис. 3.5. Формат машинной команды
Обязательным элементом формата машинной команды является код операции, определяющий команду процессора. Наличие или отсутствие остальных составляющих полностью определяется типом ассемблерной команды и ее операндами.
Применение префиксов приводит к повторению какой-то команды. Перекрытие сегмента указывает, что в команде будет применен сегмент, отличный от принятого по умолчанию, например, вместо DS:DX – CS:DX.
Код операции зависит от используемых форматов операндов и регистров. Байт ModR/M и коды операции определяют режим адресации операндов и являются основными элементами команды, используемыми при определении процессором типа и количества операндов.
Поле Mod байта ModR/M (рис. 3.6) определяет используемый в команде режим адресации. Это поле указывает, как интерпретируется поле R/M. Поле Reg указывает регистр, используемый в качестве одного из операндов команды. При использовании непосредственной адресации поле Reg содержит расширение кода операции. Поле R/M указывает либо регистр, либо адрес памяти, задаваемый некоторой комбинацией байтов смещения и содержимого регистров.
Длина |
2 |
3 |
3 |
|
(бит) |
||||
|
|
|
||
Поле |
Mod |
Reg |
R/M |
|
|
|
|
|
Рис. 3.6. Формат байта ModR/M
Если Mod=11, то операнды команды находятся в регистрах процессора, указанных в полях Reg и R/M (рис. 3.7).
При этом имеет значение нулевой бит кода операции (W-бит): при W=0 используются восьмиразрядные регистры; при W=l – 16-разрядные.
Поле Reg |
|
Регистр |
Сегментный |
|
(или R/M) |
W=0 |
|
W=1 |
регистр |
000 |
AL |
|
AX |
ES |
001 |
CL |
|
CX |
CS |
010 |
DL |
|
DX |
SS |
011 |
BL |
|
BX |
DS |
100 |
AH |
|
SP |
- |
101 |
CH |
|
BP |
- |
110 |
DH |
|
SI |
- |
111 |
BH |
|
DI |
- |
Рис. 3.7. Кодирование регистровых операндов при Mod =11
71
В других случаях поля Mod, R/M и код операции определяют используемый режим адресации. На рис. 3.8 представлены все возможные комбинации значений полей Mod и R/M с соответствующими режимами адресации.
Значение R/M |
|
Режим адресации |
|
|
|
|
Mod=00 |
|
000 |
|
BX+SI |
001 |
|
BX+DI |
010 |
|
BP+SI |
011 |
|
BP+DI |
100 |
|
SI |
101 |
|
DI |
110 |
|
DispHDispL |
111 |
|
BX |
|
Mod=01 |
|
000 |
|
BX+SI+DispL |
001 |
|
BX+DI+DispL |
010 |
|
BP+SI+DispL |
011 |
|
BP+DI+DispL |
100 |
|
SI+DispL |
101 |
|
DI+DispL |
110 |
|
BP+DispL |
111 |
|
BX+DispL |
|
Mod=01 |
|
000 |
|
BX+SI+DispHDispL |
001 |
|
BX+DI+DispHDispL |
010 |
|
BP+SI+DispHDispL |
011 |
|
BP+DI+DispHDispL |
100 |
|
SI+DispHDispL |
101 |
|
DI+DispHDispL |
110 |
|
BP+DispHDispL |
111 |
|
BX+DispHDispL |
Рис. 3.8. Кодирование операндов при Mod = 00, Mod = 01, Mod = 10
DispL соответствует младшему байту слова, содержащего смещение адреса операнда относительно заданного сегмента, DispH – старшему байту этого слова. Сегмент определяется либо по умолчанию, либо с помощью байта переопределения сегмента.
Необходимо отметить, что байт ModR/M отсутствует в команде, если
−команда не имеет операндов (PUSH, RET);
−первый операнд команды – регистр, второй – непосредственное значе-
ние;
−один операнд – адрес памяти (при прямой адресации), второй – регистр АХ (AL);
−в команде перехода применяется прямая адресация;
−это команда ввода-вывода (IN, OUT).
72
Кроме того, в некоторых командах режим адресации находится непосредственно в коде операции. Если же в команде используется косвенная адресация, то байт ModR/M присутствует всегда.
Пример 3.1. Пусть операция MOV кодируется значением 1000101w. Указать полный код операций:
1)mov ax, di;
2)mov dx, [di];
3)mov cl, [bx+di+1234h];
4)mov al, [bp+si+10].
1) mov ax, di
W=1 – используется регистр ax; оба операнда являются регистрами, поэтому Mod=11,
согласно рис. 7 Reg = 000, R/M = 111.
Запишем двоичный и шестнадцатеричный код операции: 10001011 11000111 (2) 8B C7 (16)
2) mov dx, [di]
W=1 – используется регистр ax; используется косвенная адресация без смещения, первый операнд регистр, поэтому Mod=00, согласно рис. 7 Reg = 010, согласно рис.8.
R/M = 101.
Запишем двоичный и шестнадцатеричный код операции: 10001011 00010101 (2) 8B 15 (16)
3) mov cl, [bx+di+1234h]
W=0 – используется регистр cl; используется косвенная адресация со смещением, первый операнд регистр, поэтому Mod=10, согласно рис. 7 Reg = 001, согласно рис.8.
R/M = 001.
Запишем двоичный и шестнадцатеричный код операции, учитывая то, что в памяти сначала располагается младший байт смещения, а затем старший:
10001010 10001001 00110100 00010010 (2) 8A 89 34 12 (16)
4) mov al, [bp+si+10]
W=0 – используется регистр al; используется косвенная адресация со смещением, первый операнд регистр, поэтому Mod=01, согласно рис. 7 Reg = 000, согласно рис.8.
R/M = 010.
Запишем двоичный и шестнадцатеричный код операции:
10001010 01000010 00010000 (2) |
8A 42 10 (16) |
|
Ответ: mov ax, di |
8B |
C7 (16) |
mov dx, [di] |
8B |
15 (16) |
mov cl, [bx+di+1234h] |
8A 89 34 12 (16) |
|
mov al, [bp+si+10] |
8A 42 10 (16) |
3.5. Система команд
По назначению можно выделить команды:
пересылки данных (MOV – переслать, XCHG – обменять, IN – ввести в
микропроцессор, OUT – вывести из микропроцессора и т. д.);
выполнения арифметических операций (ADD и ADC – сложения и сложе-
ния с переносом, SUB и SBB – вычитания и вычитания с заемом, MUL и IMUL
– умножения без знака и со знаком, DIV и IDIV – деления без знака и со зна-
73
ком, СМР – сравнения и т. д.);
выполнения логических операций (OR, AND, NOT, XOR, TEST и т. д.);
передачи управления (ветвления программы: JMP – безусловного перехода, CALL – вызова процедуры, RET – возврата из процедуры, J* – условного перехода, LOOP – управления циклом и т. д.);
обработки строк символов (MOVS – пересылки, CMPS – сравнения, LODS
– загрузки, SCAS – сканирования). Эти команды обычно используются с префиксом (модификатором повторения) REP;
прерывания работы программы (INT – программные прерывания, INTO –
условного прерывания при переполнении, IRET – возврата из прерывания);
управления микропроцессором (ST* и CL* – установки и сброса флагов, HLT – остановки, WAIT – ожидания, NOP – холостого хода и т. д.).
С полным списком команд ассемблера можно ознакомиться в работе [14].
Команды пересылки данных
Команда пересылки данных MOV
MOV <получатель>, <источник>
MOV пересылает содержимое второго операнда в первый. Регистр CS не может кодироваться в качестве приемника.
Команда обмена данных XCHG
XCHG <операнд1>, <операнд2>
XCHG меняет местами содержимое двух операндов. Порядок следования операндов не имеет значения. Регистр CS не может быть операндом.
Команда чтения из порта IN
IN AL, <операнд>
IN AX, <операнд> IN AL, DX
IN AX, DX
IN считывает байт или слово данных из порта, номер которого задает второй операнд, и помещает его в регистр AL или АХ, указанный в качестве первого операнда. Помещая номер порта в DX и используя команду IN с DX в качестве второго операнда, можно получить доступ к любому порту (от 0 до
65535).
Команда записи в порт OUT
OUT <операнд>, AL
OUT <операнд>, AX
OUT пересылает байт или слово данных из регистра AL или АХ, указанного в качестве второго операнда, в порт, номер которого задает первый операнд.
Команда перекодировки XLAT
XLAT <операнд>
XLAT заменяет содержимое регистра AL байтом из таблицы перекодиров-
74
ки (максимальная длина – 256 байт), начальный адрес которой относительно сегмента DS находится в регистре ВХ.
Алгоритм выполнения команды XLAT состоит из двух этапов: содержимое регистра AL прибавляется к содержимому регистра ВХ; полученный результат рассматривается как смещение относительно регистра DS. По данному адресу выбирается байт и помещается в регистр AL.
Команды работы с адресами
LEA <назначение>, <источник>
LEA вычисляет эффективный адрес (смещение) объекта памяти в соответствии с заданным режимом адресации и помещает его значение в указанный регистр.
LDS <назначение>, <источник>
LES <назначение>, <источник>
Эти команды загружают полный указатель из памяти и записывают его в выбранную пару «сегментный регистр:регистр». При этом первое слово из адресуемой памяти загружается в регистр первого операнда, второе – в регистр DS, если выполняется команда LDS, или в регистр ES, если выполняется команда LES.
Команды загрузки/сохранения флагов LAHF/SAHF
LAHF переносит значения из младшего байта флагового регистра в АН. Биты регистра АН при этом принимают значения (слева направо): SF, ZF, не определен, AF, не определен, PF, не определен, CF.
SAHF загружает указанные флаги значениями, установленными в регистре АН из битов 7, 6, 4, 2 и 0 соответственно.
Команды сохранения в стеке PUSH и PUSHF
PUSH <операнд> PUSHF
PUSH уменьшает на 2 значение указателя стека SP, после чего операнд помещается в вершину стека, адресуемую этим новым значением указателя стека.
PUSHF уменьшает на 2 значение указателя стека и копирует содержимое регистра флагов в новую вершину стека.
Команды восстановления из стека POP и POPF
POP <операнд> POPF
POP восстанавливает предыдущее состояние операнда памяти, регистра или сегментного регистра из слова, находящегося в вершине стека. Адрес вершины стека определяется регистровой парой «SS:SP». Указатель стека при этом увеличивается на 2 и определяет новую вершину стека. Команда POP CS недопустима.
POPF восстанавливает из стека слово и помещает его в регистр флагов.
75
Арифметические команды
Все арифметические команды устанавливают флаги CF, AF, SF, ZF, OF и PF в зависимости от результата операции.
Двоичные числа могут иметь длину 8 или 16 бит. Значение старшего (самого левого бита) задает знак числа: 0 – положительное, 1 – отрицательное. Отрицательные числа представляются в дополнительном коде.
Десятичные числа представляются в упакованном двоично-десятичном формате (BCD) или неупакованном (ASCII). С неупакованными десятичными числами допускается сложение, вычитание, умножение и деление. С упакованными числами допускается только сложение и вычитание.
Десятичные упакованные числа хранятся в виде двух цифр в диапазоне от 0 до 9, составляющих один байт. Например: если в регистре AL находится значение 00111001b, то в командах десятичной арифметики оно будет интерпретироваться не как шестнадцатеричное число 39h = 57, а как десятичная упакованная цифра 39.
Неупакованный формат предполагает, что каждая десятичная цифра занимает один байт памяти. Например: содержимое регистра АХ = 0603h представляет десятичное неупакованное число 63.
Команда двоичного сложения ADD
ADD <операнд1>, <операнд2>
ADD выполняет целочисленное сложение двух операндов, помещая результат в первый операнд и устанавливая флаги в соответствии с результатом операции.
Команда двоичного сложения с переносом ADC
ADC <операнд1>, <операнд2>
ADC выполняет целочисленное сложение двух операндов с использованием содержимого флага переноса (CF), который прибавляется к младшему биту результата. Результат заносится в первый операнд, а флаг устанавливается соответственно результату операции. ADC часто выполняется как часть многобайтной или многословной операции сложения.
Команда увеличения на 1 INC
INC <операнд>
INC увеличивает операнд на 1, не изменяя флага переноса. Для использования флага переноса надо применять команду ADC с 1 в качестве непосредственного операнда.
Команда двоичного вычитания SUB
SUB <операнд1>, <операнд2>
SUB вычитает второй операнд из первого. Первый получает значение результата вычитания, при этом флаги выставляются в соответствии с результатом операции.
76
Команда двоичного вычитания с заемом SBB
SBB <операнд1>, <операнд2>
SBB складывает второй операнд со значением флага переноса (CF) и вычитает результат из первого операнда. Результат вычитания присваивается первому операнду, флаги устанавливаются в соответствии с результатом.
Команда уменьшения на 1 DEC
DEC <операнд>
DEC уменьшает операнд на 1, не изменяя флага переноса. Для использования флага переноса при вычитании необходимо применять команду SUB с заданным непосредственно операндом 1.
Команда сравнения CMP
CMP <операнд1>, <операнд2>
CMP, подобно команде SUB, вычитает второй операнд из первого, но не записывает результат, а лишь изменяет флаги. СМР обычно используется вместе с командами условных переходов.
Команда инвертирования NEG
NEG <операнд>
NEG заменяет значение регистра или памяти, используемое в качестве операнда, на его «дополнение до двух», вычитая операнд из 0 и помещая результат на место операнда.
Флаг переноса устанавливается в 1, если операнд не 0, в противном случае
– очищается.
Команда коррекции AL после ASCII-сложения ААА
Выполнение команды ААА имеет смысл после команды ADD, которая оставляет байт результата в регистре AL. Младшие тетрады (полубайты) операндов команды ADD должны быть в диапазоне от 0 до 9. В этом случае ААА выполняет коррекцию регистра AL таким образом, чтобы он содержал в результате правильную десятичную цифру.
Команда коррекции AL после ASCII-вычитания AAS
Выполнение команды AAS имеет смысл после команды SUB, которая оставляет байт результата в регистре AL. Младшие тетрады операндов команды SUB должны быть в диапазоне от 0 до 9. В этом случае AAS выполняет коррекцию регистра AL таким образом, чтобы он содержал в результате правильную десятичную цифру.
Команда коррекции АХ после ASCII-умножения ААМ
Команда ААМ используется для коррекции в регистре АХ результата умножения (MUL) двух неупакованных BCD-цифр.
Команда коррекции перед ASCII-делением AAD
AAD используется для подготовки двух неупакованных BCD-цифр (в регистре AL находится число десятков, в регистре АН – число единиц) для опера-
77
ции деления, которая вернет результат в неупакованном виде. Это выполняется установкой AL в AL + (10 * АН) и сбросом АН в 0. После этого в регистре АХ находится двоичный эквивалент исходного неупакованного числа из двух цифр.
Команда десятичной коррекции AL после сложения DAA
Команда DAA выполняется только после выполнения команды ADD, которая оставляет в AL байт результата, представляющий собой две упакованные десятичные цифры. Если в результате выполнения ADD получены цифры, не являющиеся десятичными, то DAA выполняет коррекцию, приводя их к десятичному упакованному виду.
Команда десятичной коррекции AL после вычитания DAS
Команда DAS выполняется только после выполнения команды вычитания, которая оставляет в AL байт результата, представляющий собой две упакованные десятичные цифры. Если после вычитания получены цифры, не являющиеся десятичными, то DAS выполняет коррекцию, приводя их к десятичному упакованному виду.
Команда беззнакового умножения MUL
MUL <операнд>
MUL выполняет беззнаковое умножение. Ее работа зависит от размера операндов таким образом:
операнд размером в байт умножается на содержимое регистра AL, результат помещается в АХ. Флаги CF и OF устанавливаются в 0, если АН = 0, в противном случае – в 1;
операнд размером в слово умножается на содержимое регистра АХ, результат помещается в DX:AX (регистр DX рассматривается как продолжение регистра АХ). Флаги CF и OF устанавливаются в 0, если DX = 0, в противном случае – в 1.
Команда умножения со знаком IMUL
IMUL <операнд>
IMUL выполняет умножение со знаком операнда типа r/m на второй операнд, находящийся в регистре, выбор которого определяется размером первого операнда: для байта – в AL, результат помещается в АХ, для слова – в АХ, результат – в DX:AX. Единица в левом (старшем) бите числа рассматривается как знак «минус» для отрицательных чисел. IMUL очищает флаги CF и OF при выполнении расширения знака операнда в AL до 16 бит.
Команда беззнакового деления DIV
DIV <операнд>
DIV выполняет операцию целочисленного беззнакового деления. В качестве операнда задается только делитель. Остаток от деления всегда меньше, чем делитель. Регистр, который необходимо использовать для операции, определяется типом делителя по следующим правилам: для байта – делимое AX, частное
78
помещается в AL, а остаток – в AH; для слова – делимое DX:AX, частное помещается в AX, а остаток – в DX.
Команда деления со знаком IDIV
IDIV <операнд>
IDIV выполняет деление со знаком. Делимое, частное и остаток всегда находятся в конкретных регистрах. В качестве операнда задается только делитель. Регистр, используемый в операции деления, определяется типом делителя по следующим правилам: для байта – делимое AX, частное помещается в AL, а остаток в AH; для слова – делимое DX:AX, частное помещается в AX, а остаток – в DX.
Если частное слишком велико и не помещается в указанном приемнике или делитель равен 0, генерируется прерывание Int 0. Остаток имеет тот же знак, что и делимое, а его абсолютное значение всегда меньше, чем абсолютное значение делителя.
Команда преобразования байта в слово CBW
CBW преобразовывает байт со знаком, находящийся в регистре AL, в слово со знаком, помещаемое в регистр АХ, путем распространения старшего бита регистра, AL (знаковый бит) по всем битам регистра АН.
Команда преобразования слова в двойное слово CWD
CWD преобразовывает слово со знаком, хранящееся в регистре АХ, в форму двойного слова со знаком, которое помещается в DX:AX, путем распространения старшего бита из регистра АХ по всем битам регистра DX.
Логические команды
Эту группу команд можно разделить на две подгруппы: логические операции и операции сдвигов. Команды AND, TEST, OR, XOR и команды сдвигов могут изменять значения флагов CF, OF, PF, SF, ZF, а значение флага AF становится неопределенным. Команды циклических сдвигов изменяют только OF
и CF.
Команда логического И AND
AND <операнд1>, <операнд2>
Каждый бит результата выполнения команды AND устанавливается в 1, если оба соответствующих бита операндов равны 1, в противном случае он устанавливается в 0.
Команда логического сравнения TEST
TEST <операнд1>, <операнд2>
TEST выполняет над своими операндами поразрядную операцию конъюнкции (логическое И). Каждый бит результата устанавливается в 1, если оба соответствующих бита операндов равны 1, в противном случае – в 0. Результат операции игнорируется и отражается только путем модификации флагов.
79