【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:指令寄存器,保存当前指令的下一条指令的地址

 

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

调试到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函数内的汇编代码:

Add函数内的汇编代码: 

 

栈区内存开辟示意图: 

 

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

在进入被调用函数的第一行后,汇编指令会先将主调函数的栈底指针的地址进行压栈操作,再将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指令下一条指令的地址处,从而实现回到主调函数的汇编代码中。

  本篇文章已完结,谢谢支持!!!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/563658.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【Linux 进程间通信】管道(三)

文章目录 1.管道的五种特征2.管道的四种情况 1.管道的五种特征 ①&#x1f34e;匿名管道只能用于有血缘关系的进程之间进行通信&#xff08;爷孙进程之间可以进行通信&#xff09;&#xff0c;常用于父子之间进行通信&#xff1b; ②&#x1f34e;管道内部&#xff0c;自带进…

若依后台管理系统(ruo-web)修改主题色,更改颜色值 (2024-04-22)

1、修改文件 setting.js 2、修改的文件路径 ruoyi-web/src/store/modules/setting.js 3、默认主题颜色 #409EFF&#xff0c;改新的颜色值&#xff0c;刷新就好了 4、修改主题颜色 还可以用户自己更换&#xff0c;但这个更换只是存储在浏览器中&#xff0c;清除缓存之后还是…

【ARM 裸机】C 语言 led 驱动

前面刚学习了汇编 led 驱动的编写和验证&#xff0c;现在开始就要进入 C 语言 led 驱动编写与验证了 ! 1、C 语言运行环境构建 1.1、设置处理器模式 使 6ULL 处于 SVC 模式下&#xff0c;之前已经提到了处理器的九种模式&#xff0c;参考&#xff1a;【ARM 裸机】汇编 led 驱…

【Linux系统编程】第六弹---权限的概念

✨个人主页&#xff1a; 熬夜学编程的小林 &#x1f497;系列专栏&#xff1a; 【C语言详解】 【数据结构详解】【C详解】【Linux系统编程】 目录 1、什么是权限 2、权限的本质 3、Linux中的用户 4、Linux中文件的权限 4.1、文件访问者的分类(角色) 4.2、文件类型和访问权…

计算机经典黑皮书分享

计算机经典黑皮书是一套计算机科学丛书&#xff0c;其中包含了多本计算机科学领域的经典教材 提供了全面的知识体系&#xff1a;黑皮书涵盖了计算机科学的多个领域&#xff0c;如计算机组成与设计、操作系统、数据库、人工智能等。它们深入浅出地介绍了相关领域的基本概念、原…

WAF攻防-漏洞发现协议代理池GobyAwvsXray

知识点 1、Http/s&Sock5协议 2、Awvs&Xray&Goby代理 3、Proxifier进程代理使用 4、Safedog&BT&Aliyun防护在漏洞发现中&#xff0c;WAF会对三个方向进行过滤拦截&#xff1a; 1、速度频率问题&#xff08;代理池解决&#xff09; 2、工具的指纹被识别&am…

从零开始学 langchain 之搭建最小的 RAG 系统

RAG 可以说是 23 年以来到现在&#xff0c;最为火热的大模型应用技术了&#xff0c;很多人都有了很多经典的研究。而对于新人来说&#xff0c;有些代码十分复杂&#xff0c;导致只看表象并不理解其原理。今天&#xff0c;就利用 langchain 和大家一起搭建一个最简单的 RAG 系统…

JAVA学习笔记27(异常)

1.异常 ​ *异常(Exception) ​ *快捷键 ctrl alt t 选中try - catch ​ *如果进行了异常处理&#xff0c;那么即使出现了异常&#xff0c;程序可以继续执行 1.1 基本概念 ​ *在Java语言中&#xff0c;将程序执行中发生的不正常情况称为"异常"(开发过程中的语…

Xinlinx原语在哪查看如何使用/原语示例

1.打开Vivado 2.点击Tools&#xff0c;选择Language Templates 3.选择Language类型、Device Primitive Instantiation&#xff08;原语&#xff09;、Kintex-7&#xff08;芯片系列&#xff09;&#xff0c;之后可以选择自己需要使用的类型&#xff0c;这里以分布式RAM为例&am…

大一考核题解

在本篇中&#xff0c;将尽力使用多种解法&#xff0c;来达到一题多练的效果。 1&#xff1a; 1.原题链接&#xff1a; 238. 除自身以外数组的乘积 - 力扣&#xff08;LeetCode&#xff09; 这道题首先一眼肯定想到拿整体的积除以当前元素&#xff0c;将结果作为ans&#xff0c;…

