017+图解C语言中函数栈帧的创建与销毁(VS2022环境)

news2024/12/22 18:02:14

0.前言

您好,这里是limou3434的一篇个人博文,感兴趣的话您也可以看看我的其他文章。本次我将和您一起学习在C语言中函数栈帧的概念。

1.学习函数栈帧的意义

  • 局部变量是怎么穿创建的?为什么局部变量的值是随机的
  • 函数是怎么传参的?传参的顺序是怎么样的?
  • 形参和实参是什么关系?
  • 函数调用是怎么做的?函数调用时结束后怎么返回?

2.先不要使用太高级的编译器

编译器越高级就越难以观察到这些细节,因为有可能编译器做了非常高的封装,使得一些细节被其隐藏。但是使用新版本的编译器也行,有些时候大差不差。(例如本例中使用的VS2022在其汇编代码中,就有部分指令是VS2022自己加上的,这些指令对我们的学习暂时无关紧要,可以先忽略)

3.不同编译器函数调用中创建的栈帧有可能不同

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

4.计算机内的寄存器

计算机内部最常见的寄存器有“eax、ebx、ecx、edx”还有“ebp、esp”,最后两个寄存器存放的是地址,而这两个地址是用来维护函数栈帧的

5.调用main函数的函数

实际上是有函数来调用main函数的,这个函数就是“__tmainCRTStartup()”,而调用这个函数的函数是“mainCRTStartup()”,而调用这个函数的是操作系统

6.粗略解释函数栈帧的开辟和esp、ebp寄存器的使用

//源代码
#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;
}

如果把函数栈帧简单理解,则对于上面的代码就对应下面的函数栈帧建立图示过程

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
但是如果仅仅是这么讲是远远不够的,接下来我们来试试读读一些相关代码的汇编代码(哪怕您没有学过汇编也不必担心,只需看懂个大概即可)

7.详细解释函数栈帧的开辟和开寄存器的使用

下面的汇编代码不用细看,只是整理出来让您结合图解来分析函数栈帧开辟的细节,您可以看完图解再回到汇编代码来复习

  • C语言的源代码
//源代码
#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函数内部的汇编代码
int main()
{
00B518B0  push        ebp  
00B518B1  mov         ebp,esp  
00B518B3  sub         esp,0E4h  
00B518B9  push        ebx  
00B518BA  push        esi  
00B518BB  push        edi  
00B518BC  lea         edi,[ebp-24h]  
00B518BF  mov         ecx,9  
00B518C4  mov         eax,0CCCCCCCCh  
00B518C9  rep stos    dword ptr es:[edi]  
00B518CB  mov         ecx,0B5C008h  
00B518D0  call        00B5131B  
	int a = 10;
00B518D5  mov         dword ptr [ebp-8],0Ah  
	int b = 20;
00B518DC  mov         dword ptr [ebp-14h],14h  
	int c = 0;
00B518E3  mov         dword ptr [ebp-20h],0  

	c = Add(a, b);
00B518EA  mov         eax,dword ptr [ebp-14h]  
00B518ED  push        eax  
00B518EE  mov         ecx,dword ptr [ebp-8]  
00B518F1  push        ecx  
00B518F2  call        00B513B6  
00B518F7  add         esp,8  
00B518FA  mov         dword ptr [ebp-20h],eax  
	printf("%d\n", c);
00B518FD  mov         eax,dword ptr [ebp-20h]  
00B51900  push        eax  
00B51901  push        0B57B30h  
00B51906  call        00B510D2  
00B5190B  add         esp,8  
	return 0; 
00B5190E  xor         eax,eax  
}
00B51910  pop         edi  
00B51911  pop         esi  
00B51912  pop         ebx  
00B51913  add         esp,0E4h  
00B51919  cmp         ebp,esp  
00B5191B  call        00B51244  
00B51920  mov         esp,ebp  
00B51922  pop         ebp  
00B51923  ret  
//在调用Add函数时,其内部的汇编代码
int Add(int x, int y)
{
00221FF0  push        ebp  
00221FF1  mov         ebp,esp  
00221FF3  sub         esp,0CCh  
00221FF9  push        ebx  
00221FFA  push        esi  
00221FFB  push        edi  
00221FFC  lea         edi,[ebp-0Ch]  
00221FFF  mov         ecx,3  
00222004  mov         eax,0CCCCCCCCh  
00222009  rep stos    dword ptr es:[edi]  
0022200B  mov         ecx,22C008h  
00222010  call        0022131B  
	int z = 0;
00222015  mov         dword ptr [ebp-8],0  
	z = x + y;
0022201C  mov         eax,dword ptr [ebp+8]  
0022201F  add         eax,dword ptr [ebp+0Ch]  
00222022  mov         dword ptr [ebp-8],eax  
	return z;
00222025  mov         eax,dword ptr [ebp-8]  
}
00222028  pop         edi  
00222029  pop         esi  
0022202A  pop         ebx  
0022202B  add         esp,0CCh  
00222031  cmp         ebp,esp  
00222033  call        00221244  
00222038  mov         esp,ebp  
0022203A  pop         ebp  
0022203B  ret  

