当前位置: 首页 > news >正文

函数栈帧的创建和销毁——“C”

各位CSDN的uu们你们好呀,今天小雅兰来为大家介绍一个知识点——函数栈帧的创建和销毁。其实这个知识点,我们很早之前就要讲,但是因为我的一系列原因,才一直拖到了现在,那么,话不多说,让我们一起进入函数栈帧的世界吧

我们学习了前面这么多内容,不由得会想起几个问题:

  • 局部变量是如何创建的?
  • 为什么局部变量不初始化内容是随机的?
  • 函数调用时参数是如何传递的?传参的顺序是怎样的?
  • 函数调用是怎么做的?
  • 函数的形参和实参分别是怎样实例化的?
  • 形参和实参的关系是什么?
  • 函数的返回值是如何带回的? 

带着这一肚子的疑惑,就有了今天的函数栈帧的创建和销毁了。


寄存器

什么是函数栈帧

什么是栈

解析函数栈帧的创建和销毁


首先,我还得给大家拓展一个知识点——寄存器

寄存器的功能是存储二进制代码,它是由具有存储功能的触发器组合起来构成的。一个触发器可以存储1位二进制代码,故存放n位二进制代码的寄存器,需用n个触发器来构成

按照功能的不同,可将寄存器分为基本寄存器移位寄存器两大类。

基本寄存器只能并行送入数据,也只能并行输出。

移位寄存器中的数据可以在移位脉冲作用下依次逐位右移或左移,数据既可以并行输入、并行输出,也可以串行输入、串行输出,还可以并行输入、串行输出,或串行输入、并行输出,十分灵活,用途也很广。

这边介绍一下寄存器的基本含义、基本概念、结构、工作原理、类型、存放代码满足条件、寄存器组织、寄存器寻址

 

 

 相关寄存器和汇编指令

 相关寄存器

 

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

 

相关汇编命令

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

 什么是函数栈帧

我们在写C语言代码的时候,经常会把一个独立的功能抽象为函数,所以C程序是以函数为基本单位的。

那函数是如何调用的?

函数的返回值又是如何带会的?

函数参数是如何传递的?

这些问题都和函数栈帧有关系。

函数栈帧(stack frame)就是函数调用过程中在程序的调用栈(call stack)所开辟的空间,这些空间是用来存放:

   

    函数参数和函数返回值

   

    临时变量(包括函数的非静态的局部变量以及编译器自动生产的其他临时变量)

   

    保存上下文信息(包括在函数调用前后需要保持不变的寄存器)。

看到这里,我们就必须还想到一个问题——什么是栈? 


什么是栈

栈(stack)是现代计算机程序里最为重要的概念之一,几乎每一个程序都使用了栈,没有栈就没有函数,没有局部变量,也就没有我们如今看到的所有的计算机语言。

在经典的计算机科学中,栈被定义为一种特殊的容器,用户可以将数据压入栈中(入栈,push),也可以将已经压入栈中的数据弹出(出栈,pop),但是栈这个容器必须遵守一条规则:先入栈的数据后出栈(First In Last Out, FIFO)。就像叠成一叠的术,先叠上去的书在最下面,因此要最后才能取出。

在计算机系统中,栈则是一个具有以上属性的动态内存区域。程序可以将数据压入栈中,也可以将数据从栈顶弹出。压栈操作使得栈增大,而弹出操作使得栈减小。

在经典的操作系统中,栈总是向下增长(由高地址向低地址)的。 在我们常见的i386或者x86-64下,栈顶由成为 esp 的寄存器进行定位的。

在了解了这些准备工作之后,我们就可以进入我们的正题啦——解析函数栈帧的创建和销毁 


解析函数栈帧的创建和销毁

