在 Linux 下进行反汇编(如用 objdump、gdb、IDA、radare2 等)时,“看栈帧”本质上就是理解函数调用时栈是怎么布局的,以及当前指令如何使用 %rsp/%rbp(x86-64)或 %esp/%ebp(x86-32)。下面按实用角度讲。
栈帧(stack frame)通常包含:
%rbp在 x86-64 上常见布局:
高地址
| 调用者栈帧 |
| 参数(n) |
| 返回地址 | <- %rsp 在 call 后指向这里
| 旧 %rbp | <- 被 callee 压入
| 局部变量 | <- %rbp - 0x8 等
低地址
push %rbp
mov %rsp,%rbp
sub $0x20,%rsp
含义:
%rbp此时:
%rbp:当前函数栈帧基址%rbp+8:返回地址%rbp+16:第 1 个栈上传参%rbp-8 等:局部变量mov -0x4(%rbp),%eax
说明:
%rbp-4lea -0x20(%rbp),%rdi
说明:
mov %rdi,-0x8(%rbp)
说明:
若参数多:
mov 0x10(%rbp),%rax
说明:
gdb ./a.out
(gdb) disas main
(gdb) b main
(gdb) run
info registers rsp rbp rip
x/10gx $rsp
x/20x $rsp
bt
frame 0
info frame
stepi
x/10x $rsp
%rbp 的栈帧(优化代码)编译器常省略:
sub $0x18,%rsp
此时:
push %rbp%rsp 偏移例如:
mov %edi,0xc(%rsp)
看这种代码要:
%rspsub $N,%rsp 估算变量位置objdump -d -M intel ./a.out
或
r2 -d ./a.out
pdf
af
afv
afv 会直接列出:
push %rbp → 有栈帧mov %rsp,%rbp → %rbp 是基准sub $N,%rsp → 局部变量大小call → 返回地址入栈-0x?(%rbp) → 局部变量+0x?(%rbp) → 参数 / 返回地址如果你愿意,可以:
我可以直接帮你“逐行读栈帧”。