Mysql的【存储引擎】之【InnoDB】与【MyISAM】的区别

目录 1.存储引擎在 MyISAM 和 InnoDB 有什么区别 2.Mysql 5.7 默认的存储引擎是什么 3.一个简单例子&#xff08;如果非要使用【MyISAM】存储引擎 &#xff09; 4.2009年写的留言板程序的数据&#xff08;存储引擎是&#xff1a;【MyISAM】&#xff09; 5.mysql 8.0 可以使…

Java学习笔记26(枚举和注解)

1.枚举和注解 1.1 枚举 ​ 1.枚举(enumeration) ​ 2.枚举是一组常量的集合 ​ 3.枚举属于一种特殊的类&#xff0c;里面只包含一组有限的特定的对象 1.枚举应用案例 ​ 1.不需要提供setXxx方法&#xff0c;因为枚举对象值通常为只读 ​ 2.对枚举对象/属性使用final st…

web前端(简洁版)

0. 开发环境 && 安装插件 这里我使用的是vscode开发环境 Auto Rename Tag是语法自动补齐view-in-browser是快速在浏览器中打开live server实时网页刷新 1. HTML 文件基本结构 <html><head><title>第一个页面</title></head><body&g…

vuedevtools图标不亮不能使用,显示vue.js not detected

&#xff08;1&#xff09;不亮解决&#xff1a; 根本原因就是下载的vue开发者工具不对&#xff0c;没有编译。 直接来一个最彻底的解决办法&#xff1a; 下载我已经编译好的shellchrome 链接: https://pan.baidu.com/s/1zKEgGxT5uAvofpD-T1Oa_w?pwd72m5 提取码: 72m5 解…

王者荣耀防御塔如何开发!新手小白做游戏开发采坑经过。phaser前端游戏框架

好嘞&#xff0c;游戏开发框架是js 开发的网页小游戏&#xff01; phaser这个框架。好我们先上图&#xff01; 目前大概是这么一个样子。 然后防御塔功能呢。简单的说就是当人物进去的时候打他。人物扣血。 我们的小人物是这样的代码 遇到的问题如下&#xff1b; 小白刚开始…

【Spring Security系列】Spring Security整合JWT:构建安全的Web应用

前言 在企业级开发或者我们自己的课程设计中&#xff0c;确保用户数据的安全性和访问控制非常重要。而Spring Security和JWT是都两个强大的工具&#xff0c;它俩结合可以帮助我们实现这一目标。 Spring Security提供了全面的安全功能&#xff0c;而JWT则是一种用于身份验证的…

最新win11配置cuda以及cudnn补丁教程

1、首先使用指令 nvidia-smi 查看电脑支持的**最高cuda**版本&#xff0c;例如&#xff1a;本机 12.2 2、进入CUDA下载cuda安装包 https://developer.nvidia.com/cuda-toolkit-archive 2、点击上方绿色的链接&#xff0c;按照图中序号选择的即可&#xff0c;最后点击下载。 …

学习springcloud中Nacos笔记

一、springcloud版本对应 版本信息可以参考&#xff1a;版本说明 alibaba/spring-cloud-alibaba Wiki GitHub 这里说2022.x 分支对应springboot的版本信息&#xff1a; Spring Cloud Alibaba VersionSpring Cloud VersionSpring Boot Version 2022.0.0.0* Spring Cloud 202…

Unity3D 羊了个羊等游戏工程源码/3D资源 大合集

Unity3D休闲益智游戏工程源码大合集 一、关卡类游戏工程源码二、跑酷类游戏工程源码三、消除合成类游戏工程源码四、棋牌类游戏工程源码五、RPG(角色扮演)类游戏工程源码六、FPS&#xff08;射击&#xff09;类游戏工程源码十、Unity3D工艺仿真六、Unity游戏资源1、Unity3D 吃鸡…

软件杯 深度学习实现语义分割算法系统 - 机器视觉

文章目录 1 前言2 概念介绍2.1 什么是图像语义分割 3 条件随机场的深度学习模型3\. 1 多尺度特征融合 4 语义分割开发过程4.1 建立4.2 下载CamVid数据集4.3 加载CamVid图像4.4 加载CamVid像素标签图像 5 PyTorch 实现语义分割5.1 数据集准备5.2 训练基准模型5.3 损失函数5.4 归…