C语言 —— 函数栈帧的创建和销毁
在我们之前学习函数的时候,我们可能有很多困惑?
比如:
- 局部变量是怎么创建的?
- 为什么局部变量的值是随机值?
- 函数是怎么传参的?传参的顺序是怎样的?
- 形参和实参是什么关系?
- 函数调用是怎么做的?
- 函数调用是结束后怎么返回的?
那么要解决这些问题, 我们就需要知道函数栈帧的创建和销毁.
本文的环境为VS2013, 注意函数栈帧创建和销毁的过程在不同编译器下是有略微差异的.
那么要想了解函数的栈帧, 就需要再了解一些前置知识.
1. 寄存器与函数栈帧的概念
寄存器是计算机体系结构中的一种关键元素,用于存储和处理数据。
常见的寄存器有eax, ebx, ecx, edx...这些寄存器在后文都会遇到. 我们要重点介绍两个寄存器, 一个是ebp, 一个是esp.
要想理解函数栈帧, 就必须了解ebp和esp这两个寄存器.
ebp, esp这两个寄存器中存放的是地址, 这两个地址是用来维护函数栈帧的.
那么这两个寄存器是怎么来维护函数栈帧的呢?
之前我们有提到, 每一个函数调用都要在栈区创建一个空间.
我们使用VS2013写下以下代码:
#include <stdio.h>int Add(int x, int y) {int z = 0;z = x + y;return z;
}int main() {int a = 10;int b = 10;int c = 0;c = Add(a, b);printf("%d\n", c);return 0;
}
我们知道,对于这样一个代码, 每一个函数的调用都要为它开辟一块内存空间.
2. Add程序的底层调用细节分析
接下来我们通过调试来展现上文的Add程序是如何调用的.
在VS2013编译器按下F10,此时不要动,右击鼠标转到反汇编.
此时,就能看到C语言所对应的反汇编代码.
我们来一步步调试并分析.
首先要知道的是main函数是被别人调用的, 在这个地方马上要进入main函数调用的时候另外调用main函数的函数栈帧已经创建好了.
接下来我们进入main函数,第一步为push(压栈)
注意此时esp地址应该是变小了, 如下图, F10往下走一步可以看到, esp地址变小.
接下来继续看.
ebp 压栈之后 mov ebp,esp
也就是把esp的值给ebp,即
接下来 sub减法 给 esp 减去 0E4h(16进制数字).
这意味着esp本来存的ebp的地址, 减0E4h之后地址变小, 指向上面某一块区域
接下来继续看.
接下来是3个push ebx esi edi. 与前面ebp类似
往下走.
往下.
走到这里,main函数的栈帧就开辟完成了.
接下来我们就要执行正式有效的代码, 也就是我们所编写的源代码.
这里是创建变量的时候给它赋值,int a = 10;
如果创建变量的时候没有给它赋值,那么这个地方就不会把10放进去.
那么内存中默认放的就是CCCCCCCC.
之前我们在内存中打印出了随机值”烫烫烫烫”,就出自于此.
这就是变量为什么要初始化如果不初始化,这里就放的是随机值.
思考: 当函数调用往下走的时候, 函数调用需要传参,它是如何传参的?
我们再接着往下.
后面可以看到Add函数是如何被创建与调用的, 又是如何进入Add函数, 回到main函数, 等各种问题.
此时要按F11 跳到这里,可以看到内存中多了一个00a61450,刚好就是上面call的下一条指令
那么就是 执行call指令的时候,把call指令的下一条指令的地址压栈
再按一次F11,就进到函数中了, 这次是真正来到Add函数中
接下来我们分析Add函数, 其实和main差不多.
接着往下看Add函数的执行.
接着往下
我们接着往下.
到这里,z还没有返回,那么我们往下走看一下是怎么返回结果z的
至此, Add程序的整个调用细节到此结束.
相关文章:

C语言 —— 函数栈帧的创建和销毁
在我们之前学习函数的时候,我们可能有很多困惑? 比如: 局部变量是怎么创建的?为什么局部变量的值是随机值?函数是怎么传参的?传参的顺序是怎样的?形参和实参是什么关系?函数调用是怎么做的?函数调用是结束后怎么返回的? 那么要解决这些问题, 我们就需要知道…...

Appleid苹果账号自动解锁改密(自动解锁二验改密码)
目前该项目能实现以下功能: 多用户使用,权限控制多账号管理账号分享页,支持设置密码、有效期、自定义HTML内容自动解锁与关闭二步验证自动/定时修改密码自动删除Apple ID中的设备代理池与Selenium集群,提高解锁成功率允许手动触发…...
Conflicting peer dependency: eslint@8.50.0
npm install 输出 npm ERR! code ERESOLVE npm ERR! ERESOLVE could not resolve npm ERR! npm ERR! While resolving: vue/eslint-config-standard6.1.0 npm ERR! Found: eslint-plugin-vue8.7.1 npm ERR! node_modules/eslint-plugin-vue npm ERR! dev eslint-plugin-vue…...
Vue3 defineProps使用
MyTag.vue <script setup> import { ref, nextTick, defineProps, defineEmits } from "vue"; const props defineProps({flag: Boolean,title: String, }); // 写成这样也可以 // const props defineProps(["flag", "title"]);const e…...

