如果 Mod R/M 字节只用于标识寄存器操作数,那么 Intel 指令编码就会相对简单。实际上,Intel 汇编语言有着各种各样的内存寻址模式,这就使得 Mod R/M 字节编码相当复杂。(指令集的复杂性是 RISC 设计支持者常见的批评理由。)
Mod R/M 字节正好可以指定 256 个不同组合的操作数。下表列岀了 Mod 00 时的 Mod R/M 字节(十六进制)。
字节 | AL | CL | DL | BL | AH | CH | DH | BH | ||
字 | AX | CX | DX | BX | SP | BP | SI | DI | ||
寄存器ID | 000 | 001 | 010 | 011 | 100 | 101 | 110 | 111 | ||
Mod | R/M | Mod R/M 值 | 有效地址 | |||||||
00 | 000 | 00 | 08 | 10 | 18 | 20 | 28 | 30 | 38 | [BX+SI] |
001 | 01 | 09 | 11 | 19 | 21 | 29 | 31 | 39 | [BX+DI] | |
010 | 02 | 0A | 12 | 1A | 22 | 2A | 32 | 3A | [BP+SI] | |
011 | 03 | 0B | 13 | 1B | 23 | 2B | 33 | 3B | [BP+DI] | |
100 | 04 | 0C | 14 | 1C | 24 | 2C | 34 | 3C | [SI] | |
101 | 05 | 0D | 15 | 1D | 25 | 2D | 35 | 3D | [DI] | |
110 | 06 | 0E | 16 | 1E | 26 | 2E | 36 | 3E | 16 位偏移量 | |
111 | 07 | 0F | 17 | 1F | 27 | 2F | 37 | 3F | [BX] |
Mod R/M 字节编码的作用如下:Mod 列中的两位指定寻址模式的集合。比如,Mod 00 有 8 种可能的 R/M 数值(000b〜111b),有效地址列给岀了这些数值标识的操作数类型。
假设想要编码 MOV AX, [Si], Mod 位为 00b, R/M 位为 100b。从《x86指令编码》一节中的 16 位 RM 表中可知 AX 的寄存器编号为 000b,因此完整的 Mod R/M 字节为 00 000 100b 或 04h:
mod | reg | r/m |
00 | 000 | 100 |
十六进制字节 04 在上表(Mod R/M)的 AX 列第 5 行。
MOV [SI], AL 的 Mod R/M 字节还是一样的(04h),因为寄存器 AL 的编号也是 000。现在对指令 MOV [SI], AL 进行编码。8 位寄存器的传送操作码为 88。Mod R/M 字节为 04h,则机器码为 88 04。
下表列出了 8 位和 16 位 MOV 指令所有的指令格式和操作码。
操作码 | 指令 | 说明 | 操作码 | 指令 | 说明 |
---|---|---|---|---|---|
88/r | MOV eb, rb | 字节寄存器送 EA 字节操作数 | 8E/2 | MOV SS, rw | 字寄存器送 SS |
89/r | MOV ew, rw | 字寄存器送 EA 字操作数 | 8E/3 | MOV DS, mw | 内存字送 DS |
8A/r | MOV rb, eb | EA 字节操作数送字节寄存器 | 8E/3 | MOV DS, rw | 字寄存器送 DS |
8B/r | MOV rw, ew | EA 字操作数送字寄存器 | A0 dw | MOV AL, xb | 字节变量(偏移量为 dw)送 AL |
8C/0 | MOV ew, ES | ES 送 EA 字操作数 | A1 dw | MOV AX, xw | 字变量(偏移量为 dw)送 AX |
8C/1 | MOV ew, CS | CS 送 EA 字操作数 | A2 dw | MOV xb, AL | AL 送字节变量(偏移量为 dw) |
8C/2 | MOV ew, SS | SS 送 EA 字操作数 | A3 dw | MOV xw, AX | AX 送字寄存器(偏移量为 dw) |
8C/3 | MOV ew, DS | DS 送 EA 字操作数 | B0+rb db | MOV rb, db | 字节立即数送字节寄存器 |
8E/0 | MOV ES, mw | 内存字送 ES | B8+rw dw | MOV rw, dw | 字立即数送字寄存器 |
8E/0 | MOV ES, rw | 字寄存器送 ES | C6 /0 db | MOV eb, db | 字节立即数送 EA 字节操作数 |
8E/2 | MOV SS, mw | 内存字送 SS | C7 /0 dw | MOV ew, dw | 字立即数送 EA 字操作数 |
下面两表给出了上表中缩写符号的补充信息。手动汇编 MOV 指令时可以用这些表作为参考。
/n: | 操作码后面跟一个 Mod R/M 字节,该字节后面可能再跟立即数和偏移量字段。数字 n( 0〜7 )为 Mod R/ M 字节中 reg 字段的值 |
/r: | 操作码后面跟一个 Mod R/M 字节,该字节后面可能再跟立即数和偏移量字段 |
db: | 操作码和 Mod R/M 字节后面跟一个字节立即操作数 |
dw: | 操作码和 Mod R/M 字节后面跟一个字立即操作数 |
+rb: | 8 位寄存器的编号(0〜7 ),与前面的十六进制字节一起构成 8 位操作码 |
+rw: | 16 位寄存器的编号(0〜7 ),与前面的十六进制字节一起构成 8 位操作码 |
db | -128〜+127 之间的有符号数。若操作数为字类型,则该数值进行符号扩展 |
dw | 指令操作数为字类型的立即数 |
eb | 字节类型操作数,可以是寄存器也可以是内存操作数 |
ew | 字类型操作数,可以是寄存器也可以是内存操作数 |
rb | 用数值(0〜7 )标识的 8 位寄存器 |
rw | 用数值(0〜7 )标识的 16 位寄存器 |
xb | 无基址或变址寄存器的简单字节内存变量 |
xw | 无基址或变址寄存器的简单字内存变量 |
下表列出了更多的 MOV 指令,这些指令能手动汇编,且可以与表中的机器代码比较。假设 myWord 的起始地址偏移量为 0102h。
指令 | 机器码 | 寻址模式 |
---|---|---|
mov ax, my Word | A1 02 01 | 直接(为 AX 优化) |
mov my Word,bx | 89 IE 02 01 | 直接 |
mov[di],bx | 89 ID | 变址 |
mov[bx+2],ax | 89 47 02 | 基址 - 偏移量 |
mov[bx+si],ax | 89 00 | 基址 - 变址 |
mov word prt [bx+di+2], 1234h | C7 41 02 34 12 | 基址 - 变址 - 偏移量 |