logo
Методичка

2.3.5 Команды с регистровыми операндами

В командах, в которых используются только регистровые операнды, значение байта Mod R/M определяет имена регистров, как показано в таблице 2.8. Значение нулевого бита байта кода операции определяет, какие регистры (8- или 16-разрядные) используются в команде. Если бит равен 1, используются 16-разрядные регистры, а если 0, то 8-разрядные.

Таблица 2.8. Кодирование регистров в поле Mod R/M

R/M

Регистр

R/M

Регистр

000

AX или AL

100

SP или AH

001

CX или CL

101

BP или CH

010

DX или DL

110

SI или DH

011

BX или BL

111

DI или BH

В качестве примера давайте выполним ассемблирование команды PUSH CX. Машинный код команды, помещающей в стек 16-разрядный регистр, выглядит так: 50h + rw, где rw обозначает код регистра (число 0—7), который добавляется к базовому коду операции 50h. Поскольку код регистра СХ равен 1, машинный код команды PUSH СХ равен 51h.

Ассемблирование других регистровых команд, особенно тех, у которых 2 операнда, выполняется чуть сложнее. Например, машинный код команды MOV АХ, ВХ равен 89D8. В системе команд процессоров Intel команда MOV, пересылающая 16-разрядный операнд из регистра в другой регистр или память, кодируется как 89h /r, где /r означает, что за байтом кода операции следует байт Mod R/M. Он состоит из трех полей: mod, reg и r/m. Например, в таблице 2.9 показана расшифровка полей байта Mod R/M, равного D8.

Табл. 2.9. Расшифровка полей байта mod r/m

mod

reg

r/m

11

011

000

В таблице 2.10 показано несколько примеров команд, в которых используются 8- и 16-разрядные регистровые операнды.

Табл. 2.10. Примеры кодирования команд mov с регистровыми операндами

Команда

opcode

mod

reg

r/m

mov ax, dx

8B

11

000

010

mov al, dl

8A

11

000

010

mov cx, dx

8B

11

001

010

mov cl, dl

8A

11

001

010

2.3.6 Префикс изменения размера операнда в процессорах IA-32

В машинном коде, сгенерированном для процессоров семейства IA‑32, приходится часто использовать префикс размера операнда (66h), который изменяет принятые по умолчанию размеры операндов текущей команды. Чтобы изучить как он работает, давайте попытаемся выполнить ассемблирование приведенной в таблице 2.10 последовательности команд с помощью компилятора MASM. В начале фрагмента поместим директиву выбора типа процессора .286, чтобы компилятор гарантированно не использовал в командах 32-разрядные регистры. Рядом с каждой командой MOV приведен ее машинный код:

.model small

.286

.stack 100h

.code

main PROC

mov ax, dx ; 8В С2

mov al, dl ; 8A C2

mov cx, dx ; 8B CA

mov cl, dl ; 8A CA

А теперь выполним ассемблирование той же последовательности команд MOV, для случая 32‑битных операндов. В первой команде mov eax, edx префикс изменения размера операнда не требуется, тогда как во второй mov ax, dx – он просто необходим:

.model small

.386

.stack 100h

.code

main PROC

mov eax, edx ; 8В С2

mov ax, dx ; 66 8В С2

mov al, dl ; 8A C2

mov ecx, edx ; 8B CA

mov cx, dx ; 66 8B CA

mov cl, dl ; 8A CA

Обратите внимание, что при использовании 8-разрядных операндов префикс изменения размера не требуется. И, наконец, хочется отметить, что машинный код нашего примера, генерируемый компилятором, одинаков как для реального режима адресации, так и для защищенного.