【问题标题】:How to disassemble movb instruction如何反汇编movb指令
【发布时间】:2012-09-11 06:07:16
【问题描述】:

我正在编写一个反汇编程序,我正在检查指令格式(并手动进行一些反汇编),我遇到了一条我似乎无法解码的指令。

该特定指令(来自 objdump)的输出是:

c6 05 14 a0 04 08 01    movb   $0x1,0x804a014

但是,我不明白指令是如何解码的,因为操作码 c6 应该是 MOV Eb Ib (Mod R/M to imm8)。

有人可以告诉我它是如何解码的吗?

谢谢!

【问题讨论】:

  • 感谢您的回答!这3个真的很完整,我不想只选择一个,因为他们都回答了我的问题。

标签: assembly x86 disassembly objdump i386


【解决方案1】:

Alex Frunze 的回答(部分)解释了这一点,但他的回答有点简洁,所以我将在这里提供一些解释:

  1. 操作码为c6/0,表示指令有2个操作数。一个是 r/m 8,表示以 mod/rm 字节编码的操作数和立即操作数。两个操作数都是 8 位宽。
  2. 操作码中的 /0 表示操作码的一部分被编码在 mod/rm 字节中。 mod/rm 字节中的位 3-5 是操作码的一部分。当您有 c6 后跟一个 mod/rm 字节(其位 3-5 的值为 0)时,您将获得一个 mov 操作码。
  3. 值 5(紧跟 c6 的字节)对应于 r/m 字节 00 000 101(二进制)。
  4. r/m 字节的“后三位”(位 0-2)对应于 r/m 字段。 r/m 值为 101 (5) 表示“使用位移 dword”,因此 mod/rm 字节之后的接下来 4 个字节形成一个立即地址。
  5. 14 a0 04 08是0x0804a014的小端编码
  6. 最后一个字节 1 是要加载到地址中的立即值

我希望这会有所帮助。

【讨论】:

  • 非常感谢您的回答,我完全错过了表格中的条目(不知何故将其作为寄存器而不是 disp32 读取)。
【解决方案2】:

c6 - 操作码(Mod/RM 字节中也有一部分操作码,在 /digit(reg) 字段中)
05 - Mod/RM 字节(mod=00b, r/m=101b, /digit(reg)=0 - 操作码的一部分)
14 a0 04 08 - disp32
01 - imm8

这是一个从IbEbmov。您可能将 objdump 显示反汇编的 AT&T 语法与 Intel/AMD 文档的语法混淆了。 AT&T 语法中操作数的顺序与 x86 CPU 手册中的相反。

【讨论】:

  • 是的,我仍然经常混淆它们(使用不同引用的结果),很抱歉造成混淆。感谢您的回答。
【解决方案3】:

好吧,将 移动到 立即数并没有任何意义。该指令所做的是将常量 1 移入位于 0x804a014 的内存字节中。类似于等效的 C 代码:

*(unsigned char *)0x804a014 = 1;

如您所知,您的操作码为 c6。您可以在Volume 2A of the docs 中将其作为MOV 指令的一部分进行查找。

05 是 ModR/M 字节。您可以使用Table 2-2 of volume 2A,“使用 ModR/M 字节的 32 位寻址形式”来破译它。在图表的“ModR/M 字节值(十六进制)”部分中查找 05。从那里开始跟踪,您会看到此 ModR/M 值的有效地址以“disp32”形式给出。那里的脚注说“disp32 命名法表示 ModR/M 字节之后的 32 位位移”。在这种情况下,这是指令的下四个字节:14 a0 04 08

最后,你得到了 8 位立即数 01,完整的指令被解码。

【讨论】:

    猜你喜欢
    • 2011-12-29
    • 1970-01-01
    • 2011-08-06
    • 1970-01-01
    • 2013-02-06
    • 1970-01-01
    • 2011-04-28
    • 2014-12-31
    • 1970-01-01
    相关资源
    最近更新 更多