使用GDB调试x86_64汇编:如何查看栈变量及地址差疑问
栈内存查看与汇编地址疑问解答
问题背景
调试以下C程序:
int main() { int x = 5; return 0; }
在return语句处设置断点后,GDB输出的Intel语法汇编代码如下:
(gdb) disass Dump of assembler code for function main(): 0x00005555555545fa <+0>: push rbp 0x00005555555545fb <+1>: mov rbp,rsp 0x00005555555545fe <+4>: mov DWORD PTR [rbp-0x4],0x5 => 0x0000555555554605 <+11>: mov eax,0x0 0x000055555555460a <+16>: pop rbp 0x000055555555460b <+17>: ret End of assembler dump.
当前rsp寄存器值:
(gdb) info reg rsp rsp 0x7fffffffdcb0 0x7fffffffdcb0
疑问:
- 变量x存在栈中,但用
x/10x $rsp无法找到,如何正确打印栈? - 上述地址之间的差值为何是16?
解答
1. 正确定位变量x的方法
变量x存储在rbp-0x4的内存位置,当前断点处rsp指向的是之前push rbp压入栈的旧rbp值(尚未执行pop rbp),因此直接查看$rsp指向的内存看不到x。你需要以rbp为基准查看栈:
- 直接定位x的地址:执行
x/10x $rbp-0x4,会从x的存储地址开始,显示10个双字内存内容,其中第一个值就是0x5 - 从栈帧基址开始查看:执行
x/10x $rbp,输出内容中,$rbp指向的是旧rbp值,再往下4字节(即$rbp-0x4)就是x的值
也可以先通过p/x $rbp-0x4获取x的具体地址,再用x/wx [地址]命令单独查看该地址的内容,确认是否为0x5。
2. 地址差值为16的原因
你提到的16差值对应64位系统的16字节栈对齐规则,同时也和汇编指令的字节数累加有关:
- 栈对齐要求:64位系统中,函数调用时栈必须保持16字节对齐。进入
main函数后,push rbp使rsp减少8字节,打破了原本的对齐状态。编译器会预留足够的栈空间让整个栈帧大小为16字节的倍数——虽然x只需要4字节,但栈帧从rbp-0x10到rbp被预留(其中rbp-0x4存x,剩余12字节为填充空间),以此满足对齐要求。 - 指令偏移量的16:汇编中<+0>到<+16>的偏移量是指令字节数的累加:
push rbp占1字节、mov rbp,rsp占3字节、mov [rbp-0x4],0x5占7字节、mov eax,0x0占5字节,总和1+3+7+5=16,这是指令的总长度,和栈对齐的16字节是两个独立概念,容易混淆。
内容的提问来源于stack exchange,提问作者Irbis
相关产品推荐
相关产品推荐

