若要完全理解汇编语言操作码和操作数,就需要花些时间了解汇编指令翻译成机器语言的方法。由于 Intel 指令集使用了丰富多样的指令和寻址模式,因此这个问题相当复杂。
Intel 8086 处理器是第一个使用复杂指令集计算机(Complex Instruction Set Computer, CISC)设计的处理器。这种指令集中包含了各种各样的内存寻址、移位、算术运算、数据传送和逻辑操作。
与 RISC(精简指令集计算机,Reduced Instruction Set Computer)指令相比,Intel 指令在编码和解码方面有些复杂。
指令编码(encode)是指将汇编语言指令及其操作数转换为机器码。指令解码(decode)是指将机器指令转换为汇编语言。对 Intel 指令编码和解码的逐步解释至少将有助于唤起对 MASM 作者们辛苦工作的理解和欣赏。
一般的 x86 机器指令格式,如下图所示。包含了一个指令前缀字节、操作码、Mod R/M 字节、伸缩索引字节(SIB)、地址位移和立即数。
指令按小端顺序存放,因此前缀字节位于指令的起始地址。每条指令都有一个操作码,而其他字段则是可选的。少数指令包含了全部字段,平均来看,绝大多数指令都有 2 个或 3 个字节。
下面是对指令字段的简介:
1) 指令前缀覆盖默认操作数大小。
2) 操作码(操作代码)指定指令的特定变体。比如,按照使用的参数类型,指令 ADD 有 9 种不同的操作码。
3) Mod R/M 字段指定寻址模式和操作数。符号 “R/M” 代表的是寄存器和模式。下表列出了 Mod 字段。
Mod | 位移 |
---|---|
00 | DISP=0,位移低半部分和高半部分都无定义(除非r/m = 110) |
01 | DISP= 位移低半部分符号扩展到 16 位,位移高半部分无定义 |
10 | DISP= 位移高半部分和低半部分都有效 |
11 | R/M 字段包含的是寄存器编号 |
下表给出了当 Mod=10b 时 16 位应用程序的 R/M 字段。
R/M | 有效地址 | R/M | 有效地址 |
---|---|---|---|
000 | [BX+SIJ+D16 | 100 | [SI]+D16 |
001 | [BX+DI]+D16 | 101 | [DI]+D16 |
010 | [BP+SI]+D16 | 110 | [BP]+D16 |
011 | [BP+DIJ+D16 | 111 | [BX]+D16 |
4) 伸缩索引字节(scale index byte, SIB)用于计算数组索引偏移量。
5) 地址位移字段保存了操作数的偏移量,在基址-偏移量或基址-变址-偏移量寻址模式中,该字段还可以与基址或变址寄存器相加。
6) 立即数字段保存了常量操作数。