8

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

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)

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

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

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

4

1 回答 1

13

是的,它是一个参数。Linux 使用的ABI将最多 6 个“INTEGER”(<= 64 位整数,或指针)类型参数分配给寄存器,以明显且易于记忆的顺序%rdi, %rsi, %rdx, %rcx, %r8, %r9.

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

所以代码将第三个参数存储在堆栈帧的底部附近。

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

于 2010-09-23T18:19:13.500 回答