C语言函数栈帧的创建和销毁(逐步分析)

news2024/11/19 20:19:05

什么是函数栈帧

我们在写C语言代码的时候,经常会把一个独立的功能抽象为函数,所以C程序是以函数为基本单位的。 那函数是如何调用的?函数的返回值又是如何返回的?函数参数是如何传递的?这些问题都和函数栈帧有关系。

函数栈帧(stack frame)就是函数调用过程中程序的调用栈(call stack)所开辟的空间,这些空间是用来存放: 1. 函数参数和函数返回值 2. 临时变量(包括函数的非静态的局部变量以及编译器自动生产的其他临时变量) 3. 保存上下文信息(包括在函数调用前后需要保持不变的寄存器)。

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

每一个函数调用都要在栈区穿件一个空间


寄存器

寄存器是 CPU 内部用来存放数据的一些小型 存储区域 ,用来暂时存放参与运算的数据和运算结果。 其实寄存器就是一种常用的 时序逻辑电路 ,但这种时序逻辑电路只包含存储电路。

有:eax   ebx    ecx     edx     ebp     esp

ebp与esp这两个寄存器中存放的是地址,这两个地址是用来维护函数栈帧的。


举例说明

我们可以深入探究下函数调用在内存空间中到底是怎么运转的

我们可以以下面代码为例来分析

#define _CRT_SECURE_NO_WARNINGS 1
#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函数是不是也有可能被其他函数调用那。

我们可以看出在vs2013中mainCRTStartup调用_tmainCRTStartup,而_tmainCRTStartup调用main,可见main函数也是被调用的。

首先,创建一个_tmainCRTStartup函数栈帧,我们假设栈区下面为高地址,上面为地地址。


esp为栈顶指针,ebp为栈底指针


这样我们就可以进入,我们通过汇编代码可以看出第一步为push。

push为压栈操作,push的目标是ebp,所以压栈ebp,压完元素之后,esp移动到新的栈顶。压栈:给栈顶放一个元素进去 。出栈:从栈顶删除一个元素。


下一步是move,将ebp移动到esp

 


下一步是sub,sub是减的意思,意思是将esp减去0E4h(16进制数字),相当于往低地址方向移动

0E4h地址,此刻esp与ebp围成的紫色部分就是main函数的栈帧


然后是三个push分别将ebx esi edi从栈顶压入,最终esp移动到edi的上方


从lea到rep,这几步总的来说是将main函数栈帧里面都初始化“ccccccccccc” 


 以上就是main函数栈帧创建,接下来就是把值放进去,int a=10,dword是双字节的意思,将a的值放在ebp-8这个空间里


接下来就把b, c也像a一样分别放入对应的位置 


接下来就是传参,将ebp-14h也就是b的空间放入eax寄存器里面,再push一下放入栈顶

 


再传a,a也一样的道理


接下来就是call指令,call存放的是下一个指令的地址,方便函数返回时直接跳到下一指令

 


这下算是进入Add函数了创建Add函数栈帧与那main一样 先push ebp将main函数栈底指针地址通过这个元素储存起来方便返回时能找到main函数栈底指针


再move,sub将esp和ebp定义新的位置,再push三个元素ebx,esi,edi,最后再将Add函数栈帧初始化“CCCCCCCCC”


接着给z创建空间,ebp-8的位置


然后就是将传过去的b和a加起来储存在eax寄存器里面

 


接着将eax里面的值移动到z空间里(ebp-8),此时z空间的值是30,再将这个值放入eax寄存器中,这一步防止函数栈帧销毁时数据流失,所以将值保存在eax中


调用完就开始返回了,pop意思是跳出 ,把这三个元素先跳出


再将esp返回到ebp的位置


此刻esp指向的是我们先前放进的ebp在main函数底栈时的地址,把当时ebp在main函数底栈位置读取用pop,ebp又指向回了main函数的栈底,而esp继续停留这个位置


接着是ret指令,意思是返回到main函数,返回到call指令,而call指令储存的是下一个指令的地址,所以直接返回main函数call指令下一个指令也就是a传参的空间。此刻esp指向的就是a传参的空间。

 


 然后esp+8,跳出俩传参的空间


再三个pop,将edi,esi,ebx跳出去,到达main函数的空间。


最后将承载着z的值也就是两数和的值的寄存器eax,将值付给ebp-20h也就是c的地址

 此时c就为30了


 结论

局部变量是怎么创建的

创建好函数栈帧后,我们初始化一部分函数空间,而局部变量就在这个空间里分配一个空间,从而创建了局部变量

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

