Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Arkhitektura_EVM_uchebnoe_posobie

.pdf
Скачиваний:
54
Добавлен:
13.04.2015
Размер:
2 Mб
Скачать

Непосредственная адресация применяется, когда операнд длиной в байт или слово находится в ассемблерной команде:

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