函数栈帧的创建和销毁

        首先,在学习这个问题的时候,不要用太高级的编译器,越高级,越不容易学习和观察(封装得太复杂了)。同时在不同的编译器下,函数调用过程中栈帧的创建是略有差异的,具体细节取决于编译器的实现,但逻辑是一样的。

#include <stdio.h>

int Add(int x,int y)
{
    int z = 0;
    z = x + y;
    return z;
}
int main()
{
    int a = 10;
    int b = 20;
    int c = 0;
    c = Add(a,b);
    printf("%d",c);
    return 0;
}

栈区先使用高地址再使用低地址

创建这样一块代码的时候,每一个函数调用都要开辟一块空间

函数栈帧主要由这两个寄存器来维护。

        调哪个空间ebp和esp就会在哪个空间,在调用哪个函数,正在调用哪个函数,ebp和esp就是维护哪块空间的函数栈帧,当这段代码运行到Add时就会直接去维护Add的函数栈帧。

        所以他们两个的空间,就是为本次函数调用所分配的空间。

可以看到在这个地方main函数被调了

向上翻可以看到这个调用函数的函数名,在这个函数内部调用了main函数

这个函数又被

这个调用了,main函数的返回值就返回到了mainret里

所以在VS2013中main函数也是被其他函数所调用的。

再看是怎么调用到,到这里后右击鼠标到反汇编

看他的汇编代码

没有push的时候地址是这个

push完之后esp就会指上去,地址变小

再来就是执行mov ebp,esp         注意ebp上去,指向原来esp的位置,我这里怕被覆盖所以这样移,esp和ebp指的同一个位置

再执行sub                esp 0E4h

这里就是进了main函数里了

push         ebx

再来lea

即是load effective address

ecx就是一会儿存c大概进行那么多次

让这块空间全变成cccccc

PUSH        压栈:从栈顶放一个元素

POP           出栈:从栈顶拿走一个元素

所以有时访问越界时会打印烫烫烫就是这个原因。

接下来就是把局部变量的赋值

接下来又是调用函数Add,传参,ebp-14h就是b

mov eax,dword ptr[ebp - 14h]传参

mov ecx,dword ptr[ebp - 8]传参

call就是调用函数区

再接着​​​​​​​​​​​​​​又是调用函数开辟栈帧

计算

再接下来将结果带回去eax是个寄存器,寄存器不会因为调用结束就销毁

函数计算

得出c的结果,并销毁,main的同理

其实可以发现 在函数开辟空间上进行的,就是一个z=x+y操作,x,y都不在函数空间里,即可以理解为形参不在函数的栈帧里。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

KrisZhang10

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值