【C语言】函数栈帧的创建与销毁

这篇具有很好参考价值的文章主要介绍了【C语言】函数栈帧的创建与销毁。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

今天我们要学习的是函数栈帧的创建与销毁,学完这部分内容,我们可以解决下面的几个问题:

局部变量是怎么创建的?

为什么局部变量的值是随机值?

函数是怎么传参的?传参顺序是怎样的?

形参和实参是什么关系?

函数调用是怎么做的?

函数调用是怎么做的?

函数调用结束后是怎么返回的?

学习函数栈帧的创建与销毁不仅可以学习到这些知识,还能修炼自己的内功,也能搞懂后期更多的知识。

进入正题.
今天讲解的时候,使用的环境是VS2013,不要使用太高级的编译器,越高级的编译器,越不容易学习和观察。同时在不同的编译器下,函数调用过程中栈帧的创建是略有差异的,具体细节取决于编译器的实现。
 

预备知识

在学习函数栈帧的创建与销毁之前,我们要了解以下寄存器:

【C语言】函数栈帧的创建与销毁

  • eax:通用寄存器,保留临时数据,常用于返回值
  • ebx:通用寄存器,保留临时数据
  • ebp:栈底寄存器
  • esp:栈顶寄存器
  • eip:指令寄存器,保存当前指令的下一条指令的地址

esp和ebp共同维护函数栈帧,程序调用哪个函数,这两个指针就去维护那个函数调用开辟的空间

【C语言】函数栈帧的创建与销毁

常用的汇编指令:

  • mov:数据转移指令
  • push:数据入栈,同时esp栈顶寄存器也要发生改变
  • pop:数据弹出至指定位置,同时esp栈顶寄存器也要发生改变
  • sub:减法命令
  • add:加法命令
  • call:函数调用,1. 压入返回地址 2. 转入目标函数
  • jump:通过修改eip,转入目标函数,进行调用
  • ret:恢复返回地址,压入eip,类似pop eip命令

正文部分

 我们以下面这个程序来分析:

#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;
}

 在VS2013中,main函数也是被其他函数调用的,具体是:

【C语言】函数栈帧的创建与销毁

 

main函数栈帧的创建

下面是反汇编代码:

【C语言】函数栈帧的创建与销毁

 我们已经知道,main函数是由其他函数调用的,在调用main函数前,已经为_tmainCRTStartup在栈区开辟了空间。

 此时的情景:

【C语言】函数栈帧的创建与销毁

 进入main函数第一步:【C语言】函数栈帧的创建与销毁

 进行压栈:

【C语言】函数栈帧的创建与销毁

 接着进行下一步操作:【C语言】函数栈帧的创建与销毁

 将esp的值赋给ebp,因此ebp就移到了esp的位置,再将esp减一个八进制的数字0E4H,因此esp向上移动:

此时的情景变成了下图所示:

【C语言】函数栈帧的创建与销毁

  可以看出,esp和ebp已经在维护新的空间了,而这块空间就是为main函数开辟的

接下来是三个压栈的操作:

【C语言】函数栈帧的创建与销毁

 在压栈的同时,esp指针也会向上移动

【C语言】函数栈帧的创建与销毁

 接下来,将ebp+FFFFFF1CHF加载到edi里面,lea是加载的意思。

 【C语言】函数栈帧的创建与销毁

 如果勾选上显示符号名,我们会惊奇的发现:

【C语言】函数栈帧的创建与销毁

【C语言】函数栈帧的创建与销毁

 这步操作是将ebp-0E4H加载到edi里面,

接着进行下一步:

【C语言】函数栈帧的创建与销毁

这几步的操作是:从edi开始向下的空间初始化为CCCCCCCC总共初始化ecx次,每次初始化8个字节;

【C语言】函数栈帧的创建与销毁

 到这里,为main函数栈帧的开辟就完成了

执行main函数内部代码

【C语言】函数栈帧的创建与销毁

将变量a,b,c初始化:

【C语言】函数栈帧的创建与销毁

这些步骤是在main函数栈帧中的存入变量a,b,c的值,并将其赋值。如果没有赋初始值,此时变量里的值仍是cccccccc,正好和”烫烫烫“的二进制编码一样,这就是为什么我们如果不初始化变量,可能在屏幕上输出”烫烫烫“的原因了。

Add函数栈帧的创建

【C语言】函数栈帧的创建与销毁

 前面4步执行的操作:【C语言】函数栈帧的创建与销毁

 

【C语言】函数栈帧的创建与销毁

 Add函数的执行

【C语言】函数栈帧的创建与销毁

call 指令是要执行函数调用逻辑的,在执行call指令之前先会把call指令的下一条指令的地址进行压栈操作,这个操作是为了解决当函数调用结束后要回到call指令的下一条指令的地方,继续往后执行。

【C语言】函数栈帧的创建与销毁

 

 Add函数的汇编代码:【C语言】函数栈帧的创建与销毁

前面这几步和main函数的前几步执行过程相似,是为Add函数准备栈帧

【C语言】函数栈帧的创建与销毁

 上面代码执行完的结果:

【C语言】函数栈帧的创建与销毁

 

创建临时变量z:

【C语言】函数栈帧的创建与销毁

【C语言】函数栈帧的创建与销毁

 执行相加操作:

【C语言】函数栈帧的创建与销毁

 ebp+8就是10的地址,ebp+12就是20的地址:

【C语言】函数栈帧的创建与销毁

 相加后,将z的值放在eax这个寄存器中, 寄存器是不会被销毁的,因此,当z被销毁后,z的值仍然保存了下来。

