我有32位操作码:FF 35 0E 20 40 00
。有人知道一个好的OpCode表给出了答案吗? (我知道我可以使用反汇编程序,但我想知道,如何使用操作码表来确定它)。我找到了this网页,但FF
有7种不同的解决方案。我没有得到它。
答案 0 :(得分:15)
Appendix A Opcode Map
Vol 2B
的{{1}}表示Intel® 64 and IA-32 Architectures Software Developer’s Manual Combined Volumes: 1, 2A, 2B, 3A and 3B
为FF
INC/DEC Grp5
。
1A
的{{1}} Table A-6 Opcode Extensions for One- and Two-byte Opcodes by Group Number
Vol 2B
/ FF
Group 5
,INC
,DEC
,CALLN
},CALLF
,JMPN
,JMPF
,取决于PUSH
字节的第5位到第3位,后面的字节。 (0x35>> 3)& 7 = 6或110二进制。所以,这是ModR/M
。
PUSH Ev
的{p> Chapter 2 Instruction Format
解释了指令包含哪些部分,包括那些Vol 2A
个字节,哪些不是。
ModR/M
的{p> Appendix A Using Opcode Tables
告诉您Vol 2B
:
操作码后面有一个ModR / M字节并指定操作数。操作数是通用寄存器或存储器地址。如果是存储器地址,则从段寄存器和以下任何值计算地址:基址寄存器,索引寄存器,缩放因子,位移。
它还会告诉您E
:
字,双字或四字(在64位模式下),具体取决于操作数大小属性。
因此,您知道v
表示寄存器或内存操作数,因为这是针对32位代码而没有指令前缀,操作数大小为32位。所以,Ev
是32位寄存器或内存中的32位变量。
现在你需要从ModR / M中找出剩下的字节直到结束。
查看Ev
的{{1}}。它告诉你在Figure 2-1. Intel 64 and IA-32 Architectures Instruction Format
= 0x35:
Vol 2A
= 00(二进制)
ModR/M
= 110(二进制;我们之前提取了这3位)
Mod
= 101(二进制)
Reg
的{p> R/M
告诉您Table 2-2. 32-Bit Addressing Forms with the ModR/M Byte
= 00而Vol 2A
= 101表示Mod
,IOW,有一个由32-组成的内存操作数指令中的位移位。
R/M
字节的disp32
字段已用于选择七条指令中的一条,因此该字段不对寄存器操作数进行编码。
所以,你的指示是Reg
。
这与我的反汇编输出一致。
答案 1 :(得分:14)
让我们一次尝试一个字节的字节序列。
FF
。在英特尔指令集参考中的操作码映射中查找它告诉我们这是一个INC
或DEC
指令,以及密码“Grp 5 - 1A”。 1A表示“用作操作码扩展的ModR / M字节的第5位,第4位和第3位”。 ModR / M字节是编码源的字节和用于该指令的操作数的地址。在这种情况下,这三个位用于扩展操作码。35
。这是ModR / M字节,通常出现在操作码本身之后,在使用它的指令中。 35
(十六进制)是二进制的00110101
,因此第5位,第4位和第3位是110
。在操作码扩展表(表A-6)中查看这一点,我们可以看到这意味着这是一个PUSH d64 Ev
指令。 d64
脚注表示“在64位模式下,指令默认为64位操作数大小,不能编码32位操作数大小。”。这是PUSH
指令的预期。 Ev
是一个指定操作数编码的符号 - 最重要的是,它指出ModR / M字节跟在操作码本身之后。另一方面,v
表示操作数的大小取决于操作数大小属性。我们已经有了ModR / M字节,所以让我们对其进行解码(表2-2,假设此代码以32位模式运行):有效地址由disp32
指定,这意味着32位移应遵循ModR / M字节。指定寄存器的部分表示应该使用ESI
,但在这种情况下,该字段用于操作码扩展,因此它不用于表示寄存器源操作数。0E 20 40 00
,在解码为小端时,表示0x40200e
。这是将用于此指令的操作数的地址。总结一下,我们得到FF 35 0E 20 40 00
为PUSH DWORD [0x40200e]
,即它将推送从堆栈上的地址0x40200e
读取的32位值。