GDB调试汇编堆栈过程分析

分析过程

使用gcc -g example.c -o example -m32指令在64位的机器上产生32位汇编,然后使用gdb example指令进入gdb调试器:

进入之后先在main函数处设置一个断点,再run一下,使用disassemble指令获取汇编代码,用i(info) r(registers)指令查看各寄存器的值:

可见此时主函数的栈基址为0xffffd068,用x(examine)指令查看内存地址中的值,但目前%esp所指堆栈内容为0,%ebp所指内容也为0

首先,结合display命令和寄存器或pc内部变量,做如下设置:display /i $pc,这样在每次执行下一条汇编语句时,都会显示出当前执行的语句。下面展示每一步时%esp、%ebp和堆栈内容的变化:
计算short+int:
pop %ebp指令将栈顶弹到%ebp中,同时%esp增加4字节:
ret指令将栈顶弹给%eip:
因为函数f修改了%esp,所以用leave指令恢复。leave指令先将%esp对其到%ebp,然后把栈顶弹给%ebp:
主函数汇编代码:

指令 %esp %ebp 堆栈
push $0x8 0xffffd058 0xffffd058 0x0
call 0x80483ef 0xffffd054 0xffffd058 0x8 0x0
push %ebp 0xffffd050 0xffffd058 0x8048412 0x8 0x0
mov %esp,%ebp 0xffffd04c 0xffffd058 0xffffd058 0x8048412 0x8 0x0
mov 0x804a01c,%edx 0xffffd04c 0xffffd04c 0xffffd058 0x8048412 0x8 0x0
call 0x80483db 0xffffd048 0xffffd04c 0xa 0xffffd058 0x8048412 0x8 0x0
push %ebp 0xffffd044 0xffffd04c 0x8048403 0xa 0xffffd058 0x8048412 0x8 0x0
mov %esp,%ebp 0xffffd040 0xffffd04c 0xffffd04c 0x8048403 0xa 0xffffd058 0x8048412 0x8 0x0
movzwl 0x804a018,%eax 0xffffd040 0xffffd040 0xffffd04c 0x8048403 0xa 0xffffd058 0x8048412 0x8 0x0
ret 0xffffd044 0xffffd04c 0x8048403 0xa 0xffffd058 0x8048412 0x8 0x0
leave 0xffffd04c 0xffffd04c 0xffffd058 0x8048412 0x8 0x0
ret 0xffffd050 0xffffd058 0x8048412 0x8 0x0
add $0x4,%esp 0xffffd054 0xffffd058 0x8 0x0
mov $0x3,%edx 0xffffd058 0xffffd058 0x0
ret

这次实验是在卢肖明同学的博客的帮助下完成的,很感谢卢肖明同学以及菜野同学的帮助