无法理解x86-64函数前导码

unw*_*ind 8 linux assembly x86-64 calling-convention

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

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)
Run Code Online (Sandbox Code Playgroud)

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

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

我试着阅读调用约定,现在我最好的理论rdx是用于参数,所以代码基本上是"返回"参数值.这不是功能的结束,当然,它并没有真正回归.

Mat*_*ery 12

是的,这是一个参数.的Linux使用ABI分配到6"INTEGER"(<= 64位整数,或指针)类型参数的寄存器,在明显和容易记住的顺序%rdi,%rsi,%rdx,%rcx,%r8,%r9.

堆栈帧是1648字节(sub $0x648,%rsp声称1608字节,在此之前已经推送了5个64位寄存器),并且0xfffffffffffff998是-1640.

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

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