【C语言__函数栈帧的创建和销毁__复习篇9】

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

目录

前言

一、知识补充

二、分析创建和销毁的过程

三、前言问题回答


前言

本篇主要讨论以下问题:

1. 编译器什么时候为局部变量分配的空间

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

3. 函数是怎么传参的,传参的顺序是怎样的

4. 形参和实参是什么关系

5. 函数调用是怎么做的

6. 函数调用结束后怎么返回的

一、知识补充

1. 使用的环境是VS2013,因为越高级的编译器越不容易观察细节。

2. 在不同的编译器下,函数调用过程中栈帧的创建略有差异,具体细节取决于编译器。

3. 寄存器ebp(栈底指针)、esp(栈顶指针) 中存放的是地址,这里面的地址是专门用来维护函数栈帧的。

4. 每一次函数调用,都要在栈区创建一个空间,这个空间就叫该函数的函数栈帧,在调用哪个函数寄存器ebp、esp就维护哪块函数栈帧。

5. 栈区的使用习惯,先使用高地址,再使用低地址。

6. main函数其实也是被其它函数调用的,例如再VS2013中,mainCRTStartup函数调用__tmainCRTStartup函数,由__tmainCRTStartup函数调用的main函数。

7. 在研究函数栈帧时看的是汇编代码。

8. 相关寄存器:

    eax:通用寄存器,保留临时数据,常用于返回值

    ebx:通用寄存器,保留临时数据

    ebp:栈底寄存器

    esp:栈顶寄存器

    eip:指令寄存器,保存当前指令的下一条指令的地址

【C语言__函数栈帧的创建和销毁__复习篇9】,C语言,c语言,开发语言 

二、分析创建和销毁的过程

调试到main函数开始执行的第一行,右击鼠标转到反汇编。

//【研究的源代码】
#include <stdio.h>
int Add(int x, int y)
{
    int z = 0;
    z = x + y;
    return z;
}

int main()
{
    int a = 3;
    int b = 5;
    int ret = 0;
    ret = Add(a, b);
    printf("%d\n", ret);
    return 0;
}

 main函数内的汇编代码:

【C语言__函数栈帧的创建和销毁__复习篇9】,C语言,c语言,开发语言

【C语言__函数栈帧的创建和销毁__复习篇9】,C语言,c语言,开发语言

Add函数内的汇编代码: 

【C语言__函数栈帧的创建和销毁__复习篇9】,C语言,c语言,开发语言

 【C语言__函数栈帧的创建和销毁__复习篇9】,C语言,c语言,开发语言

栈区内存开辟示意图: 

【C语言__函数栈帧的创建和销毁__复习篇9】,C语言,c语言,开发语言 

函数栈帧创建和销毁过程的过程简易描述:

在进入被调用函数的第一行后,汇编指令会先将主调函数的栈底指针的地址进行压栈操作,再将esp的值给ebp,esp接着sub一个值,此步结束后相当于初步搭建起了被调函数的函数栈帧。接着会在栈顶压入三个地址,结束后会进行初始化刚刚开辟的函数栈帧空间,里面会初始化一些随机值,然后在函数栈帧中为局部变量开辟空间并存入局部变量初始化的值,在执行过程中如果存在函数调用,且被调用的函数有参数,则会将从右向左参数的值依次压栈入栈顶(为形参开辟空间),接着执行call指令,在执行call指令时会压入call指令下一条指令的地址,接着程序就会跳入被调用函数的汇编代码中,并执行上面打横线的步骤,执行完后如果后面的指令中需要使用形参的值,则会利用指针偏移找到形参所在的位置,函数的返回类型如果不为void那么函数的返回值会存放在寄存器eax中,此步骤结束后会开始进行一系列pop操作,使得寄存器ebp、esp回到维护主调函数栈帧的位置上,程序回到主调函数的汇编代码中是依靠ret指令完成的,回到主调函数的汇编代码后,会根据代码内容继续执行其他的汇编指令。

三、前言问题回答

1. 编译器什么时候为局部变量分配的空间?

答:编译器为被调用函数分配栈帧空间后,会立即为刚刚开辟的空间初始化,然后再为局部变量分配空间并放入代码中局部变量指定的初始化值。

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

答:因为在为被调用函数分配栈帧空间后,系统会先初始化一次栈帧空间,此时放入初始化的值就是随机的,如果我们在创建局部变量后就为局部变量初始化就能达到覆盖随机值的效果。

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

答:在进入被调函数前就已经把从右向左的实参的值拷贝并push在栈顶了,在需要使用形参的值时通过指针偏移就能找到对应的形参。

4. 形参和实参是什么关系?

答:形参是实参的一份临时拷贝,改变形参不影响实参。

5. 函数调用是怎么做的?

答:略。

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

答:函数返回与两个指令有关。在执行call指令之前先会把call指令的下一条指令的地址进行压栈操作,这个操作是为了解决当函数调用结束后要回到call指令的下一条指令的地方,继续往后执行;ret指令的执行,首先是从栈顶弹出一个值,此时栈顶的值就是call指令下一条指令的地址,此时esp+4,然后编译器会直接跳转到call指令下一条指令的地址处,从而实现回到主调函数的汇编代码中。

  本篇文章已完结,谢谢支持!!!文章来源地址https://www.toymoban.com/news/detail-857935.html

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

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

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

相关文章

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

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

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

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

    2024年01月23日
    浏览(37)
  • 打通你学习C语言的任督二脉-函数栈帧的创建和销毁(上)

      🌈个人主页:  Aileen_0v0 🔥系列专栏: C语言学习 💫个人格言: \\\"没有罗马,那就自己创造罗马~\\\" 待解决疑惑: 局部变量是怎么创建的? 为什么局部变量的值是随机值? 函数是怎么传参的?传参的顺序是怎样的? 形参和实参是什么关系? 函数调用是怎么做的? 函数调用是结束后怎么返

    2024年02月05日
    浏览(35)
  • 函数栈帧的创建和销毁

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

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

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

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

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

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

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

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

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

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

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

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

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

    2024年02月04日
    浏览(39)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包