首先我们达成一些预备知识才能有效的帮助我们理解,函数栈帧的创建和销毁。

 1. 每一次函数调用,都要为本次函数调用开辟空间,就是函数栈帧的空间。

 2. 这块空间的维护是使用了2个寄存器: esp 和 ebp ebp 记录的是栈底的地址, esp 记录的是栈顶的地址。

 3. 函数栈帧的创建和销毁过程,在不同的编译器上实现的方法大同小异,本次演示以VS2010为例。  

函数的调用堆栈

#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函数也确实被调用了

在VS2010中,main函数也是被其他函数调用的   __tmainCRTStartup  这个函数又是被调用的  mainCRTStartup

即,mainCRTStartup调用了__tmainCRTStartup,__tmainCRTStartup又调用了main函数

 

 现在转到我们的反汇编,把这个显示符号名的勾勾去掉,这样方便观察

 

 

 压栈(push)操作

 mov操作,表示把esp的值给ebp

 sub操作,表示esp的值减去0E4h

0E4h是一个十六进制数字,转为十进制为228

经过sub操作,esp的值就变了

 

 然后,esp就指向上面开辟的某一块空间了

 

 这一块空间,就是为我们的main函数预开辟的一块空间了,也就是main函数的栈帧

然后再是三个push操作,push了ebx、esi、edi

 

 

 再是lea操作,lea表示Load Effective Address,是为加载有效地址

 把[ebp+FFFFFF1Ch]的值加载到edi中,但是这个值不好观察,那我们还得把我们之前取消的显示符号名给勾上

 

 

这三个操作的意思是,把刚刚main函数的栈帧全部初始化为CCCCCCCC

dword的意思是double word(双字),一个字是两个字节,双字就是四个字节

 

 走了这么半天,竟然还没有执行一行有效的代码!!!

#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 ret = 0;ret = Add(a, b);printf("%d\n", ret);return 0;
}

 

 这就是我们的变量为什么要初始化的原因,如果不初始化的话,内存里面放的是一个随机值

 

接下来,就是调用函数

 

 

这几个动作就是在传参

 

 我们会发现,这个Add函数的指令和我们的main函数开始的指令几乎是一样的,这实际上就是在准备栈帧

 

 

其实初始化并不止这么多次,把33h这个十六进制数字换成十进制,是多少次就初始化多少次CCCCCCCC

 

 

通过画图,我们可以清楚地知道,并没有给形参创建空间,这也验证了我们之前的结论:实参传递给形参的时候,形参是实参的一份临时拷贝,改变形参是不会影响实参的

把[ebp-8]的值放到eax这个寄存器中

 

 

 

 


好啦,小雅兰今天的函数栈帧的创建和销毁的内容就到这里了,总体来说,我觉得这个内容比较地抽象,难度也是很大的,对于我们这种初学者来说,但是,不奢求一遍就把它看懂,但求每多看一遍,收获的知识点就多一点点,这样我就心满意足啦!!!

 

相关文章:

函数栈帧的创建和销毁——“C”

各位CSDN的uu们你们好呀&#xff0c;今天小雅兰来为大家介绍一个知识点——函数栈帧的创建和销毁。其实这个知识点&#xff0c;我们很早之前就要讲&#xff0c;但是因为我的一系列原因&#xff0c;才一直拖到了现在&#xff0c;那么&#xff0c;话不多说&#xff0c;让我们一起…...

腾讯云对象存储+企业网盘 打通数据链“最后一公里

对云厂商和企业用户来说&#xff0c;随着数据规模的快速增长&#xff0c;企业除了对存储功能和性能的要求不断增加&#xff0c;也越来越注重数据分发的效率。在传统数据分发的过程中&#xff0c;数据管理员往往需要先在存储桶下载对应的客户方案/交付资料&#xff0c;再使用微信…...

在浏览器输入url到发起http请求,这过程发生了什么

当用户输入url&#xff0c;操作系统会将输入事件传递到浏览器中&#xff0c;在这过程中&#xff0c;浏览器可能会做一些预处理&#xff0c;比如 Chrome 会根据历史统计来预估所输入字符对应的网站&#xff0c;例如输入goog&#xff0c;根据之前的历史发现 90% 的概率会访问「ww…...

