函数调用过程(栈桢)

这篇博客详细解析了函数调用过程中栈桢的创建、变化和销毁过程。从代码示例出发,阐述了如何通过push、call、move、pop和ret指令管理栈中的变量和函数调用。在计算a + b后,栈恢复到原始状态,并释放临时变量,展示了函数调用的完整生命周期。
摘要由CSDN通过智能技术生成
栈桢
首先来看一段代码
#include<stdio.h>
int add(int x, int y)
{
    int z = x + y;
    return z;
}
int main()
{
    int a = 10;
    int b = 20;
    int ret = add(a, b);
    printf("ret = %d\n",ret);
    return 0;
}

这里写图片描述

      此处是为了给a,b分别开辟空间,这时栈桢如图所示

这里写图片描述
这里写图片描述

     两条push命令将a,b变量入栈保存这里写图片描述
     接下来通过call命令,将call命令的下一条命令的地址入栈,目的是为了恢复,其次call命令通过jmp命令修改eip寄存器的值,从而达到跳转的目的这里写图片描述这里写图片描述这里写图片描述
     通过push命令将此时的ebp压栈保护(此时的ebp是main函数的ebp),再通过move将esp和ebp的指向变得相同(都指向esp指向的位置),再将esp减44,至此形成新的栈桢结构

这里写图片描述

     接下来,通过以下几条命令计算出a + b,并将其保存,同时通过pop指令出栈,再用move指令将esp和ebp指向相同位置再通过ret将当前栈顶的数据弹回到eip(ret将当前栈顶数据弹回到eip 中)

这里写图片描述这里写图片描述

     对应汇编代码如下这里写图片描述
     此时对应的栈桢结构如图所示这里写图片描述
     此时已经回到初始状态,通过add和move指令达到将ebp返回到main函数的ebp,再将a+b的内容放到ebp-12的那块空间,如图所示.这里写图片描述这里写图片描述
     至此完成所栈桢结构,以及临时变量的释放
     再来看一段栈桢应用的代码:
#include<stdio.h>
#include<windows.h>

void bug();
int my_add(int x, int y);

void* ret = NULL;
void bug()
{
    int x = 0;
    int* q = &x;
    q += 2;
    *q = ret;
    printf("bug: hehe i am a bug!\n");
    Sleep(2000);
}

int my_add(int x, int y)
{
    //printf("my_add:");
    int* p = &x;
    p--;
    ret = *p;
    *p = bug;
}

int main()
{
    int a = 10;
    int b = 20;
    int c = my_add(a, b);
    __asm
    {
        sub esp,4
    }
    printf("main: you should run here\n");
    return 0;
}

这里写图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值