【C语言】函数栈帧的创建与销毁

 当执行完Add函数是,就要释放内存给Add函数分配的内存空间。

【C语言】函数栈帧的创建与销毁

 这三步将edi,esi, ebx 出栈,同时esp也增加会向下移动。

将esp赋给ebp,同时这部分的空间也会还给操作系统。

【C语言】函数栈帧的创建与销毁

 返回值的带回方法:将eax中存放的z的值赋给ebp-20h

【C语言】函数栈帧的创建与销毁

 main函数的空间销毁和Add函数类似,就不过多赘述了。文章来源地址https://www.toymoban.com/news/detail-493805.html

到了这里,关于【C语言】函数栈帧的创建与销毁的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • C语言-------函数栈帧的创建和销毁------剖析描骨

    🎂        ✨✨✨✨✨✨🍧🍧🍧🍧🍧🍧🍧🎂    🎂      作者介绍:                              🎂🎂        🎂 🎉🎉🎉🎉🎉🎉🎉              🎂           🎂作者id:老秦包你会,         🎂 简单介绍:🎂🎂🎂🎂🎂🎂🎂🎂🎂🎂🎂🎂🎂🎂🎂

    2024年02月14日
    浏览(33)
  • C语言之反汇编查看函数栈帧的创建与销毁

    函数栈帧是用于在计算机程序中实现函数调用的一种数据结构。在函数调用过程中,每个函数都需要在内存中创建一个栈帧,用于存储局部变量、返回地址和参数等。 具体来说,函数栈帧通常包含以下部分: 局部变量表:存储函数的局部变量,包括基本数据类型(如整数、

    2024年01月23日
    浏览(37)
  • 【C语言__函数栈帧的创建和销毁__复习篇9】

    目录 前言 一、知识补充 二、分析创建和销毁的过程 三、前言问题回答 本篇主要讨论以下问题: 1. 编译器什么时候为局部变量分配的空间 2. 为什么局部变量的值是随机的 3. 函数是怎么传参的,传参的顺序是怎样的 4. 形参和实参是什么关系 5. 函数调用是怎么做的 6. 函数调

    2024年04月25日
    浏览(37)
  • 函数栈帧的创建和销毁

    前言 观察函数栈帧的创建和销毁,不要使用太高级别的的编译器,越高级的编译器越不容易学习和观察。同时在不同编译器下,函数调用的过程中栈帧的创建是略有差异的,具体细节取决于编译器的实现 我们在写C语言代码的时候,经常会把一个独立的功能抽象为函数,所以

    2023年04月17日
    浏览(40)
  • 函数栈帧的创建与销毁

    魔王的介绍:😶‍🌫️一名双非本科大一小白。 魔王的目标:🤯努力赶上周围卷王的脚步。 魔王的主页:🔥🔥🔥大魔王.🔥🔥🔥 ❤️‍🔥大魔王与你分享:莫泊桑说过,生活可能不像你想象的那么好,但是也不会像你想象的那么糟。人的脆弱和坚强都超乎了自己的想

    2024年02月15日
    浏览(36)
  • 从汇编代码探究函数栈帧的创建和销毁的底层原理

    人,只有在放弃战斗的时候才算输,只要坚持战斗,就还没输  本文收录于青花雾气-计算机基础 往期回顾 从0到1搞定在线OJ 数据在内存中的存储 计算机存储的大小端模式 目录 一、先导知识 二、函数调用堆栈 三、函数栈帧的创建 1.创建函数栈帧 2.创建变量 3.函数传参 4.函数

    2024年02月08日
    浏览(37)
  • 【C语言】函数栈帧的创建和毁销

    大家好,我是深鱼~ 目录 一、寄存器 二、栈区  三、函数栈帧的创建 1.为main函数开辟栈帧  2.在main函数中创建变量 3.调用Add函数前的准备  4.为Add函数开辟栈帧  5.在Add函数中创建变量并运算 四、函数栈帧的销毁 6.Add函数栈帧的销毁 7.返回main函数栈帧 【前言】 前期学习的时

    2024年02月14日
    浏览(31)
  • 函数栈帧的创建和毁销【C语言版】

    大家好,我是深鱼~ 目录 一、寄存器 二、栈区  三、函数栈帧的创建 1.为main函数开辟栈帧  2.在main函数中创建变量 3.调用Add函数前的准备  4.为Add函数开辟栈帧  5.在Add函数中创建变量并运算 四、函数栈帧的销毁 6.Add函数栈帧的销毁 7.返回main函数栈帧 【前言】 前期学习的时

    2024年02月15日
    浏览(38)
  • 探秘函数栈帧:『 揭开函数栈帧创建与销毁的神秘面纱 』

    .. 目录 知识点回顾 一、什么是栈帧(堆栈帧)? 1.内存布局 2.常用寄存器 3.汇编指令 👇👇对于栈的详细介绍 : 👇👇函数栈帧的介绍: 二、函数调用中的栈帧 1.探究main函数栈帧的创建 2.对main函数中的代码进行分析 3.探究Add函数栈帧的创建  三、函数栈帧的销毁过程 博客引

    2024年02月06日
    浏览(63)
  • 学C的第十一天【查看汇编代码一步步了解 函数栈帧(栈区局部变量)的创建和销毁】

    ========================================================================= 相关代码gitee自取: C语言学习日记: 加油努力 (gitee.com) ========================================================================= 接上期: 学C的第十天(继续深入学习函数、函数递归、练习)-CSDN博客 ============================================

    2024年02月04日
    浏览(38)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包