机器学习7:逻辑回归
一、说明 逻辑回归模型是处理分类问题的最常见机器学习模型之一。二项式逻辑回归只是逻辑回归模型的一种类型。它指的是两个变量的分类,其中概率用于确定二元结果,因此“二项式”中的“bi”。结果为真或假 — 0 或 1。 二项式逻辑回归的一个例子是预测人…...
生活小记-纸张尺寸
A系列纸张: A0:841 x 1189 毫米A1:594 x 841 毫米A2:420 x 594 毫米A3:297 x 420 毫米A4:210 x 297 毫米A5:148 x 210 毫米A6:105 x 148 毫米A7:74 x 105 毫米A8…...

【MATLAB源码-第41期】基于压缩感知算法的OFDM系统信道估计和LS算法对比仿真。
操作环境: MATLAB 2013b 1、算法描述 压缩感知(Compressed Sensing, CS)是一种从稀疏或可压缩信号中重构完整信号的数学理论和技术。下面详细介绍压缩感知和它在OFDM信道估计中的应用。 1. 压缩感知基本概念 在传统采样理论中࿰…...

优思学院|六西格玛将烹饪和美味提升至极致
最近,我们曾提到一个美国男子如何利用六西格玛来控制糖尿病。这表明六西格玛逐渐被认为是一个不仅可以在工作场所之外使用,尤其不仅限于制造业的系统。 六西格玛的核心理念是改进过程的质量,从而改善最终结果。如果你做了晚餐或尝试了一道新…...
git stash
git stash 是 Git 中一个非常有用的命令,用于临时保存当前工作目录中的修改,以便你可以切换到其他分支或处理其他任务而不丢失你的修改。它的主要用途是: 保存未提交的修改:你可以使用 git stash 命令将未提交的修改(包…...
Flink Data Source
Flink Data Source 一、内置 Data Source Flink Data Source 用于定义 Flink 程序的数据来源,Flink 官方提供了多种数据获取方法,用于帮助开发者简单快速地构建输入流,具体如下: 1.1 基于文件构建 1. readTextFile(path):按照 TextInputFormat 格式读取文本文件,并将…...

怒刷LeetCode的第23天(Java版)
目录 第一题 题目来源 题目内容 解决方法 方法一:贪心算法 方法二:动态规划 方法三:回溯算法 方法四:并查集 第二题 题目来源 题目内容 解决方法 方法一:排序和遍历 方法二:扫描线算法 方法…...

Golang 中的调试技巧
掌握有效的策略和工具,实现顺畅的开发 调试是每位开发人员都必须掌握的关键技能。它是识别、隔离和解决代码库中问题的过程。在 Golang 的世界中,掌握有效的调试技巧可以显著提升您的开发工作流程,并帮助您创建更可靠和健壮的应用程序。在本…...
linux 监控内存利用率
监控内存利用率 使用free来分析CPU使用信息 #!/bin/bashDATE$(date %F" "%H:%M)IP$(ifconfig eth0 |awk -F [ :] /inet addr/{print $4}) MAIL"examplemail.com"TOTAL$(free -m |awk /Mem/{print $2})USE$(free -m |awk /Mem/{print $3-$6-$7})FREE$(($TO…...

43 验证二叉搜索树
验证二叉搜索树 理解题意:验证搜索二叉树:中序遍历是升序题解1 递归(学习学习!)题解2 中序遍历(保持升序) 给你一个二叉树的根节点 root ,判断其是否是一个 有效的二叉搜索树。 有…...

深度学习笔记之微积分及绘图
深度学习笔记之微积分及绘图 学习资料来源:微积分 %matplotlib inline from matplotlib_inline import backend_inline from mxnet import np, npx from d2l import mxnet as d2lnpx.set_np()def f(x):return 3 * x ** 2 - 4 * xdef numerical_lim(f, x, h):retur…...

java Spring Boot按日期 限制大小分文件记录日志
上文 java Spring Boot 将日志写入文件中记录 中 我们实现另一个将控制台日志写入到 项目本地文件的效果 但是 这里有个问题 比如 我项目是个大体量的企业项目 每天会有一百万用户访问 那我每天的日志都记载同一个文件上 那不跟没记没什么区别吗? 东西怎么找&#x…...

CSS 语法
CSS 实例 CSS 规则由两个主要的部分构成:选择器,以及一条或多条声明: 选择器通常是您需要改变样式的 HTML 元素。 每条声明由一个属性和一个值组成。 属性(property)是您希望设置的样式属性(style attribute&#x…...

Vue3+TS+ECharts5实现中国地图数据信息显示
1.引言 最近在做一个管理系统,主要技术栈使用的是Vue3TSViteElementPlus,主要参考项目是yudao-ui-admin-vue3,其中用到ECharts5做数字大屏,展示中国地图相关信息,以此基础做一个分享,写下这篇文章。 &quo…...

PowerShell 内网不能直接安装SqlServer模块的处理办法
PowerShell 内网不能直接安装SqlServer模块的处理办法 文章目录 下载sqlserver module安装sqlserver module导入和验证sqlserver 模块推荐阅读 下载sqlserver module 首先先将sqlserver.nupkg下载到本地,我是放到了C:\windows\system32目录下。 PowerShell Galler…...

Git使用【下】
欢迎来到Cefler的博客😁 🕌博客主页:那个传说中的man的主页 🏠个人专栏:题目解析 🌎推荐文章:题目大解析(3) 目录 👉🏻标签管理理解标签标签运用 …...
uniapp 对接腾讯云IM群组成员管理(增删改查)
UniApp 实战:腾讯云IM群组成员管理(增删改查) 一、前言 在社交类App开发中,群组成员管理是核心功能之一。本文将基于UniApp框架,结合腾讯云IM SDK,详细讲解如何实现群组成员的增删改查全流程。 权限校验…...

第19节 Node.js Express 框架
Express 是一个为Node.js设计的web开发框架,它基于nodejs平台。 Express 简介 Express是一个简洁而灵活的node.js Web应用框架, 提供了一系列强大特性帮助你创建各种Web应用,和丰富的HTTP工具。 使用Express可以快速地搭建一个完整功能的网站。 Expre…...

【kafka】Golang实现分布式Masscan任务调度系统
要求: 输出两个程序,一个命令行程序(命令行参数用flag)和一个服务端程序。 命令行程序支持通过命令行参数配置下发IP或IP段、端口、扫描带宽,然后将消息推送到kafka里面。 服务端程序: 从kafka消费者接收…...
【服务器压力测试】本地PC电脑作为服务器运行时出现卡顿和资源紧张(Windows/Linux)
要让本地PC电脑作为服务器运行时出现卡顿和资源紧张的情况,可以通过以下几种方式模拟或触发: 1. 增加CPU负载 运行大量计算密集型任务,例如: 使用多线程循环执行复杂计算(如数学运算、加密解密等)。运行图…...

SpringCloudGateway 自定义局部过滤器
场景: 将所有请求转化为同一路径请求(方便穿网配置)在请求头内标识原来路径,然后在将请求分发给不同服务 AllToOneGatewayFilterFactory import lombok.Getter; import lombok.Setter; import lombok.extern.slf4j.Slf4j; impor…...
Java线上CPU飙高问题排查全指南
一、引言 在Java应用的线上运行环境中,CPU飙高是一个常见且棘手的性能问题。当系统出现CPU飙高时,通常会导致应用响应缓慢,甚至服务不可用,严重影响用户体验和业务运行。因此,掌握一套科学有效的CPU飙高问题排查方法&…...
高效线程安全的单例模式:Python 中的懒加载与自定义初始化参数
高效线程安全的单例模式:Python 中的懒加载与自定义初始化参数 在软件开发中,单例模式(Singleton Pattern)是一种常见的设计模式,确保一个类仅有一个实例,并提供一个全局访问点。在多线程环境下,实现单例模式时需要注意线程安全问题,以防止多个线程同时创建实例,导致…...

佰力博科技与您探讨热释电测量的几种方法
热释电的测量主要涉及热释电系数的测定,这是表征热释电材料性能的重要参数。热释电系数的测量方法主要包括静态法、动态法和积分电荷法。其中,积分电荷法最为常用,其原理是通过测量在电容器上积累的热释电电荷,从而确定热释电系数…...
掌握 HTTP 请求:理解 cURL GET 语法
cURL 是一个强大的命令行工具,用于发送 HTTP 请求和与 Web 服务器交互。在 Web 开发和测试中,cURL 经常用于发送 GET 请求来获取服务器资源。本文将详细介绍 cURL GET 请求的语法和使用方法。 一、cURL 基本概念 cURL 是 "Client URL" 的缩写…...
基于鸿蒙(HarmonyOS5)的打车小程序
1. 开发环境准备 安装DevEco Studio (鸿蒙官方IDE)配置HarmonyOS SDK申请开发者账号和必要的API密钥 2. 项目结构设计 ├── entry │ ├── src │ │ ├── main │ │ │ ├── ets │ │ │ │ ├── pages │ │ │ │ │ ├── H…...