为何x86汇编中函数调用的第一个参数对应rbp-4而非rbp+4?
函数栈帧参数地址疑问解答
示例代码
C++ 实现
int square(int num, int i2) { return num * num; }
对应汇编代码
square(int, int): push rbp mov rbp, rsp mov DWORD PTR [rbp-4], edi mov DWORD PTR [rbp-8], esi mov eax, DWORD PTR [rbp-4] imul eax, eax pop rbp ret
问题解释
你疑惑的核心原因在于这段汇编采用了x86-64架构的System V调用约定,参数并非一开始就存在栈上,而是先通过寄存器传递,之后被拷贝到当前函数的局部栈帧里。
你之前了解的「参数→返回地址→旧ebp」是32位x86传统调用约定(比如cdecl)的栈布局,这种场景下参数会被调用者压入栈,函数内访问参数时确实会用rbp+4、rbp+8这类偏移(因为旧ebp在rbp位置,上方是返回地址和参数,栈向低地址增长,所以参数在高地址侧)。
但在64位的System V调用约定中,前6个整数/指针参数是通过寄存器传递的:第一个参数存在rdi,第二个在rsi,以此类推。这段汇编里的mov DWORD PTR [rbp-4], edi就是把第一个参数从edi寄存器里复制到当前函数栈帧的局部变量区域——rbp是当前栈帧的基址,栈向低地址增长,所以局部变量区域在rbp的下方,用rbp-4、rbp-8这样的偏移。
简单说,你看到的rbp-4不是原参数的地址,而是参数值被拷贝后存在当前函数局部栈里的地址,原参数根本没在栈上(而是一开始在寄存器里)。
内容的提问来源于stack exchange,提问作者helianthus
相关产品推荐
相关产品推荐

