在this源代码中,他们给出了cmp r/m16/32 imm 8的十六进制值为0x 837。我在某个地方找到了,ebp的十六进制是0 b 0101。有了这些信息,我该如何对指令cmp dword [ebp-4] 2
进行编码?我一直在寻找这个从几个小时,并没有得到任何线索,除了this(第61页)类似的指令cmpb $0xf,(%rdi)
编码为80 3f 0 f。但我无法理解这一点,因为我提到的前一个来源说,0x 803是为sbb。另外,rdi是0 b 0111,而不是0 b1111(实际上是r15)。我有点糊涂了...如果可能的话,我想要x86-32和x86-64的编码指令。
2条答案
按热度按时间cld4siwp1#
除非您已经知道x86指令编码是如何工作的,否则您所链接的文档不是很有用。我们换一个。在this resource(从英特尔官方PDF手册中抓取1)之后,我们得到以下候选编码:
字符串
这里需要注意的一点是,word和dword操作的编码相同。这不是一个错误:操作数大小由当前代码段的默认操作数宽度(即,无论我们是在16位、32位还是64位模式下运行)以及存在
66
或REX.W
操作数大小覆盖前缀。规则很简单:66
前缀在16和32位操作数大小之间切换REX.W
前缀切换到64位操作数大小因此,当在32或64位模式下编程时,不需要前缀,因为默认操作数大小已经是我们想要的大小。
现在的问题是使用
83
还是81
。在这种情况下,两者都可以使用,因为我们的立即数适合8位签名。我们将继续使用83
操作码,因为编码更短。编码
83 /7 ib
告诉我们,操作码是83
,后面是reg = 7的modr/m字节(其他字段编码r/m32操作数),后面是8位立即数。r/m32操作数
[ebp-4]
可以在链接的参考中给出的modr/m字节表中查找。我们有一个带索引寻址模式的内存操作数;指数ebp
和位移-4
。位移适合8位有符号,因此我们使用表中的[ebp+disp8]
条目,并最终在7d
处为modr/m字节。接下来是位移字节0xfc
,表示2的补码中的−4。把所有这些放在一起,我们得到
83 7d fc 02
作为cmp dword ptr [ebp-4], 2
的编码:型
值得注意的是,对于32位和64位模式,编码是相同的。对于16位模式,需要额外的
66
和67
前缀来选择32位操作数和地址大小,即66 67 83 7d fc 02
。脚注1:在英特尔软件开发人员手册(SDM)中,指令的操作数大小属性在第1卷第1章中描述。3.6,
66h
前缀用于选择模式的非默认值,在第2卷ch中描述。2.1.1组3.其他编码细节主要在第2卷手册中。像https://www.felixcloutier.com/x86/和https://c9x.me/x86/这样的网站是从英特尔的vol.2 PDF中抓取的,但只包括每条指令的条目,而不是告诉你适用于每条指令的基础知识的介绍,或者如何阅读条目的细节。How to read the Intel Opcode notation
disho6za2#
请参阅官方 * 英特尔® 64和IA-32体系结构软件开发人员手册第2卷:指令集参考,A-Z*,在Intel's website上以多种格式提供。翻到关于
CMP
的那一页,找到有CMP r/m32, imm8
的那一行。这给出了操作码列为83 /7 ib
。翻到 * 表2-2。32位寻址形式,带ModR/M字节 *。选择[ebp]+disp8
行和/digit 7
列。单元格告诉您ModR/M字节是7d
。您需要附加-4
的位移,即8位有符号的fc
和立即操作数。因此,完整的指令是83 7d fc 02
。在64位模式下,如果使用rbp
,编码是相同的。如果您想保留ebp
,则需要使用地址大小覆盖前缀67
。