当我们只知道操作码的十六进制时如何编码指令
How to encode an instruction when we just know the hex for opcode
在this source, they have given that hex for cmp r/m16/32 imm8 is 0x837. Somewhere i got that, hex for ebp is 0b0101. With this information, how can i encode the instruction cmp dword [ebp-4] 2
? I have been searching for this from a couple of hours and got no clues except for this(第61页)类似的指令cmpb [=11=]xf,(%rdi)
编码为80 3f 0f。但我无法理解这一点,因为我提到的前一个来源说 0x803 是给 sbb 的。另外 rdi 是 0b0111 而不是 0b1111(实际上是 r15)。我很困惑...如果可能的话,我想要 x86-32 和 x86-64 的编码指令。
查阅官方 Intel® 64 和 IA-32 架构软件开发人员手册第 2 卷:指令集参考,A-Z,在 Intel's website 上提供多种格式。翻到关于CMP
的页面,找到CMP r/m32, imm8
那一行。这将操作码列作为 83 /7 ib
。转向
Table 2-2。具有 ModR/M 字节 的 32 位寻址形式。选择 [ebp]+disp8
行和 /digit 7
列。该单元格告诉您 ModR/M 字节是 7d
。您需要附加 -4
的位移,即 8 位有符号的 fc
和您的直接操作数。因此,完整的指令是 83 7d fc 02
。在 64 位模式下,如果您使用 rbp
,编码是相同的。如果要保留 ebp
,则需要使用 67
.
的地址大小覆盖前缀
除非您已经知道 x86 指令编码的工作原理,否则您链接的文档不是很有用。因此,让我们尝试另一个。在 this resource 之后,我们得到以下候选编码:
81 /7 iw CMP r/m16,imm16 Compare imm16 with r/m16.
81 /7 id CMP r/m32,imm32 Compare imm32 with r/m32.
83 /7 ib CMP r/m16,imm8 Compare imm8 with r/m16.
83 /7 ib CMP r/m32,imm8 Compare imm8 with r/m32.
这里要注意的一件事是,word 和 dword 运算使用相同的编码。这不是一个错误:操作数大小由当前代码段的默认操作数宽度(即我们是 运行 在 16、32 还是 64 位模式下决定)和 66
或REX.W
操作数大小覆盖前缀。规则很简单:
- 在16位模式下,默认操作数大小为16位
- 在 32 位和 64 位模式下,默认操作数大小为 32 位
66
前缀在 16 位和 32 位操作数大小之间切换
- 在 64 位模式下,
REX.W
前缀切换到 64 位操作数大小
因此在 32 位或 64 位模式下编程时,不需要前缀,因为默认操作数大小已经是我们想要的。
现在的问题是使用83
还是81
。在这种情况下,两者都可以使用,因为我们的立即数适合带符号的 8 位。我们将继续使用 83
操作码,因为编码更短。
编码83 /7 ib
告诉我们操作码是83
后跟一个modr/m字节reg = 7(其他字段编码r/m32操作数)后跟通过 8 位立即数。
r/m32 操作数 [ebp-4]
可以在您链接的参考文献中给出的 modr/m 字节 table 中查找。我们有一个带索引寻址模式的内存操作数;索引 ebp
和位移 -4
。位移适合 8 位有符号位,因此我们使用 table 中的 [ebp+disp8]
条目并在 modr/m 字节的 7d
处结束。接下来是位移字节,0xfc
for −4 in two's complement.
将它们放在一起我们得到 83 7d fc 02
作为 cmp dword ptr [ebp-4], 2
的编码:
83 opcode
7d modr/m byte: reg = 7, r/m = [ebp+disp8]
fc displacement: -4
02 immediate: 2
值得注意的是,32 位和 64 位模式的编码相同。对于 16 位模式,需要额外的 66
和 67
前缀来 select 32 位操作数和地址大小,给出 66 67 83 7d fc 02
.
在this source, they have given that hex for cmp r/m16/32 imm8 is 0x837. Somewhere i got that, hex for ebp is 0b0101. With this information, how can i encode the instruction cmp dword [ebp-4] 2
? I have been searching for this from a couple of hours and got no clues except for this(第61页)类似的指令cmpb [=11=]xf,(%rdi)
编码为80 3f 0f。但我无法理解这一点,因为我提到的前一个来源说 0x803 是给 sbb 的。另外 rdi 是 0b0111 而不是 0b1111(实际上是 r15)。我很困惑...如果可能的话,我想要 x86-32 和 x86-64 的编码指令。
查阅官方 Intel® 64 和 IA-32 架构软件开发人员手册第 2 卷:指令集参考,A-Z,在 Intel's website 上提供多种格式。翻到关于CMP
的页面,找到CMP r/m32, imm8
那一行。这将操作码列作为 83 /7 ib
。转向
Table 2-2。具有 ModR/M 字节 的 32 位寻址形式。选择 [ebp]+disp8
行和 /digit 7
列。该单元格告诉您 ModR/M 字节是 7d
。您需要附加 -4
的位移,即 8 位有符号的 fc
和您的直接操作数。因此,完整的指令是 83 7d fc 02
。在 64 位模式下,如果您使用 rbp
,编码是相同的。如果要保留 ebp
,则需要使用 67
.
除非您已经知道 x86 指令编码的工作原理,否则您链接的文档不是很有用。因此,让我们尝试另一个。在 this resource 之后,我们得到以下候选编码:
81 /7 iw CMP r/m16,imm16 Compare imm16 with r/m16.
81 /7 id CMP r/m32,imm32 Compare imm32 with r/m32.
83 /7 ib CMP r/m16,imm8 Compare imm8 with r/m16.
83 /7 ib CMP r/m32,imm8 Compare imm8 with r/m32.
这里要注意的一件事是,word 和 dword 运算使用相同的编码。这不是一个错误:操作数大小由当前代码段的默认操作数宽度(即我们是 运行 在 16、32 还是 64 位模式下决定)和 66
或REX.W
操作数大小覆盖前缀。规则很简单:
- 在16位模式下,默认操作数大小为16位
- 在 32 位和 64 位模式下,默认操作数大小为 32 位
66
前缀在 16 位和 32 位操作数大小之间切换- 在 64 位模式下,
REX.W
前缀切换到 64 位操作数大小
因此在 32 位或 64 位模式下编程时,不需要前缀,因为默认操作数大小已经是我们想要的。
现在的问题是使用83
还是81
。在这种情况下,两者都可以使用,因为我们的立即数适合带符号的 8 位。我们将继续使用 83
操作码,因为编码更短。
编码83 /7 ib
告诉我们操作码是83
后跟一个modr/m字节reg = 7(其他字段编码r/m32操作数)后跟通过 8 位立即数。
r/m32 操作数 [ebp-4]
可以在您链接的参考文献中给出的 modr/m 字节 table 中查找。我们有一个带索引寻址模式的内存操作数;索引 ebp
和位移 -4
。位移适合 8 位有符号位,因此我们使用 table 中的 [ebp+disp8]
条目并在 modr/m 字节的 7d
处结束。接下来是位移字节,0xfc
for −4 in two's complement.
将它们放在一起我们得到 83 7d fc 02
作为 cmp dword ptr [ebp-4], 2
的编码:
83 opcode
7d modr/m byte: reg = 7, r/m = [ebp+disp8]
fc displacement: -4
02 immediate: 2
值得注意的是,32 位和 64 位模式的编码相同。对于 16 位模式,需要额外的 66
和 67
前缀来 select 32 位操作数和地址大小,给出 66 67 83 7d fc 02
.