程序员的内功修炼——函数栈帧的创建与销毁

每个函数都是在栈上创建,同时在执行程序之后被自动销毁。在执行程序调用该函数的过程中,由两个寄存器 esp , ebp来存放该函数地址(一个是该函数的最高位的地址,一个是该函数最低位的地址),这两个地址是用来维护函数在栈上开辟的空间(该空间又称为函数栈帧)。程序总是从main函数开始,但其实main函数也是被其他函数调用;#include <stdio.h>int Add(int x, int y){ int z = 0; z = x + y; return z;}
摘要由CSDN通过智能技术生成

每个函数都是在栈上创建,同时在执行程序之后被自动销毁。

在执行程序调用该函数的过程中,由两个寄存器 esp , ebp来存放该函数地址(一个是该函数的最高位的地址,一个是该函数最低位的地址),这两个地址是用来维护函数在栈上开辟的空间(该空间又称为函数栈帧)。

程序总是从main函数开始,但其实main函数也是被其他函数调用;

#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\n",c);
    return 0;
}

就拿上面简单的程序说一下创建和销毁的过程:

 最开始时:

程序开始执行,先进入main函数,进入main函数时就得为main函数开辟空间,此时将栈顶指针的值赋给栈底指针,而栈顶指针将指向一个更小的地址,两指针之间就是main函数的函数栈帧;确定后空间之后,就把里面的单位赋上随机值。

现在开始执行main函数语句,开辟整形a,b,c,并赋上值; 

 

下一指令是调用Add函数,首先传参(我使用vs2013版本)Add(a,b) ,先传b(在当前栈顶放一个元素,用来存放b),同理再传a ,栈顶指针也跟着向低地址下两个单元; 

进入Add函数之前 1. 还要记住main函数中下一指令的地址,为了出Add函数之后便于找到下一指令;也是在栈顶放一个元素存放Add函数后面指令单地址, 栈顶指针也跟着向低地址下一个单元;

 进入Add函数之前 2.进入Add函数,esp,ebp 将会维护Add函数,还要在栈顶开辟一个单元存放目前main函数的ebp,栈顶指针也跟着向低地址下一个单元;然后此时将栈顶指针的值赋给栈底指针,而栈顶指针将指向一个更小的地址,两指针之间就是Add函数的函数栈帧;确定后空间之后,就把里面的单位赋上随机值。

 开始执行Add函数,开辟整型变量z,并赋值;

接着往下走执行 z = x+y;最后返回 z 值;先把z的值传给寄存器eax(因为释放空间之后找不到z值);然后释放Add函数空间,把ebp赋值给esp; 

此时把栈顶释放一个单元,ebp回到了main函数的栈底,esp向高位移一个单元 ;

而注意Add函数下面一个指令的地址以保存,得到地址后也将释放空间,Add函数的形参也被释放(函数形参是实参的临时拷贝);

 

接着往下走,直到结束,main函数的空间释放和Add函数一样;

 

  • 13
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值