PyTorch学习笔记:nn.ReLU——ReLU激活函数

PyTorch学习笔记&#xff1a;nn.ReLU——ReLU激活函数 torch.nn.ReLU(inplaceFalse)功能&#xff1a;逐元素应用ReLU函数对数据进行激活 函数方程&#xff1a; ReLU(x)(x)max⁡(0,x)ReLU(x)(x)^\max(0,x) ReLU(x)(x)max(0,x) 输入&#xff1a; inplace&#xff1a;是否改变输…...

同步线程

↵ 由于这节内容资料比较少&#xff0c;所以以下内容总结自Qt官方文献&#xff0c;在文章最后会给出相应链接。 线程的目的是允许并行运行&#xff0c;但有时线程必须停止等待其他线程。例如&#xff0c;如果两个线程尝试访问同一个变量&#xff0c;这样的话结果是未定义的。强…...

服务端返回内容跨域CORS之后,也在chrome/edge浏览器里显示出响应信息

由于浏览器的同源策略&#xff0c;服务端返回的内容跨域&#xff0c;且没有允许跨域CORS的请求头之后&#xff0c;浏览器无法显示出服务端返回的信息&#xff0c;不方便问题排查。比如&#xff1a;Access to XMLHttpRequest at http://localhost:6001/service-app/query/common…...

DHCP中继及配置

为什么需要DHCP Relay&#xff1f;产生背景解决方案DHCP Relay工作原理DHCP Relay配置实现产生背景 随着网络规模的扩大&#xff0c;网络中就会出现用户处于不同网段的情况。 这个时候客户A和客户B要请求IP地址时&#xff0c;首先会发送DHCP Discover广播包&#xff0c;这个广…...

中国社科院与美国杜兰大学金融管理硕士,让我们相遇在春暖花开时

在芸芸众生中&#xff0c;能拥有志同道合的朋友是一件多么幸运的事。人们常说&#xff1a;你是谁&#xff0c;就会遇见谁。走过半生才知道&#xff0c;看似命中注定的遇见谁、发生的事&#xff0c;其实都取决于自己。只有自己足够优秀&#xff0c;才能遇到更优秀的别人。在这个…...

MySQL---单表查询、多表查询

一、单表查询 素材&#xff1a; 表名&#xff1a;worker-- 表中字段均为中文&#xff0c;比如 部门号 工资 职工号 参加工作 等 CREATE TABLE worker ( 部门号 int(11) NOT NULL, 职工号 int(11) NOT NULL, 工作时间 date NOT NULL, 工资 float(8,2) NOT NULL, 政治面貌 v…...

3年自动化测试这水平?我还不如去招应届生

公司前段缺人&#xff0c;也面了不少测试&#xff0c;结果竟然没有一个合适的。一开始瞄准的就是中级的水准&#xff0c;也没指望来大牛&#xff0c;提供的薪资在10-20k&#xff0c;面试的人很多&#xff0c;但平均水平很让人失望。看简历很多都是3年工作经验&#xff0c;但面试…...

5 个自定义 React Hooks 将改变你的代码

昨天完成我的每日文章&#xff08;是的&#xff0c;我每天都会发布一篇关于前端开发的新文章&#xff0c;所以如果你想要每天的代码丸&#xff0c;请务必关注 &#x1f609;&#xff09;&#xff0c;我去编码了一点......我开始为我正在构建的副项目编写一些自定义挂钩&#xf…...

Java学习笔记-03(API阶段)

前言 目前我们看到的是Java基础部分的一个新的部分API,这是个啥,又能做啥呢? 其实可以概括成一句话:帮助我们站在巨人的肩膀上,实现更加高效的开发,那么我们来一探究竟吧~ API API&#xff08;Application Programming Interface&#xff0c;应用程序接口&#xff09;是一些预…...

