20145236 GDB调试汇编堆栈过程分析

本文介绍如何通过GDB调试器分析32位程序的汇编堆栈过程,包括安装必要库、生成32位汇编代码、设置断点、观察寄存器变化及汇编指令执行流程等。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

GDB调试汇编堆栈过程分析

  • 首先需要输入sudo apt-get install libc6-dev-i386安装一个库才能产生汇编代码,然后输入gcc - g example.c -o example -m32,在64位机器上产生32位汇编。

测试源代码

#include<stdio.h>

short addend1 = 1;
static int addend2 = 2;
const static long addend3 = 3;

static int g(int x)
{
return x + addend1;
}

static const int f(int x)
{
return g(x + addend2);
}

int main(void)
{
return f(8) + addend3;
}

  • 先从main程序开始执行,调用x前,先将返回地址入栈,再将%ebp入栈,将%ebp放在现在的栈顶位置,栈顶指针减4分配空间,再将参数8入栈,调用x
  • g调用x前,再进行一次将返回地址和%ebp入栈,改变%ebp位置的操作,将栈顶指针减4分配空间,将8存贮在%eax寄存器中,再将现在%eax中的值入栈保存
  • 再进行一次将返回地址和%ebp入栈,改变%ebp位置的操作,将8存入%eax便于操作,对8进行加3的操作,弹出到%ebp,返回main
  • 返回main,将%eax中的参数加1,结束程序

  • gdb example进入gdb,b example.c:main设置一个函数断点,run启动程序
  • disassemble获取汇编代码,若命令不带参数,默认的反汇编范围是所选择帧的pc附近的函数。info registers列出使用的寄存器.
    886779-20161204104147115-924306245.png
    886779-20161204104235240-419217848.png

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

  • 首先,结合display命令和寄存器或pc内部变量,做如下设置:display /i $pc,这样在每次执行下一条汇编语句时,都会显示出当前执行的语句。下面展示每一步时%esp%ebp和堆栈内容的变化:
    886779-20161204104520302-697357349.png

  • call指令将下一条指令的地址入栈,此时%esp,%ebp和堆栈的值为:
    886779-20161204104645724-1399935249.png

  • 将上一个函数的基址入栈,从当前%esp开始作为新基址:
    886779-20161204104725990-2137199820.png

  • 先为传参做准备:
    886779-20161204105338927-1298854891.png

  • 实参的计算在%eax中进行:
    886779-20161204105401552-1268186347.png

  • f函数的汇编代码:
    886779-20161204105420068-1689497937.png

  • 实参入栈:
    886779-20161204105435240-1140521200.png

  • call指令将下一条指令的地址入栈:
    886779-20161204105451052-350870416.png
    886779-20161204105549427-1166024964.png
    886779-20161204105558287-147284937.png
    886779-20161204105606318-181044662.png

  • 计算short+int:
    886779-20161204105639740-1403434982.png

  • pop %ebp指令将栈顶弹到%ebp中,同时%espret指令将栈顶弹给%eip:增加4字节:
    886779-20161204105647943-1627601442.png

  • ret指令将栈顶弹给%eip
    886779-20161204105709365-573820002.png
    886779-20161204105730834-1048388908.png

  • 因为函数f修改了%esp,所以用leave指令恢复。leave指令先将%esp对其到%ebp,然后把栈顶弹给%ebp
    886779-20161204105819302-149531507.png
    886779-20161204105831177-1187952030.png
    886779-20161204105840802-1646416147.png
    886779-20161204105850349-410148536.png

  • 使用disassemble对主函数进行汇编代码:
    886779-20161204105917256-359221620.png

序号指令%eip%esp%ebp%eax堆栈
0001push $0x80x804840b0xffffd0480xffffd0480xf7fb8dbc0x0
0002call 0x80483ef0x804840d0xffffd0440xffffd0480xf7fb8dbc0x8 0x0
0003push %ebp0x80483ef0xffffd0400xffffd0480xf7fb8dbc0x8048412 0x8 0x0
0004mov %esp,%ebp0x80483f00xffffd03c0xffffd0480xf7fb8dbc
0005mov 0x804a01c,%edx0x80483f20xffffd03c0xffffd03c0xf7fb8dbc0xffffd048 0x8048412 0x8 0x0
0006mov 0x8(%ebp),%eax0x80483f80xffffd03c0xffffd03c0xf7fb8dbc0xffffd048 0x8048412 0x8 0x0
0007call 0x80483db0x80483fe0xffffd0380xffffd03c0xa0xa 0xffffd048 0x8048412 0x8 0x0
0008push %ebp0x80483db0xffffd0340xffffd03c0xa0x8048403 0xa 0xffffd048 0x8048412 0x8 0x0
0009mov %esp,%ebp0x80483dc0xffffd0300xffffd03c0xa0xffffd03c 0x8048403 0xa 0xffffd048 0x8048412 0x8 0x0
0010ret0x80483ee0xffffd0340xffffd03c0xb0x8048403 0xa 0xffffd048 0x8048412 0x8 0x0
0011leave0x80484060xffffd03c0xffffd03c0xb0xffffd048 0x8048412 0x8 0x0
0012ret0x80484070xffffd0400xffffd0480xb0x8048412 0x8 0x0
0013add $0x4,%esp0x80484070xffffd0400xffffd0480xb0x8 0x0
0014leave0x804841c0xffffd0480xffffd0480xe
0015ret0x804841d0xffffd04c0x00xe

转载于:https://www.cnblogs.com/feng886779/p/6130323.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值