图解1(__tmainCRTStartup函数调用main函数)

在这里插入图片描述

图解2

在这里插入图片描述

图解3

在这里插入图片描述

图解4

在这里插入图片描述

图解5

在这里插入图片描述

图解6(main函数调用Add函数)

在这里插入图片描述

图解7

在这里插入图片描述

图解8

在这里插入图片描述

图解9

在这里插入图片描述

图解10

在这里插入图片描述

图解11

在这里插入图片描述

图解12

在这里插入图片描述

图解13

在这里插入图片描述

图解14

在这里插入图片描述

图解15

在这里插入图片描述

图解16

在这里插入图片描述
……后续步骤我不再给出,如果您完整的看过上面的图解后,就能很清晰的理解栈帧这一概念了,也能对后续没有做图解的汇编代码进行理解

8.总结

这次我采用绘图的方式帮助您了解函数创立栈帧的详细过程,还希望您能仔细地看下去,这是一个C程序员内功的一部分。

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

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

相关文章

满分Spring全家桶笔记:Spring+Spring Boot+Spring Cloud+Spring MVC

最近小编整理了一下一线架构师的Spring全家桶笔记&#xff1a;SpringSpring BootSpring CloudSpring MVC&#xff0c;分享给大家一起学习一下~ 01 Spring Spring是一个轻量级控制反转(IoC)和面向切面(AOP)的容器框架。Spring框架是由于软件开发的复杂性而创建的。Spring使用的…

nacos+frp穿透实现局域网调用

简介&#xff1a;首先你要有外网服务器。在外网服务器上安装frp服务端。然后在你想要调用的局域网电脑上安装frp客户端 frp下载链接 Releases fatedier/frp GitHub 外网服务器上我用的是docker安装的。你也可以直接下载并启动。这里我就不描述了。 首先我们先创建某个目录…

ESP32 ADC测量电压 arduino

ADC ADCESP32的ADC通道衰减倍数代码实现精度问题 ADC ADC&#xff08;模拟-数字转换器&#xff09;&#xff0c;首先了解模拟信号和数字信号之间的差异。模拟信号是连续的&#xff0c;可以在其范围内取无限个离散值&#xff0c;例如声音、光线等。 数字信号则是离散的&#xf…

Redis(三)常用配置解析

文章目录 度量单位引入其他配置文件启动时加载模块网路配置GENERAL 通用配置REPLICATION 主从复制相关配置安全配置AOF配置 提示&#xff1a;Redis 6.2.6版本 度量单位 注意&#xff1a;g和gb有区别&#xff0c;不区分大小写&#xff0c;1gb 1GB都是一样的。引入其他配置文件…

Qt编程基础 | 第三章-控件 | 3.3、对话框

一、QDialog 1.1、定义 对话框&#xff1a;在主窗口中操作&#xff0c;有可能触发某一个行为动作&#xff0c;会弹出一个新的对话窗口&#xff0c;解决一个临时性的会话&#xff0c;在对话窗口中执行某一个功能。QDialog可以作为自定义对话框的基类&#xff0c;同时Qt也提供了…

Hadoop部署本地模式

​ 本地模式&#xff0c;即运行在单台机器上。没有分布式的思想&#xff0c;使用的是本地文件系统。使用本地模式主要是用于对MapReduce的程序的逻辑进行调试&#xff0c;确保程序的正确性。由于在本地模式下测试和调试MapReduce程序较为方便&#xff0c;因此&#xff0c;这种模…

java实现大气质量插值图及六项污染物插值图图片导出

软件导出成果图效果 一、技术实现应用背景 大气污染是当今世界面临的一个严重问题。它不仅对人类健康造成了危害&#xff0c;还对环境和生态系统产生了负面影响。在许多地区&#xff0c;大气污染已经成为了日常生活中不可忽视的问题。 虽然大气污染的问题是复杂的&#xff0c;…

关于如何使用 python 下载CSV格式数据

