拆解'faddl'指令

时间:2011-11-15 05:39:32

标签: x86 disassembly opcode instruction-set x87

在我为x86平台上的32位Linux编写反汇编程序的尝试中,我遇到了一个问题。当我使用objdump反汇编一个简单的ELF-32可执行文件时,我看到了以下操作码序列:

dc 82 04 08 0d 00     faddl  0xd0804(%edx)

但是当我查看Intel manual时,我没有看到与此对应的操作码。 fadd指令以0xDC开头,但是它需要一个m64fp操作数,即“内存中的内存四字操作数”。

现在,这是否意味着操作数是64位地址(这意味着fadd指令是64位指令,但不以REX字节为前缀),或者是只是一个32位地址,指向一个四字(64位)?

我在这里遗漏了一些微不足道的东西,还是我对编码x86指令的理解错了?

2 个答案:

答案 0 :(得分:5)

让我们打破这一点。

> dc 82 04 08 0d 00     faddl  0xd0804(%edx)
  |  |  \____ ____/
  |  |       V
  |  |       |
  |  |       +---------> 32-bit displacement
  |  +-----------------> ModRM byte
  +--------------------> Opcode

详细查看文档,dc确实是以m64real浮点参数作为源。它会将此64位参数添加到ST(0)浮点寄存器。

但是,第二个字节82决定了64位值的来源。这转换为:

的二进制ModRM字节
+---+---+---+---+---+---+---+---+
| 1 | 0 | 0 | 0 | 0 | 0 | 1 | 0 |
+---+---+---+---+---+---+---+---+
|  MOD  |  REG/OPCD |    R/M    |

如果查看链接文档中的表2.2(32位寻址模式的表),您会看到这会转换为disp32[EDX]

换句话说,它需要接下来的32位(四个字节),将其添加到edx寄存器并使用该地址从内存中提取64位值。

答案 1 :(得分:2)

“内存中的四字操作数”表示该值在RAM中占用64位。地址大小取决于它是编译为32位还是64位进程,而不是编译器操作数的大小。以下是拆卸的完整细分。

  • 第一个字节DC是操作码。结合下一个字节不在C0和C7之间,并且在寄存器字段(第3-5位)中包含0的事实,这表示具有64位存储器操作数的fadd指令。有趣的是,操作码末尾的l表示32位操作数。它应该是faddq

  • 第二个字节包含3个字段。

    • 第6-7位表示最后一个字段的模式。
    • 第3-5位是寄存器字段。由于该指令不需要寄存器操作数,因此它们用作操作码的一部分。
    • 位0-2是R / M字段。它可以保存寄存器或指定内存操作数。组合模式10和R / M 010表示操作数是一个内存操作数,相对于edx寄存器具有32位地址。
  • 最后4个字节是小端(最低有效字节优先)中操作数的相对偏移量。