通过反编译一个简单的C程序,解释堆栈的变化

本次我们使用的示例程序如下

 int g (int x)
{
    return x + 4;
}

int f (int x)
{
    return g(x);
}

int main (void)
{
    return f(6) + 1;
}

使用的反汇编指令为:gcc -S -o main.s main.c (文件名写自己的,如果使用的是32位系统的话在指令后面加上 -m32)
得到的汇编程序经过处理后如下所示:

g:
    pushl   %ebp            //esp-4指向7,ebp入栈
    movl    %esp, %ebp      //esp的值赋给ebp,ebp指向7
    movl    8(%ebp), %eax   //将ebp+8后指向的栈地址内的数(即6)赋值给eax
    addl    $4, %eax        //将eax内数加上4并存入eax,此时eax值为10
    popl    %ebp            //将栈7出栈放入ebp,即ebp指向栈4,esp+4指向6
    ret                     //将栈6出栈放入eip,esp+4指向5,回到f方法
f:
    pushl   %ebp             //esp-4指向4,ebp入栈
    movl    %esp, %ebp       //esp的值赋给ebp,ebp指向4 
    subl    $4, %esp         //esp-4指向5
    movl    8(%ebp), %eax    //将ebp+8后指向的栈地址内的数(即6)赋值给eax
    movl    %eax, (%esp)     //eax将数值赋给esp当前所指位置,即栈5
    call    g                //esp-4指向6,将eip入栈,调转到g方法
    leave                    //将ebp的值赋给esp,esp指向4,将栈4出栈放入ebp,ebp指向1,esp+4指向3
    ret                      //将栈3出栈放入eip,esp+4指向2,回到main方法
main:
    pushl   %ebp              //此时ebp指向0,esp-4指向1,ebp入栈
    movl    %esp, %ebp        //esp的值赋给ebp,ebp指向1
    subl    $4, %esp          //esp-4指向2
    movl    $6, (%esp)        //将6存入栈2中
    call    f                 //将eip入栈,esp-4指向3调转到f方法
    addl    $1, %eax          //将eax的值加1(即10+1),存入eax中
    leave                     //将ebp的值赋给esp,esp指向1,将栈1出栈放入ebp,ebp指向0,esp+4指向0
    ret                       //将eip出栈放入eip,然后就是main方法的上层方法了

首先说明一下,leave 指令相当于:

movl %ebp, %esp
popl %ebp

call指令相当于:

pushl eip
movl f,eip

ret指令相当于:

popl eip(*)

总结:计算机通过eip来存储下一条指令的地址,
通过eax传递函数返回值,
每次调用一个方法时重新开辟一个新的栈空间

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值