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 字段
| 归档时间: |
|
| 查看次数: |
1759 次 |
| 最近记录: |