高地址 ------------------------- return address (to caller of main) ------------------------- saved rbp ------------------------- ← rbp (main) x (-0x8) y (-0xc) z (-0x10) padding ------------------------- ← rsp 低地址
执行 call 后:
1 2 3 4 5 6 7 8 9 10 11
高地址 ------------------------- return address to main caller ------------------------- saved rbp (main) ------------------------- ← rbp(main) local variables ------------------------- return address (0x100003fa8) ← rsp ------------------------- 低地址
八、add 函数栈帧
add 的 prologue:
1 2 3
pushq %rbp movq %rsp, %rbp movl %edi, -0x4(%rbp)
这里 没有 sub rsp。
该版本编译器没有显式为 add 分配额外栈空间。
本例中 add 为 leaf function。虽然未显式 sub rsp 分配空间,但由于使用了 push %rbp,局部变量仍然位于当前栈帧中,并未实际使用 red zone。 在 macOS / Linux 的 System V ABI 下:
栈顶以下 128 字节称为 red zone,可在 leaf function 中使用。
所以 add 是一个 leaf function:
没有再调用其他函数
不需要保持 16-byte 对齐给下一级
编译器优化掉 sub rsp
栈变为:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
高地址 -------------------------------- main 的局部变量 -------------------------------- saved rbp (main) -------------------------------- return addr → main caller -------------------------------- return addr → main ← 8(%rbp_add) saved rbp (main) ← 0(%rbp_add) -------------------------------- ← rbp(add) local a copy local b copy local c -------------------------------- ← rsp 低地址
注意: 每次函数调用都会:
保存调用者 rbp
建立新的栈帧
形成一条链。
本例中 add 为 leaf function,未显式执行 sub rsp。 在 System V ABI 下允许使用 128 字节 red zone,因此编译器可省略栈空间分配。