【问题标题】:operand generation of CALL instruction on x86-64 AMDx86-64 AMD 上 CALL 指令的操作数生成
【发布时间】:2012-02-24 21:48:16
【问题描述】:

以下是示例程序的objdump的输出,

080483b4 <display>:
 80483b4:       55                      push   %ebp
 80483b5:       89 e5                   mov    %esp,%ebp
 80483b7:       83 ec 18                sub    $0x18,%esp
 80483ba:       8b 45 0c                mov    0xc(%ebp),%eax
 80483bd:       89 44 24 04             mov    %eax,0x4(%esp)
 80483c1:       8d 45 fe                lea    0xfffffffe(%ebp),%eax
 80483c4:       89 04 24                mov    %eax,(%esp)
 80483c7:       e8 ec fe ff ff          call   80482b8 <strcpy@plt>
 80483cc:       8b 45 08                mov    0x8(%ebp),%eax
 80483cf:       89 44 24 04             mov    %eax,0x4(%esp)
 80483d3:       c7 04 24 f0 84 04 08    movl   $0x80484f0,(%esp)
 80483da:       e8 e9 fe ff ff          call   80482c8 <printf@plt>
 80483df:       c9                      leave
 80483e0:       c3                      ret

080483e1 <main>:
 80483e1:       8d 4c 24 04             lea    0x4(%esp),%ecx
 80483e5:       83 e4 f0                and    $0xfffffff0,%esp
 80483e8:       ff 71 fc                pushl  0xfffffffc(%ecx)
 80483eb:       55                      push   %ebp
 80483ec:       89 e5                   mov    %esp,%ebp
 80483ee:       51                      push   %ecx
 80483ef:       83 ec 24                sub    $0x24,%esp
 80483f2:       c7 44 24 04 f3 84 04    movl   $0x80484f3,0x4(%esp)
 80483f9:       08
 80483fa:       c7 04 24 0a 00 00 00    movl   $0xa,(%esp)
 8048401:       e8 ae ff ff ff          call   80483b4 <display>
 8048406:       b8 00 00 00 00          mov    $0x0,%eax
 804840b:       83 c4 24                add    $0x24,%esp
 804840e:       59                      pop    %ecx
 804840f:       5d                      pop    %ebp
 8048410:       8d 61 fc                lea    0xfffffffc(%ecx),%esp

我需要了解的是,主要我们在地址 - 8048401,调用 80483b4 看到以下内容,但是机器代码是 - e8 ae ff ff ff。我看到 CALL 指令是 E8 但函数 80483b4 的地址如何解码为 FFFFFFAE?我在谷歌上做了很多搜索,但它没有返回任何东西。谁能解释一下?

【问题讨论】:

    标签: linux assembly x86 machine-code


    【解决方案1】:

    E8 是“调用相对”的操作数,意味着目标地址是通过将操作数与下一条指令的地址相加来计算的。操作数为 0xFFFFFFAE,即负 0x52。 0x808406 - 0x52 是 0x80483b4。

    大多数反汇编程序有助于计算实际目标地址,而不仅仅是在操作数中提供相对地址。

    x86 ISA 的完整信息:http://www.intel.com/content/www/us/en/architecture-and-technology/64-ia-32-architectures-software-developer-vol-2a-manual.html

    【讨论】:

      【解决方案2】:

      有趣的问题。我看过Intel's documentationE8 操作码是CALL rel16/32。 0xfffffae 实际上是一个 32 位二进制补码有符号整数,等于十进制 -82;它是操作码及其操作数之后的字节的相对地址。

      如果你做数学,你可以看到它检查出来:

      0x8048406 - 82 = 0x80483b4

      这会将指令指针放在display 函数的开头。

      【讨论】:

      • 感谢您的 cmets。所以这仅适用于 NEAR 调用。 FAR 电话呢?从您的评论中,我了解到 NEAR 呼叫是 E8。 FAR也叫E8吗?另外,FAR 调用的操作数会是绝对地址吗??
      • @SamirBaid Far 电话是9a并采用绝对地址。还有ff 使用绝对间接地址做一些事情,但我不确定它们是如何工作的。在我链接的页面上查看组合卷集的第 716 页(即顶部)以获取更多详细信息。
      • @SamirBaid:远调用很少见,即使在 x86_64 上也是如此。库调用通常通过 PLT 完成,因此您需要一个大于 2 GiByte 的文本段才能实现。
      • 或者更简单地说,rel32next指令的开始,call之后的第一个字节开始计算。
      【解决方案3】:

      Near 调用通常是 IP 相关的——这意味着,“地址”实际上是指令指针的偏移量。在这种情况下,EIP 指向下一条指令(因此它的值为8048406)。将ffffffae(或-00000052 的补码)添加到它,你会得到80483b4

      请注意,所有这些数学运算都是 32 位的。您没有在此处执行任何 64 位操作(或者您的寄存器名称中将包含 Rs 而不是 Es,并且地址会更长)。

      【讨论】:

        猜你喜欢
        • 2011-01-03
        • 1970-01-01
        • 1970-01-01
        • 2019-06-13
        • 1970-01-01
        • 2019-01-03
        • 2014-08-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多