操作码FF350E204000有什么作用?

Nic*_* M. 3 x86 assembly opcode

我有32位操作码:FF 35 0E 20 40 00.有人知道一个好的OpCode表给出了答案吗?(我知道我可以使用反汇编程序,但我想知道,如何使用操作码表来确定它).我找到了这个网页,但有7个不同的解决方案FF.我没有得到它.

Ale*_*nze 15

你在找错了地方.您应该在英特尔或AMD的官方文档中查看此内容.

Appendix A Opcode MapVol 2BIntel® 64 and IA-32 Architectures Software Developer’s Manual Combined Volumes: 1, 2A, 2B, 3A and 3BFFINC/DEC Grp51A.

Table A-6 Opcode Extensions for One- and Two-byte Opcodes by Group NumberVol 2BFF/ Group 5任一的INC,DEC,CALLN,CALLF,JMPN,JMPF,PUSH,这取决于比特5通过的3 ModR/M字节,随后的字节.(0x35 >> 3)&7 = 6或110二进制.所以,这是PUSH Ev.

Chapter 2 Instruction FormatVol 2A解释了部分的指令需要,包括那些ModR/M字节,什么不是.

Appendix A Using Opcode TablesVol 2B告诉你E:

操作码后面有一个ModR/M字节并指定操作数.操作数是通用寄存器或存储器地址.如果它是存储器地址,则从段寄存器和以下任何值计算地址:基址寄存器,索引寄存器,缩放因子,位移.

它还告诉你v:

字,双字或四字(在64位模式下),具体取决于操作数大小属性.

因此,您知道这Ev意味着寄存器或内存操作数,因为这是针对32位代码而且没有指令前缀,操作数大小为32位.所以,Ev32位寄存器或内存中的32位变量.

现在你需要从ModR/M中找出剩下的字节直到结束.

看看Figure 2-1. Intel 64 and IA-32 Architectures Instruction FormatVol 2A.它告诉你in ModR/M= 0x35:

Mod= 00(二进制)
Reg= 110(二进制;我们之前提取了这3位)
R/M= 101(二进制)

Table 2-2. 32-Bit Addressing Forms with the ModR/M ByteVol 2A告诉你Mod= 00和R/M= 101手段disp32,IOW,有包括在指令中的32位位移的存储器操作数.

字节的Reg字段ModR/M已用于选择七个指令中的一个,因此该字段不编码寄存器操作数.

所以,你的指示是PUSH DWORD [0x0040200E].

这与我的反汇编输出一致.


Dan*_*zar 14

让我们一次尝试一个字节的字节序列.

  1. 第一个字节是FF.看它在操作码映射在Intel指令集告诉我们,这是一个INC或一个DEC指令,与cryptical一起"GRP 5 - 1A".1A表示"用作操作码扩展的ModR/M字节的第5位,第4位和第3位".ModR/M字节是编码源的字节和用于该指令的操作数的地址.在这种情况下,这三个位用于扩展操作码.
  2. 下一个字节是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应使用,但在这种情况下,这字段用于操作码扩展,所以它不用于表示寄存器源操作数.
  3. 接下来的四个字节是32位位移.0E 20 40 00,当解码为小端时,意味着0x40200e.这是将用于此指令的操作数的地址.

总而言之,我们得到的FF 35 0E 20 40 00PUSH DWORD [0x40200e],即它将推动从0x40200e堆栈上的地址读取的32位值.