Django自定义模板标签的使用详解

目录 1.创建子应用&#xff1a;python manage.py startapp test01 2.进行相关的配置 3.在新建的test01文件下创建urls.py(此处名称可变但注意上图) 4.在test01文件下创建名称为templatetags的文件夹 5.templatetags文件下继续创建几个py文件如下图​编辑 6.views视图函数…...

洗地机怎么选?洗地机品牌排行榜

洗地机的出现不仅能高效的清洁地面还能节省我们做家务的时间&#xff0c;对于上班族、有宠物的家庭以及宝妈来说简直不要太方便;目前市面上的洗地机有分有线款和无线款&#xff0c;无线款会比有线款操作更加方便;洗地机怎么选&#xff0c;其实洗地机的清洁能力主要是看吸力大小…...

CSS的元素显示模式

&#x1f60a;博主页面&#xff1a;鱿年年 &#x1f449;博主推荐专栏&#xff1a;《WEB前端》&#x1f448; ​&#x1f493;博主格言&#xff1a;追风赶月莫停留&#xff0c;平芜尽处是春山❤️ 目录 前言 一、什么是元素显示模式 1.1块元素 1.2行内元素 1.3行内块元素…...

【MySQL Shell】8.9.1 在 InnoDB ClusterSet 中隔离集群

在发生紧急故障切换后&#xff0c;如果 ClusterSet 的各个部分之间存在事务集不同的风险&#xff0c;则必须保护集群不受写入流量或所有流量的影响。 如果发生网络分区&#xff0c;则有可能出现脑裂的情况&#xff0c;即实例失去同步&#xff0c;无法正确通信以定义同步状态。…...

Ubuntu20.04+cuda11.2+cudnn8.1+Anaconda3安装tensorflow-GPU环境,亲测可用

(1)安装nvidia显卡驱动注意Ubuntu20.04和Ubuntu16.04版本的安装方法不同,安装驱动前一定要更新软件列表和安装必要软件、依赖&#xff08;必须&#xff09;sudo apt-get update #更新软件列表sudo apt-get install gsudo apt-get install gccsudo apt-get install make查看GP…...

剑指Offer 第27天 JZ75 字符流中第一个不重复的字符

字符流中第一个不重复的字符_牛客题霸_牛客网 描述 请实现一个函数用来找出字符流中第一个只出现一次的字符。例如&#xff0c;当从字符流中只读出前两个字符 "go" 时&#xff0c;第一个只出现一次的字符是 "g" 。当从该字符流中读出前六个字符 “google&…...

科研试剂供应1476737-97-9,Bis-PEG2-endo-BCN可发生点击反应

●外观以及性质&#xff1a;Bis-PEG2-endo-BCN一般为白色固体&#xff0c;BCN其为点击试剂&#xff0c;点击化学&#xff08;Click chemistry&#xff09;&#xff0c;又译为“链接化学”、“动态组合化学” &#xff08;Dynamic Combinatorial Chemistry&#xff09;、“速配接…...

Zabbix 构建监控告警平台(一)--部署安装

监控对象监控收集信息方式Zabbix 部署 1.监控对象 源代码: *.html *.jsp *.php *.py 数据库&#xff1a; MySQL,MariaDB,Oracle,SQL Server,DB2 应用软件&#xff1a;Nginx,Apache,PHP,Tomcat agent 集群&#xff1a; LVS,Keepalived,HAproxy…...

龙虎榜——20250610

上证指数放量收阴线&#xff0c;个股多数下跌&#xff0c;盘中受消息影响大幅波动。 深证指数放量收阴线形成顶分型&#xff0c;指数短线有调整的需求&#xff0c;大概需要一两天。 2025年6月10日龙虎榜行业方向分析 1. 金融科技 代表标的&#xff1a;御银股份、雄帝科技 驱动…...

