【问题标题】:Trouble understanding an x86-64 function preamble无法理解 x86-64 函数序言
【发布时间】:2011-04-16 07:30:27
【问题描述】:

我遇到了崩溃,在调查时我发现自己完全被以下代码阻止:

0000000000000a00 <_IO_vfprintf>:
a00:       55                      push   %rbp
a01:       48 89 e5                mov    %rsp,%rbp
a04:       41 57                   push   %r15
a06:       41 56                   push   %r14
a08:       41 55                   push   %r13
a0a:       41 54                   push   %r12
a0c:       53                      push   %rbx
a0d:       48 81 ec 48 06 00 00    sub    $0x648,%rsp
a14:       48 89 95 98 f9 ff ff    mov    %rdx,0xfffffffffffff998(%rbp)

这是通过在 64 位 Linux x86 系统上运行 objdump --disassemble /usr/lib64/libc.a 生成的,然后搜索输出。这是AT&T syntax,所以目的地在右边。

具体来说,我不明白最后一条指令。在函数触及该寄存器之前,它似乎正在将rdx 寄存器的值写入堆栈某处(很远,很远)的内存中。对我来说,这没有任何意义。

我尝试阅读调用约定,现在我最好的理论是rdx 用于参数,因此代码基本上是直接“返回”参数值。这不是函数的结束,所以它当然没有真正返回。

【问题讨论】:

标签: linux assembly x86-64 calling-convention


【解决方案1】:

是的,它是一个参数。 ABI used by Linux 将最多 6 个“INTEGER”(%rdi、%rsi%rdx、@ 987654325@, %r8, %r9.

堆栈帧为 1648 字节(sub $0x648,%rsp 声称为 1608 字节,加上之前已推送 5 个 64 位寄存器),0xfffffffffffff998 为 -1640。

因此代码将第三个参数存储在堆栈框架底部附近。

(注意:Windows 64 位 ABI 与 Linux 不同。)

【讨论】:

  • 太棒了,谢谢。我真的应该花一些时间(5 到 10 年左右)重新回到汇编编程的状态。
  • 如果默认情况下将0xfffffffffffff998 渲染为-1640 会很好。这将更容易理解,并且不依赖于 64 位地址空间。
猜你喜欢
  • 2020-12-06
  • 1970-01-01
  • 1970-01-01
  • 2012-02-10
  • 1970-01-01
  • 2021-12-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多