函数栈帧的创建和销毁

大家好,我是真的王。今天我来分享一下有关栈帧的知识。 

目录

前言

一、寄存器

二、具体步骤

1.内存

2.程序执行的具体过程

3.调用add()函数

总结


前言

我们每个人编写代码时都会调用函数,但你知道调用函数的具体过程吗?

下面以vs2019环境为例演示。


一、寄存器

下面引用维基百科对寄存器的定义”

寄存器(Register)是中央处理器内用来暂存指令、数据地址电脑存储器。寄存器的存贮容量有限,读写速度非常快。在计算机体系结构里,寄存器存储在已知时间点所作计算的中间结果,通过快速地访问数据来加速计算机程序的执行。

寄存器位于存储器层次结构的最顶端,也是CPU可以读写的最快的存储器,事实上所谓的暂存已经不像存储器,而是非常短暂的读写少量信息并马上用到,因为通常程序执行的步骤中,这期间就会一直使用它。寄存器通常都是以他们可以保存的比特数量来计量,举例来说,一个8位寄存器或32位寄存器。在中央处理器中,包含寄存器的部件有指令寄存器(IR)、程序计数器累加器。寄存器现在都以寄存器数组的方式来实现,但是他们也可能使用单独的触发器、高速的核心存储器薄膜存储器以及在数种机器上的其他方式来实现出来。”

寄存器我们只要大致了解通用寄存器即可

  • EAX:(针对操作数和结果数据的)累加器 ,返回函数结果
  • EBX:(DS段中的数据指针)基址寄存器
  • ECX:(字符串和循环操作数)计数器
  • EDX:(I/O指针)数据寄存器
  • EBP:(SS段中栈内数据指针)扩展基址指针寄存器
  • ESI:(字符串操作源指针)源变址寄存器
  • EDI:(字符串操作目标指针)目的变址寄存器
  • ESP:(SS段中栈指针)栈指针寄存器

其中ebp,esp 在本文中较为重要

ebp(栈底指针)和esp(栈顶指针)负责维护调用的函数

二、具体步骤

1.内存

我们要弄清楚函数调用的具体过程,我们就要了解一下内存

一个内存单元是1个字节(1个字节8个比特位)

我们或许听说过电脑有32位的也有64位的,32位就是有32根地址线,64位同理。而地址线就是实际在电脑中的线,它们有高电平和低电平两种状态,已32位为例,每一根地址线有两种状态,它一共有2的32次方种状态,也就可以储存2的32次方比特的数据。

我们就可以知道为什么我们每次取地址时,都是随机的。 

 函数在栈区开辟,栈这种数据结构,类似于弹夹

栈底

 我们每次创建临时变量时都会将变量从栈顶向下压,形象的称为压栈

2.程序执行的具体过程

接下来,我们进入正题!!!!!

我们以最简单的代码为例

#include<stdio.h>
int add(int x, int y)
{
	int z = 0;
	z = x + y;
	return z;
}
int main()
{
	int a = 3;
	int b = 4;
	int c=add(a, b);
	printf("%d\n", c);
	return 0;
}

首先我们在vs2019环境下,打开调试窗口点击调试,窗口,反汇编


 这时,我们来到反汇编。我们可以看到push(压栈),mov(移动),rep(初始化),call(调用)

pop(出栈)等汇编代码。(函数在被调用前,编译器会预先在栈区开辟一块空间将这块空间赋值成CCCCCCCCCCC......这也就是为什么某一个变量没有初始化时出现的烫烫烫的原因。

我们发现在还没有进入main函数之前系统进行了一系列过程 

main函数并不是一个程序最开始执行的函数。

 我们再打开内存,调用堆栈

发现main不是最初调用的函数,main()函数是被__tmainCRTStartup函数调用的,而 __tmainCRTStartup又是被mainCRTStartup调用的。

我们再回到代码

在创建a时之前,先把ebp压入栈中,然后移动ebp,esp

 

这段代码的含义为,esp的值减少4字节,将ebp的值压入栈中,将esp的值赋给ebp,将esp-0E4h字节的结果保存在esp中(esp指针向低地址方向移动0E4h字节)。

esp的值减少4字节,ebx的值压入栈中。esp的值减少4字节,esi的值压入栈中,esp的值减少4字节,将edi的值压入栈中。

3.调用add()函数

 首先栈区会存放call命令的下一条指令的地址,ebp会减去某个数值来到add()函数的栈帧,随着函数内部指令的执行,ebp逐渐递减,来到add()函数的栈顶,这时ebp指向add()函数返回值的地址。寄存器预先存放的地址就是通过ebp指针,返回到call命令的下一条指令的地址,然后add()函数栈帧销毁。而到程序的末尾main()函数的最后也是经过上述过程return 0和栈帧销毁的。

总结

以上就是函数栈帧相关的知识分享,如有错误请指正。谢谢

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值