指令前缀:
分为4组,每个前缀最多一个字节,一条指令最多4个前缀。
- 第1组锁与重复(Lock and repeat)
锁(LOCK)编码为:F0H。用于互斥访问共享内存的操作。
非零时重复(REPNE/REPNZ)编码为:F2H。用于字符串操作指令。
为零时重复(REP/REPE/REPZ)编码为:F3H。用于字符串操作指令。 - 第2组段覆盖与分支提示
段覆盖(Segment override):CS、SS、DS、ES、FS、GS的段覆盖前缀的编码分别是2EH、36H、3EH、26H、64H、65H(在分支指令中使用未定义)。
分支提示(Branch hints),只用于条件分支指令Jcc。提示分支不发生编码为2EH;提示分支发生编码为3EH。 - 第3组操作数长度覆盖(Operand-size override)编码为66H。用于在16位与32位操作数切换。例如,指令MOV ax, 1234H对应的十六机制机器码是"66 B8 34 12"(66即是操作数长度覆盖前缀)
- 第4组地址长度覆盖(Address-size override)编码为67H。用于在16位与32位地址切换。例如,指令MOV eax, [si]对应的十六进制机器码是"67 8B 04"(67即使地址长度覆盖前缀)
REX前缀:
REX前缀是64位模式下使用的指令前缀字节,如下作用:
- 指定GPRs和SSE寄存器
- 指定64位操作数大小
- 指定扩展控制寄存器
并非所有指令在64位模式下都需要REX前缀。只有当指令引用扩展寄存器之一或使用64位操作数时,才需要前缀。如果REX前缀在没有任何意义的情况下使用,则会忽略它。每条指令只允许一个REX前缀。如果使用,REX前缀字节必须紧挨着操作码字节或转义操作码字节(0FH)。当REX前缀与包含强制前缀的指令一起使用时,强制前缀必须出现在REX之前,这样REX前缀就可以直接位于操作码或转义字节的前面。例如,带有REX前缀的CVTDQ2PD应该将REX放在F3和0F E6之间。其他位置被忽略。15字节的指令大小限制仍然适用于带有REX前缀的指令。
操作码(OPCode):
一个主操作码的长度可以是1、2或3个字节。一个额外的3位操作码字段有时被编码在ModR/M字节中。更小的字段可以在主操作码中定义。这些字段定义了操作方向、位移大小、寄存器编码、条件代码或符号扩展。一个操作码所使用的编码字段 操作码使用的编码字段根据操作的类别而不同。
ModR/M 和 SIB 字节:
许多在内存中引用操作数的指令在主操作码后面都有一个寻址形式的说明符字节(称为ModR/M字节)。ModR/M字节包含三个字段的信息:
- mod字段与r/m字段结合形成32个可能的值:8个寄存器和24个寻址模式。
- reg/opcode字段指定了一个寄存器编号或另外三个比特的操作码信息。reg/opcode字段的目的是在主操作码中指定的。
- r/m字段可以将寄存器指定为操作数,也可以将其与mod字段组合起来对寻址模式进行编码。有时,mod字段和r/m字段的某些组合用于表示某些指令的操作码信息
某些编码的ModR/M字节需要第二个寻址字节(SIB字节)。32位寻址的基数加索引和比例加索引形式需要SIB字节。SIB字节包括以下字段:
- scale字段指定缩放因子。
- index字段指定索引寄存器的寄存器号。
- base字段指定基寄存器的寄存器号
偏移和立即数字节:
有些寻址形式包括紧跟在ModR/M字节后面的位移(如果有的话,也可以是SIB字节)。如果需要一个位移,它可以是1、2或4个字节。
如果指令指定了立即操作数,则操作数总是紧跟在任何偏移字节之后。立即操作数可以是1、2或4个字节。
其他
- 指令大小限制为不大于15字节。
- 在64位模式下,使用RAX/RCX/RDX/RBX/RSP/RBP/RSI/RDI不需要REX Prefix,而使用R8 ~ R15则是必须的
- 在Intel 64位架构指令集中的REX前缀(4xH)可以改变两类指令的长度:MOV指令的位移量和MOV指令的立即数。
- Intel保护模式(子模式:虚拟8086模式)
- 实地址模式
- 系统管理模式
- IA-32e模式(子模式:兼容模式、64位模式)
- 平坦内存模型
- 分段内存模型
- 实模式内存模型
平坦内存 | 分段内存 | 实模式内存 | |
Intel保护模式 | Y | Y | Y |
实地址模式 | N | N | Y |
系统管理模式 | N | N | Y |
兼容模式 | Y | Y | Y |
64位模式 | Y | N | N |
操作数
源操作数:
- 立即数
- 寄存器
- 内存地址
- I/O 端口
目的操作数:
- 寄存器
- 内存地址
- I/O 端口
立即数:
MOV RAX,1122334455667788H
寄存器:
32位寄存器
64位寄存器
内存地址(内存有效地址):
Intel语法形式为 segreg:[base index*scale disp],而AT&T语法形式为 %segreg:disp(?se,%index,scale)