GDB调试汇编堆栈

GDB调试汇编堆栈

第五周分析

  • stack.c反汇编成stack.s的代码

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

GDB调试例子的汇编堆栈

  • 根据卢肖明同学博客内容进行调试

#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;
}

  • 例子的源文件使用gcc - g example.c -o example -m32指令将C源文件在64位机器上编译成32位汇编代码
  • 进入GDB调试器
  • 在main处设置断点、运行并获取汇编代码查看各寄存器状态

  • 主函数栈基址为0xffffcf74,值为0

  • 单步执行并显示%esp和%ebp的值

  • call指令将下一条指令地址入栈,%esp、%ebp值发生变化

  • 上一个函数的基址入栈,从当前%esp开始作为新基址,原地址压栈保存

  • 为传参做准备

  • 实参计算在%eax中进行

  • f函数汇编代码

  • 实参入栈

  • call指令将下一条指令的地址入栈




  • 计算short+int

  • pop %ebp指令将栈顶弹到%ebp中,同时%esp增加4字节



  • ret指令将栈顶弹给%eip





堆栈情况

指令 %esp %ebp 堆栈
movl$0x8,(%esp) 0ffffcf74 0ffffcf74 0x0
call 0x80483ef 0ffffcf74 0ffffcf74 0x8 0x0
push %ebp 0ffffcf70 0ffffcf78 0x804842e 0x8 0x0
mov %esp,%ebp 0ffffcf6c 0ffffcf78 0xffffcf78 0x804842e 0x8 0x0
mov 0x804a01c,%edx 0ffffcf6c 0ffffcf6c 0xffffcf78 0x804842e 0x8 0x0
call 0x80483db 0ffffcf68 0ffffcf6c 0xa 0xffffcf78 0x804842e 0x8 0x0
push %ebp 0ffffcf64 0ffffcf6c 0x804841a 0xa 0xffffcf78 0x804842e 0x8 0x0
mov %esp,%ebp 0ffffcf60 0ffffcf6c 0xffffcf6c 0x804841a 0xa 0xffffcf78 0x804842e 0x8 0x0
movzwl 0x804a018,%eax 0ffffcf60 0ffffcf60 0xffffcf6c 0x804841a 0xa 0xffffcf78 0x804842e 0x8 0x0
ret 0ffffcf64 0xffffcf6c 0x804841a 0xa 0xffffcf78 0x804842e 0x8 0x0
leave 0ffffcf68 0ffffcf6c 0xa 0xffffcf78 0x804842e 0x8 0x0
ret 0ffffcf70 0ffffcf78 0x804842e 0x8 0x0
posted @ 2016-12-03 14:27  20145308刘昊阳  阅读(229)  评论(0编辑  收藏  举报