因为随机值是在我们创建函数栈帧时放进去的,函数空间里都是随机值,所以一定要初始化。

函数是怎么传参的,函数传参的顺序是什么

我们通过push将两个实参压栈,从而栈顶有了两个独立空间,将两个值放进去,创建好调用的函数栈帧后,通过指针的偏移量,实现传参。传参顺序从从右向左

形参和实参是什么关系

形参是实参的临时拷贝

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

我们通过push将当时edp在主函数栈底的地址压栈到一个空间,当我们返回指向这个空间是就能读取到主函数栈底的位置,再读取通过call指令存放下一个指令的地址,就直接返回主函数的栈帧里,返回值是通过寄存器存储,保护数据在调用的函数栈帧销毁时不丢失,再通过寄存器将值放入对应的主函数空间

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Linux操作系统基础(六):Linux常见命令(一)

文章目录 Linux常见命令 一、命令结构 二、ls命令 三、cd命令 四、mkdir命令 五、touch命令 六、rm命令 七、cp命令 八、mv命令 九、cat命令 十、more命令 Linux常见命令 一、命令结构 command [-options] [parameter]说明: command : 命令名, 相应功能的英文单词…

vue3 的setup和生命周期

vue3 的setup和生命周期 许多文章认为setup执行时间在beforeCreate 和created 之间&#xff0c;但是通过实际测试发现setup调用在beforecreate之前。 export default {beforeCreate() {console.log(beforeCreate running....);},created() {console.log("created runnin…

前端JavaScript篇之call() 和 apply() 的区别?

目录 call() 和 apply() 的区别&#xff1f; call() 和 apply() 的区别&#xff1f; 在JavaScript中&#xff0c;call()和apply()都是用来改变函数中this指向的方法&#xff0c;它们的作用是一样的&#xff0c;只是传参的方式不同。 call()方法和apply()方法的第一个参数都是…

【北邮鲁鹏老师计算机视觉课程笔记】01 introduction

1 生活中的计算机视觉 生活中的各种计算机视觉识别系统已经广泛地应用起来了。 2 计算机视觉与其他学科的关系 认知科学和神经科学是研究人类视觉系统的&#xff0c;如果能把人类视觉系统学习得更好&#xff0c;可以迁移到计算机视觉。是计算机视觉的理论基础。 算法、系统、框…

curl8.6.0 - CURLE_PEER_FAILED_VERIFICATION

文章目录 curl8.6.0 - CURLE_PEER_FAILED_VERIFICATION概述笔记END curl8.6.0 - CURLE_PEER_FAILED_VERIFICATION 概述 在看一个开源工程, 里面用到了curl和openssl, 但是工程使用vcpkg来管理的包, 用CMake来编译 依赖太多了, win10 编译选项为 vs2019 x64/Win32(或者Ninja)…

kaggle实战语义分割-Car segmentation(附源码)

目录 前言 项目介绍 数据集处理 数据集加载 定义网络 训练网络 验证网络 前言 本篇文章会讲解使用pytorch完成另外一个计算机视觉的基本任务-语义分割。 语义分割是将图片中每个部分根据其语义分割出来&#xff0c;其相比于图像分类的不同点是&#xff0c;图像分类是对…

Windows下搭建Redis Sentinel

下载安装程序 下载Redis关于Windows安装程序&#xff0c;下载地址 下载成功后进行解压&#xff0c;解压如下&#xff1a; 配置redis和sentinel 首先复制三份redis.windows.conf&#xff0c;分别命名为&#xff1a;redis.6379.conf、redis.6380.conf、redis.6381.conf&…

【机器学习笔记】回归算法

回归算法 文章目录 回归算法1 线性回归2 损失函数3 多元线性回归4 线性回归的相关系数 1 线性回归 回归分析(Regression) 回归分析是描述变量间关系的一种统计分析方法 例&#xff1a;在线教育场景 因变量 Y&#xff1a;在线学习课程满意度 自变量 X&#xff1a;平台交互性、教…

《CSS 简易速速上手小册》第1章:CSS 基础入门(2024 最新版)

文章目录 1.1 CSS 语法和选择器&#xff1a;挑选你的画笔1.1.1 基础知识1.1.2 重点案例&#xff1a;创建一个响应式导航菜单1.1.3 拓展案例 1&#xff1a;为特定链接添加图标1.1.4 拓展案例 2&#xff1a;创建一个简单的问答折叠面板 1.2 盒模型的基础&#xff1a;构建你的乐高…