本章节内容节自《python 编程从入门到实践》第十六章&#xff0c;我们将从网络上下载数据&#xff0c;并对数据进行可视化。就可以对其进行分析甚至观察其规律和关联。 学习目标 我们将访问并可视化以下两种常见格式存储的数据&#xff1a; CSV 使用 Python 模块 CSV 来处理以…

测试2年,26岁大龄程序员面试13家公司,拿下25K,差点被面试官KO了···

前言 我大概面试了13家公司&#xff0c;简历包装的是两年半测试经验&#xff0c;因为我的年纪已经是26岁&#xff0c;所以必须进行包装&#xff0c;这也并不是我想欺骗别人&#xff0c;而是现在无论干什么工作都需要有工作经验的&#xff0c;就连找个销售都要有工作经验的&…

Vue绑定class样式与style样式

1&#xff0c;回顾HTML的class属性 答&#xff1a;任何一个HTML标签都能够具有class属性&#xff0c;这个属性可能只有一个值&#xff0c;如class"happs"&#xff0c;也有可能存在多个属性值&#xff0c;如class"happs good blue"&#xff0c;js的原生DOM针…

STM32开发踩坑——芯片写保护解除

成立这个专栏的目的是&#xff0c;记录自己嵌入式开发遇到的问题&#xff0c;与成功的解决方法&#xff0c;方便自己回顾。 具体参考链接&#xff1a;STM32的Flash写了保护怎么办&#xff1f; 解决方法&#xff1a;在STLink连接目标板的情况下打开程序烧写软件ST-Link Utilit…

低代码开发迎来设备管理新时代:智能制造加速升级

随着智能制造时代的到来&#xff0c;制造业正在经历一场前所未有的变革。在这场变革中&#xff0c;设备管理平台和低代码开发已经成为了制造业的不二利器&#xff0c;帮助企业实现数字化转型&#xff0c;提高生产效率&#xff0c;降低成本&#xff0c;增强竞争力。 一、设备管…

OptaPlanner 中的hello world项目实战

实际操作步骤&#xff1a; 1.代码下载 下载下来的文件目录 2.使用编辑器打开hello-world项目 3.进行配置 配置JDK &#xff0c;File——》Settings File——》Project Structure 配置maven 说明&#xff1a;不用下载新的maven&#xff0c;用工具自带的&#xff0c;需要将sett…

旋翼无人机常用仿真工具

四旋翼常用仿真工具 rviz&#xff1a; 简单的质点&#xff08;也可以加上动力学姿态&#xff09;&#xff0c;用urdf模型在rviz中显示无人机和飞行轨迹、地图等。配合ROS代码使用&#xff0c;轻量化适合多机。典型的比如浙大ego-planner的仿真&#xff1a; https://github.c…

screen 的介绍及用法

screen 是什么 screen 是一种类似于终端模拟器的程序&#xff0c;允许你在一个终端窗口中创建和使用多个会话。这对于同时运行多个命令或任务非常有用&#xff0c;这样你就可以轻松地在它们之间切换&#xff0c;而不必依赖于多个终端窗口。此外&#xff0c;如果在ssh会话中运行…

HDMI之带宽计算

基本概念 像素时钟 英文 A pixel clock, also known as a dot clock, is a term commonly used in computer graphics and video display systems. It refers to the frequency at which pixels are displayed on a screen or monitor. The pixel clock determines the speed…

VMware是什么?VMware虚拟机最新安装教程

VMware Workstation是一款虚拟机软件&#xff0c;允许用户将Linux、Windows等多个操作系统作为虚拟机在单台PC上运行; 用户可以在虚拟机上重现服务器、桌面和平板电脑环境&#xff0c;无需重新启动即可跨不同操作系统同时运行应用。 通过对个人笔记本(PC)硬件资源的虚拟&#…

【zmq】REQ REP 模式

[c代码(https://github.com/dongyusheng/csdn-code/tree/master/ZeroMQ)zguide 官方有c++发布订阅:可以使用信封 发布订阅可以让消息一直流动请求应答是双向的,但是必须请求 应答 请求 应答 循环。简单的请求应答 requester 作为客户端以tcp连接到 reponderrequester zmq_sen…

自动化测试用例怎么写?最全自动化测试用例设计编写指南...

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 Python自动化测试&…

算法系列题目

文章目录 一. 下一个更大元素1. 下一个更大元素 Ⅰ2. 下一个较大元素II 二. 区间问题1. 贪心策略最少射箭问题无重叠区间合并区间划分字母区间 2. 差分数组 三. 设计类题目1. LRU(最近最少使用)缓存2. LFU(最不经常使用)缓存 一. 下一个更大元素 1. 下一个更大元素 Ⅰ 添加链…