我的编程空间,编程开发者的网络收藏夹
学习永远不晚

C语言函数栈帧的创建与销毁详解

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

C语言函数栈帧的创建与销毁详解

前言

大家在学习的时候一定有以下困惑: 局部变量是怎么创建的?为什么局部变量的值是随机值?函数是怎么传参?传参的顺序是怎样的?形参与实参是什么关系?函数调用是怎么做到的?函数调用完成不是销毁了吗,如何带回的返回值?

以上这些都可以通过了解函数栈帧的创建与销毁来理解。接下来我就带大家来了解函数栈帧的创建与销毁。

本次使用的编辑器是VS2013,因为越先进的编辑器,越不容易观察到底层。好了,我们回到正题。

一、函数栈帧是什么?

1.寄存器

寄存器里有eax,ebx,ecx,edx,ebp,esp等,我们今天要重点了解的是ebp与esp这两个寄存器。

2.ebp与esp

这两个寄存器中存放的是地址,整两个地址使用来维护函数栈帧的。每一个函数调用,都要在栈区创建一个空间,这块空间叫做函数栈帧,用esp与ebp来维护。

二、函数栈帧的创建

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

这个代码只是一个很简单的实现了加法函数,不用多说。

2.调用堆栈

接下来开始调试程序来看底层代码如何实现,首先打开调用堆栈

在这里插入图片描述

从这里可以清楚地知道,main函数之前还有两个函数在调用,所以大家平时认为的main函数就是最初的开始是错误的哦。

3.esp与ebp如何维护栈帧

在栈的使用中,是从高地址开始的。其中ebp指向栈底,esp指向栈顶。

在这里插入图片描述

main函数被调用后,程序会为main函数分配栈空间。接下来调试并右击鼠标转到反汇编。可以看到

在这里插入图片描述

这些代码的意思是

将ebp的值压栈,然后将esp赋给ebp,给esp减去0E4h的大小,之后分别将ebx,esi,edi压栈

压栈的意思是将元素放到栈顶。在上面调用堆栈可以看到main函数由__tmainCRTStartup调用。图解如下:

在这里插入图片描述

值得一提的是,在栈顶放元素是esp会自动指向新放元素的上方。

在这里插入图片描述

在这里插入图片描述


上图中我们很容易的看出在调用main函数是为main函数开辟的栈空间即栈帧,并且将esp的值给ebp,ebp和esp指向同一块空间,然后esp变小指向上面的区域,接下来将ebx,esi,edi压栈。

在这里插入图片描述

在这里插入图片描述

接下来这四句,lea是加载有效地址,从上图中,我们知道ebp指向的地址,那么edi存放的就是ebp-0E4h的地址也就是③esp处的地址,最后一句rep stos dword ptr es:[edi] 意思是从edi里面重复拷贝ecx次eax的内容。一次拷贝四个字节,dword是四个字节的意思。

在这里插入图片描述

接下来这三个汇编代码的意思就是将值放入相应的空间。至于为什么是为什么是ebp-8和ebp-20,这个和编译器有关,就不过多叙述。

在这里插入图片描述

在这里插入图片描述

由汇编代码可知,接下来就开始创建形式参数,将要传递的参数值存入eax与ecx这两个寄存器中并压入栈顶,所以创建的形式参数并不在add函数的函数栈帧哦,并且我们之前常说的形参是实参的一份临时拷贝无疑是非常正确的。

在这里插入图片描述

在这里插入图片描述

接下来开始add函数调用。call是调用的意思,后面是add函数的地址用来找到调用函数。这里值得一提的是call指令下一条指令的地址被存储来方便执行完add函数可以跳回来。

Add函数创建栈帧的过程其实和main函数一样的,先将ebp压栈方便找到指向main函数栈底的空间,再将esp的地址存放到ebp里面,此时,esp和ebp指向同一位置,再将esp上移0CCh个位置,然后就是ebx,esi,edi压栈,这里不多作说明,由下图可清晰理解:

在这里插入图片描述

在这里插入图片描述

接下来初始化z与执行加法也没什么要说的,z=x=y是找到之前创建的形参来进行加法。并将结果移动到z里。

在这里插入图片描述

返回z的操作是将z的值存放到eax这个寄存器中,所以函数销毁变量与返回的值这个操作并不冲突。

在这里插入图片描述

最后销毁add函数栈帧,pop就是弹出元素然后把元素放入后面的寄存器,每次pop都会销毁一个栈顶元素然后esp自动++往下挪移。三下pop之后要回收空间了,操作是把ebp的值传给esp这样esp指向的空间是main函数的栈顶,然后popebp这个操作会将之前栈底存放的之前存放的main函数的栈底指针传给ebp,这样ebp就指向了main函数的栈底。如下图:

在这里插入图片描述

接下来销毁main函数的操作也与之前一样,就不细说了。

总结 

本篇文章就到这里了,希望能够给你带来帮助,也希望您能够多多关注编程网的更多内容!        

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

C语言函数栈帧的创建与销毁详解

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

C语言函数栈帧如何创建和销毁

这篇文章主要为大家展示了“C语言函数栈帧如何创建和销毁”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“C语言函数栈帧如何创建和销毁”这篇文章吧。写在前面我们知道,每一次函数调用都需要在栈区上为其开
2023-06-29

如何进行C语言函数栈帧的创建和销毁分析

如何进行C语言函数栈帧的创建和销毁分析,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。以下是我们平时接触过,但不了解的问题:1.为什么局部变量在未赋值前是随机的。2.局部变量
2023-06-22

C语言堆栈帧的介绍与创建方式

本篇内容主要讲解“C语言堆栈帧的介绍与创建方式”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“C语言堆栈帧的介绍与创建方式”吧!什么是堆栈帧? 堆栈帧(stack frame)是一块堆
2023-06-20

怎么理解C语言的函数栈帧

本篇内容介绍了“怎么理解C语言的函数栈帧”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!一、函数栈帧的创建1.寄存器一般来说,计算机中的寄存器
2023-06-25

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录