Linux 【docker系列1 - docker 安装与使用】

系列文章目录 文章目录 系列文章目录前言一、docker安装二、常用使用1.镜像相关2.读入数据 总结 前言 一、docker安装 docker的官方文档写的非常的详细&#xff0c;它包含了docker在各种环境下的安装&#xff0c;以及可能遇到的问题和解决方案。这里我们只描述docker在contOS上…

Excel+VBA处理高斯光束

文章目录 1 图片导入与裁剪2 获取图片数据3 数据拟合 1 图片导入与裁剪 插入图片没什么好说的&#xff0c;新建Excel&#xff0c;【插入】->【图片】。 由于图像比较大&#xff0c;所以要对数据进行截取&#xff0c;选中图片之后&#xff0c;点击选项卡右端的【图片格式】…

Qt QML学习(一):Qt Quick 与 QML 简介

参考引用 QML和Qt Quick快速入门全面认识 Qt Widgets、QML、Qt Quick 1. Qt Widgets、QML、Qt Quick 区别 1.1 QML 和 Qt Quick 是什么关系&#xff1f; 1.1.1 从概念上区分 QML 是一种用户界面规范和标记语言&#xff0c;它允许开发人员创建高性能、流畅的动画和具有视觉吸引…

pycharm deployment 灰色 一直无法点击

我的development的配置如下&#xff0c;我看了很多教程一直不知道为什么一直是灰色的&#xff0c; 文件夹配置&#xff1a; 如果你这里 Autodect&#xff0c;那么你Mapping 的文件夹应该是应该省略这个前缀的&#xff0c;例如我下面&#xff0c;我应该将本地文件夹映射到/home…

解析十六进制雷达数据格式:解析雷达FSPEC数据

以Cat62格式雷达数据为例&#xff0c;十六进制雷达数据部分代码&#xff1a; 3e0120bf7da4ffee0085 base_fspec_processor.h // // Created by qiaowei on 2024-02-03. //#ifndef RADARDATACONTROLLER_BASE_FSPEC_PROCESSOR_H #define RADARDATACONTROLLER_BASE_FSPEC_PROCESS…

音视频/流媒体协议和编码汇总

一、流媒体协议 1. RTMP/RTMPT/RTMPS/RTMPE 等多变种 是应用层协议&#xff0c;使用TCP作为底层传输协议&#xff0c;并提供了低延迟、高带宽利用率和实时性的特点。 (1)RTMP协议是Adobe的私有协议,未完全公开 (2)一般传输的是 flv&#xff0c;f4v 格式流 2. RTP/RTCP/SRTP …

【51单片机】LCD1602(可视化液晶屏)调试工具的使用

前言 大家好吖&#xff0c;欢迎来到 YY 滴 单片机系列 &#xff0c;热烈欢迎&#xff01; 本章主要内容面向接触过单片机的老铁 主要内容含&#xff1a; 欢迎订阅 YY滴C专栏&#xff01;更多干货持续更新&#xff01;以下是传送门&#xff01; YY的《C》专栏YY的《C11》专栏YY…

网络编程..

1.互联网 有了互联网的出现 我们就可以足不出户的实现看电影、购物等等操作 我们认知中可能的互联网模型 较为真实的互联网模型 那么数据是如何从一个设备传递到另外一个设备的呢&#xff1f; 2.网络互联模型 统共有三种&#xff1a; 3.TCP/IP协议 TCP/IP是一群协议 里面…

Debezium发布历史120

原文地址&#xff1a; https://debezium.io/blog/2022/04/07/read-only-incremental-snapshots/ 欢迎关注留言&#xff0c;我是收集整理小能手&#xff0c;工具翻译&#xff0c;仅供参考&#xff0c;笔芯笔芯. Read-only Incremental Snapshots for MySQL April 7, 2022 by K…

Amazon Dynamo学习总结

目录 一、Amazon Dynamo的问世 二、Amazon Dynamo主要技术概要 三、数据划分算法 四、数据复制 五、版本控制 六、故障处理 七、成员和故障检测 一、Amazon Dynamo的问世 Amazon Dynamo是由亚马逊在2007年开发的一种高度可扩展和分布式的键值存储系统&#xff0c;旨在解…

过渡效果的艺术:CSS transition 让网页交互更平滑(上)

&#x1f90d; 前端开发工程师、技术日更博主、已过CET6 &#x1f368; 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 &#x1f560; 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》 &#x1f35a; 蓝桥云课签约作者、上架课程《Vue.js 和 E…