Alp*_*_Pi 0 assembly masm machine-code x86-16
在我可以找到的关于 MOV 助记符的操作码的所有文档中,每个操作码都没有单独记录。操作码B8h+
记录为将 16 位或 32 位数据移动到 16 位或 32 位注册表。究竟关注什么注册表,取决于B8h
操作码高出多远。也就是说,要获得B8h
类型为 MOV 指令的操作码,您需要B8h
将寄存器的编号相加。问题是,我没有找到有关每个注册表数量的任何信息。以下是我的猜测,但我不确定。
目的地登记处。操作码。
AX B8
CX B9
DX BA
BX BB
EAX BC
ECX BD
EDX BE
EBX BF
Run Code Online (Sandbox Code Playgroud)
您的表中有错误:16 位和 32 位操作数大小具有相同的操作码,并通过操作数大小前缀字节区分,以使用当前不是默认操作数大小的字节。(所以 16 位指令在 32 位和 64 位模式下需要一个额外的字节。)这适用于所有操作码,而不仅仅是mov
.
您可以自己使用汇编器和反汇编器进行检查,该反汇编器在输出中包含指令编码的十六进制字节。
对于大多数指令,8 和 16/32/64 有单独的操作码,但我想当从 16 位扩展到 32 位时,没有足够的操作码空间来添加另一个版本的所有内容。
mov r8, imm8
使用操作码B0+rb
(所以,B0-B7)。mov r16/32/64, imm16/32/64
使用操作码B8+rw/rd
(so,B8-BF),带有操作数大小前缀,带有 .W 位设置的 REX 前缀)或不带前缀。既然我们在讨论这个话题,值得一提的是mov r/m64, imm32
(sign-extended move-immediate) 必须使用一个额外的字节来编码目标寄存器或有效地址,但仍然比mov r64, imm64
. 在 AT&T 语法中,如果需要,您必须使用movabs
助记符,否则汇编程序会将您的常量截断为 32 位。
寄存器编号的实际二进制编码似乎在英特尔参考手册第 2 卷的三个地方指定。(链接自x86 wiki)。
与这个问题最相关(寄存器编码为操作码的最后 3 位),有表 3-1。与 +rb, +rw, +rd, +ro 相关的寄存器代码,在第 3.1 节:解释指令参考页中。
编码与附录 B.1.3 中的相同,它再次指出 3 位寄存器字段可以是操作码的最后 3 位。(我猜所有使用+rb
/的操作码+rd
都是 8 的倍数,所以添加 0-7 = 设置最后 3 位)。B.1.4.1 有表格,其中寄存器每个可能的 3 位值选择,用于 16 位和 32 位操作数大小(在非 64 位模式下)。
它是:
encoding | 8bit reg | 32bit reg
000 | AL | EAX
001 | CL | ECX
010 | DL | EDX
011 | BL | EBX
100 | AH | ESP
101 | CH | EBP
110 | DH | ESI
111 | BH | EDI
Run Code Online (Sandbox Code Playgroud)
其他操作数大小和 64 位模式的表就在附近。(带有 REX 前缀的指令通常不能寻址 AH/BH/CH/DH,只能寻址 16 个 GP 寄存器的低字节。我猜这是因为当与 REX 前缀ch
一起使用时bpl
,编码与 发生冲突。)
第 2 章中还有一个寄存器编码表(用于在 mod/rm 字段中使用),并附有表格。
在表之后的 64 位模式部分还提到将 dest 寄存器编码到操作码中。
第 2.2.1.1 章:编码(在 IA-32e 部分内):
Intel 64 和 IA-32 指令格式通过在编码中使用 3 位字段指定最多三个寄存器,具体取决于格式:
- ModR/M:ModR/M 字节的 reg 和 r/m 字段
- ModR/M with SIB:ModR/M字节的reg字段,SIB(scale,index,base)字节的base和index字段
- 不带 ModR/M 的指令:操作码的 reg 字段