《用户共鸣指数(E)驱动品牌大模型种草:如何抢占大模型搜索结果情感高地》

在注意力分散、内容高度同质化的时代&#xff0c;情感连接已成为品牌破圈的关键通道。我们在服务大量品牌客户的过程中发现&#xff0c;消费者对内容的“有感”程度&#xff0c;正日益成为影响品牌传播效率与转化率的核心变量。在生成式AI驱动的内容生成与推荐环境中&#xff0…...

【数据分析】R版IntelliGenes用于生物标志物发现的可解释机器学习

禁止商业或二改转载&#xff0c;仅供自学使用&#xff0c;侵权必究&#xff0c;如需截取部分内容请后台联系作者! 文章目录 介绍流程步骤1. 输入数据2. 特征选择3. 模型训练4. I-Genes 评分计算5. 输出结果 IntelliGenesR 安装包1. 特征选择2. 模型训练和评估3. I-Genes 评分计…...

Linux离线(zip方式)安装docker

目录 基础信息操作系统信息docker信息 安装实例安装步骤示例 遇到的问题问题1&#xff1a;修改默认工作路径启动失败问题2 找不到对应组 基础信息 操作系统信息 OS版本&#xff1a;CentOS 7 64位 内核版本&#xff1a;3.10.0 相关命令&#xff1a; uname -rcat /etc/os-rele…...

基于TurtleBot3在Gazebo地图实现机器人远程控制

1. TurtleBot3环境配置 # 下载TurtleBot3核心包 mkdir -p ~/catkin_ws/src cd ~/catkin_ws/src git clone -b noetic-devel https://github.com/ROBOTIS-GIT/turtlebot3.git git clone -b noetic https://github.com/ROBOTIS-GIT/turtlebot3_msgs.git git clone -b noetic-dev…...

浪潮交换机配置track检测实现高速公路收费网络主备切换NQA

浪潮交换机track配置 项目背景高速网络拓扑网络情况分析通信线路收费网络路由 收费汇聚交换机相应配置收费汇聚track配置 项目背景 在实施省内一条高速公路时遇到的需求&#xff0c;本次涉及的主要是收费汇聚交换机的配置&#xff0c;浪潮网络设备在高速项目很少&#xff0c;通…...

七、数据库的完整性

七、数据库的完整性 主要内容 7.1 数据库的完整性概述 7.2 实体完整性 7.3 参照完整性 7.4 用户定义的完整性 7.5 触发器 7.6 SQL Server中数据库完整性的实现 7.7 小结 7.1 数据库的完整性概述 数据库完整性的含义 正确性 指数据的合法性 有效性 指数据是否属于所定…...

怎么让Comfyui导出的图像不包含工作流信息,

为了数据安全&#xff0c;让Comfyui导出的图像不包含工作流信息&#xff0c;导出的图像就不会拖到comfyui中加载出来工作流。 ComfyUI的目录下node.py 直接移除 pnginfo&#xff08;推荐&#xff09;​​ 在 save_images 方法中&#xff0c;​​删除或注释掉所有与 metadata …...

MySQL的pymysql操作

本章是MySQL的最后一章&#xff0c;MySQL到此完结&#xff0c;下一站Hadoop&#xff01;&#xff01;&#xff01; 这章很简单&#xff0c;完整代码在最后&#xff0c;详细讲解之前python课程里面也有&#xff0c;感兴趣的可以往前找一下 一、查询操作 我们需要打开pycharm …...

保姆级【快数学会Android端“动画“】+ 实现补间动画和逐帧动画!!!

目录 补间动画 1.创建资源文件夹 2.设置文件夹类型 3.创建.xml文件 4.样式设计 5.动画设置 6.动画的实现 内容拓展 7.在原基础上继续添加.xml文件 8.xml代码编写 (1)rotate_anim (2)scale_anim (3)translate_anim 9.MainActivity.java代码汇总 10.效果展示 逐帧…...