C语言的函数栈帧

article/2025/10/18 19:45:48

⭐️前面的话⭐️

📒博客主页:未见花闻的博客主页
🎉欢迎关注🔎点赞👍收藏⭐️留言📝
📌本文由未见花闻原创,CSDN首发!
✉️坚持和努力一定能换来诗与远方!
💬参考在线编程网站:🌐牛客网🌐力扣
博主的码云gitee,平常博主写的程序代码都在里面。
博主的github,平常博主写的程序代码都在里面。
🙏作者水平很有限,如果发现错误,一定要及时告知作者哦!感谢感谢!


内容导读

  • 1.寄存器
  • 2.函数栈帧
    • 2.1函数栈帧的概述
    • 2.2函数栈帧创建过程
      • 2.2.1被调用的main函数
      • 2.2.2函数栈帧创建与销毁的过程

1.寄存器

寄存器是中央处理器内的组成部分。寄存器是有限存贮容量的高速存贮部件,它们可用来暂存指令、数据和地址。在中央处理器的控制部件中,包含的寄存器有指令寄存器(IR)和程序计数器(PC)。在中央处理器的算术及逻辑部件中,寄存器有累加器(ACC)。

本文不过多深入了解寄存器,只要知道寄存器集成在CPU之中和以下几个寄存器就可以了。
在这里插入图片描述

2.函数栈帧

2.1函数栈帧的概述

C语言中,每个栈帧对应着一个未运行完的函数。栈帧中保存了该函数的返回地址和局部变量。栈帧也叫过程活动记录,是编译器用来实现过程/函数调用的一种数据结构

函数栈帧的创建和销毁是基于栈所实现的。
所谓栈,是一种数据结构,具有先进后出的特点。在函数栈帧创建过程中,内存从高地址开始使用,越后面创建的函数栈帧或压栈数据,所存储的空间地址越低。
在这里插入图片描述
想要更深入了解这一数据结构,欢迎访问博主另一篇文章:栈和队列介绍和基本功能从理论到实践

2.2函数栈帧创建过程

2.2.1被调用的main函数

main函数是会被其他函数调用的,在不同编译器中调用main的函数也不同。
在VS2019中,main函数会被下面几个编译器内置的函数链式访问。
在这里插入图片描述
首先,这个invoke_main函数会返回main函数的返回值。

    static int __cdecl invoke_main(){return main(__argc, __argv, _get_initial_narrow_environment());}

然后会有一个名叫main_result的int const类型变量接收,invoke_main函数的返回值,也就是main函数的返回值,最后这个main_result会被编译器其他函数所使用。

	int const main_result = invoke_main();

在这里插入图片描述
在这里插入图片描述
函数栈帧的结构如下
esp为栈顶指针
ebp为栈底指针
它们共同维护函数栈帧
在这里插入图片描述

2.2.2函数栈帧创建与销毁的过程

对于函数栈帧的创建与销毁,我们以一个简单的程序为例。

#define _CRT_SECURE_NO_WARNINGS 1#include <stdio.h>int add(int a, int b)
{int d = a + a;return d;
}int main()
{int a = 2;int b = 6;int c = 0;c = add(a, b);printf("%d\n",c);return 0;
}

由于编译器中有其他函数调用main,所以在main函数栈帧创建前,编译器中调用main的函数栈帧就已经创建了,esp,ebp会在如图位置
在这里插入图片描述

00892580  push        ebp  //ebp压栈
00892581  mov         ebp,esp  //将esp的值赋给ebp
00892583  sub         esp,0E4h  //将esp的值减0E4h,也就是为main函数栈帧分配空间

在这里插入图片描述

00892589  push        ebx  //ebx压栈
0089258A  push        esi  //esi压栈
0089258B  push        edi  //edi压栈
0089258C  lea         edi,[ebp-24h]  
0089258F  mov         ecx,9  
00892594  mov         eax,0CCCCCCCCh  
00892599  rep stos    dword ptr es:[edi]  //将main初始函数栈帧全部初始化为0CCCCCCCCh

在这里插入图片描述

0089259B  mov         ecx,89C003h  
008925A0  call        0089130C  //进入main函数int a = 2;
008925A5  mov         dword ptr [ebp-8],2  //ebp - 8就是a的位置,将a赋值为2int b = 6;
008925AC  mov         dword ptr [ebp-14h],6  //同理ebp - 14h为b的地址将b赋值为6int c = 0;
008925B3  mov         dword ptr [ebp-20h],0  //ebp - 20h为c的地址,c赋值为0

在这里插入图片描述

	c = add(a, b);
008925BA  mov         eax,dword ptr [ebp-14h] //传参,将b值传给add函数 ,先将b值传给eax
008925BD  push        eax  //eax压栈
008925BE  mov         ecx,dword ptr [ebp-8]  //传参,将a值传给add函数,先将a值传给ecx
008925C1  push        ecx  //ecx压栈

在这里插入图片描述

008925C2  call        00891023  //进入add
//带符号:008925C2  call        _add (0891023h) int add(int a, int b)
{
008917B0  push        ebp  //记录上一个ebp的地址
008917B1  mov         ebp,esp  //将ebp赋值成esp地址
008917B3  sub         esp,0CCh  //add函数栈帧
008917B9  push        ebx  
008917BA  push        esi  
008917BB  push        edi  
008917BC  lea         edi,[ebp-0Ch]  
008917BF  mov         ecx,3  
008917C4  mov         eax,0CCCCCCCCh  
008917C9  rep stos    dword ptr es:[edi]  //与main函数栈帧初始化同理,将add函数初始化为CC CC CC CC
008917CB  mov         ecx,offset _18BA86EA_test@c (089C003h)  
008917D0  call        @__CheckForDebuggerJustMyCode@4 (089130Ch)  
//008917C9  rep stos    dword ptr es:[edi]  
//008917CB  mov         ecx,89C003h  
//008917D0  call        0089130C  
//	int d = a + b;
//008917D5  mov         eax,dword ptr [a]  
//008917D8  add         eax,dword ptr [b]  
//008917DB  mov         dword ptr [d],eax  
//	return d;
//008917DE  mov         eax,dword ptr [d]  int d = a + b;
008917D5  mov         eax,dword ptr [ebp+8]  //将a赋值给eax
008917D8  add         eax,dword ptr [ebp+0Ch]  //将eax加上b,即2+6 = 8
008917DB  mov         dword ptr [ebp-8],eax  //将eax=8赋值给dreturn d;
008917DE  mov         eax,dword ptr [ebp-8]  //将d的值赋值给寄存器eax
}

在这里插入图片描述

008917E1  pop         edi  //出栈edi
008917E2  pop         esi  //出栈esi
008917E3  pop         ebx  //出栈ebx
008917E4  add         esp,0CCh  //将add函数销毁,esp回到ebp的位置
008917EA  cmp         ebp,esp  
008917EC  call        00891235  //回到main
008917F1  mov         esp,ebp  //将ebp的地址给esp
008917F3  pop         ebp  //出栈ebp,让ebp指向上一次地址位置
008917F4  ret  
008925C7  add         esp,8 // 销毁两个形参,esp指向main函数栈顶
008925CA  mov         dword ptr [ebp-20h],eax  //将eax(返回)值8赋值给ebp - 20h 也就是c

在这里插入图片描述
在这里插入图片描述

	printf("%d\n",c);
008925CD  mov         eax,dword ptr [ebp-20h]  //将c值赋给eax
008925D0  push        eax  
008925D1  push        897BCCh  
008925D6  call        008913A2  
008925DB  add         esp,8  return 0;
008925DE  xor         eax,eax  
}
//和add函数销毁一样,main函数销毁,结束程序
008925E0  pop         edi  
008925E1  pop         esi  
008925E2  pop         ebx  
008925E3  add         esp,0E4h  
008925E9  cmp         ebp,esp  
008925EB  call        00891235  
008925F0  mov         esp,ebp  
008925F2  pop         ebp  
008925F3  ret  
本篇文章如有错误,还请大佬指点!后续会慢慢优化!

http://chatgpt.dhexx.cn/article/3gHYNq6n.shtml

相关文章

【C语言】函数栈帧的创建和销毁(1)

前言&#xff1a; ❓ 在我们前期学习C语言时&#xff0c;你是否曾产生过很多困惑&#xff1f; &#x1f4ad; 比如&#xff1a;局部变量是怎么创建出来的&#xff1f;因为局部变量的值是随机值&#xff0c;我们建议将它初始化&#xff0c;那么为什么局部变量的值是随机值&am…

函数栈帧(详解版)

文章目录 前言1.浅谈C语言内存1.1 内存分配1.2 栈1.3 寄存器 2. 为main()函数开辟栈帧3.变量的初始化及函数调用4.ADD函数4.1 ADD函数的创建4.2 ADD函数使用与销毁 5.总结 前言 前期学习的时候&#xff0c;我们可能有很多困感? 比如: ●局部变量是怎么创建的?I为什么局部变量…

也谈栈和栈帧

&#xfeff;&#xfeff; 一个码农要是没遇见过coredump&#xff0c;那他就是神仙了。core file(coredump的转储文件)中保存的最重要内容之一&#xff0c;就是函数的call trace。还原这部分内容 (栈回溯) &#xff0c;并与原代码对应上&#xff0c;尽快找出程序崩溃的位置和…

(栈帧和函数调用一)栈帧,函数调用与栈的关系

&#xff08;栈帧和函数调用一&#xff09;栈帧&#xff0c;函数调用与栈的关系 一&#xff0c;栈帧的介绍二&#xff0c;函数调用与栈的关系三&#xff0c;汇编演示四&#xff0c;总结 在计算机科学中&#xff0c;栈是一个特殊的容器&#xff0c;用户可以将数据压入栈中&#…

理解栈帧和栈的运行原理

栈中的数据都是以栈帧&#xff08;Stack Frame&#xff09;的格式存在&#xff0c;栈帧是一个内存区块&#xff0c;是一个数据集&#xff0c;是一个有关方法 (Method) 和运行期数据的数据集&#xff0c;当一个方法A被调用时就产生了一个栈帧 F1&#xff0c;并被压入到栈中&…

函数栈帧的形成与释放

✅作者简介&#xff1a;嵌入式入坑者&#xff0c;与大家一起加油&#xff0c;希望文章能够帮助各位&#xff01;&#xff01;&#xff01;&#xff01; &#x1f4c3;个人主页&#xff1a;rivencode的个人主页 &#x1f525;系列专栏&#xff1a;玩转C语言 &#x1f4ac;推荐一…

【函数栈帧的创建和销毁】(超详细图解)

想必大家在学完C语言函数章节之后&#xff0c;是否有这样的困惑&#xff1a; 局部变量是怎么创建的 &#xff1f; 为什么局部变量的值是随机值 &#xff1f; 函数是怎么传参的&#xff1f;传参的顺序又是什么样的 &#xff1f; 形参和实参是什么关系 &#xff1f; 函数调用…

C语言函数栈帧详解

系列文章目录 前言 最近正在学习栈帧方面的知识&#xff0c;由于本人对汇编不太熟悉&#xff0c;对其中频繁出现的ESP寄存器和EBP寄存器一直没搞清楚&#xff0c;在查找资料后&#xff0c;在此进行整理&#xff0c;方便以后温故知新。 一、预备知识 要清楚理解栈帧的概念&…

详解栈帧结构

https://www.1024do.com/?p367 栈帧结构 含义&#xff1a;C语言中&#xff0c;每个栈帧对应着一个未运行完的函数。栈帧中保存了该函数的返回地址和局部变量。栈帧也叫过程活动记录&#xff0c;是编译器用来实现过程函数调用的一种数据结构。 从逻辑上讲&#xff0c;栈帧就是…

函数栈帧详解

目录 一.什么是函数栈帧 1.寄存器&#xff1a; 2.函数栈帧 3.栈帧的作用和维护 4.栈帧结构 二.函数栈帧的创建 1.汇编代码 2.main函数函数栈帧的创建 1.汇编语言讲解&#xff1a; 2.栈帧创建&#xff1a; 3.详细步骤 3.ADD函数栈帧的创建 栈帧创建&#xff1a; 3.函…

栈帧

首先应该明白,栈是从高地址向低地址延伸的。每个函数的每次调用,都有它自己独立的一个栈帧,这个栈帧中维持着所需要的各种信息。寄存器ebp指向当前的栈帧的底部(高地址),寄存器esp指向当前的栈帧的顶部(地址地)。下图为典型的存取器安排,观察栈在其中的位置 入栈操…

什么是函数栈帧

函数栈帧的创建与销毁 一、函数栈帧的创建1.寄存器2.函数栈帧3.函数中调用函数 二、函数栈帧的销毁总结 一、函数栈帧的创建 1.寄存器 一般来说&#xff0c;计算机中的寄存器有六种 分别是&#xff1a;eax, ebx, ecx,edx,ebp,esp 而ebp,esp这两个寄存器中存放的是地址&#…

栈帧 stack frame

栈帧 stack frame 每一次函数调用都会维护一个栈帧&#xff08;stack frame&#xff09;&#xff0c;栈帧主要用于传递参数、保存返回地址、保存局部变量等。先直接上一个《深入理解计算机系统》上的原图。 其中&#xff0c;%rsp 指向栈顶位置&#xff0c;%rbp 指向栈底位置。…

C/函数栈帧

&#x1f331;博客主页&#xff1a;大寄一场. &#x1f331;系列专栏&#xff1a;C语言学习笔记 &#x1f618;博客制作不易欢迎各位&#x1f44d;点赞⭐收藏➕关注 ​ 目录 前言 寄存器 1. 寄存器的种类与功能 C语言汇编指令介绍 函数栈帧的创建与销毁过程 1.函数栈帧的…

浅谈函数栈帧(Stack Frame)

&#x1f499;作者&#xff1a;阿润菜菜 &#x1f4d6;专栏&#xff1a;C 本文目录 什么是栈帧 在调试中观察 总结 什么是栈帧 那我们先来看看什么是栈&#xff1a; 栈(stack)是限定仅在表尾进行插入或者删除的线性表。栈是一种数据结构&#xff0c;它按照后进先出的原则存储…

栈和栈帧

栈 堆栈(stack)又称为栈或堆叠&#xff0c;是计算机科学里最重要且最基础的数据结构之一&#xff0c;它按照FILO&#xff08;First In Last Out&#xff0c;后进先出&#xff09;的原则存储数据。 栈的相关概念&#xff1a; 栈顶和栈底&#xff1a;允许元素插入与删除的一端…

函数栈帧的创建和销毁(图解)

目录 基础知识介绍1. 寄存器的种类与功能2. 常用汇编指令3. 内存模型 演示函数栈帧的创建销毁过程1. 为main()函数开辟栈帧2. 在main()函数中创建变量3. 调用Add()函数前的准备4. 为Add()函数开辟栈帧5. 在Add()函数中创建变量并运算6. Add()栈帧的销毁7. 返回main()函数栈帧 总…

运行时栈帧结构是怎样的?

写在前面 本文隶属于专栏《100个问题搞定Java虚拟机》&#xff0c;该专栏为笔者原创&#xff0c;引用请注明来源&#xff0c;不足和错误之处请在评论区帮忙指出&#xff0c;谢谢&#xff01; 本专栏目录结构和文献引用请见100个问题搞定Java虚拟机 解答 栈帧(Stack Frame)是J…

函数栈帧(详细图解)

目录 一、栈 二、常用寄存器及简单汇编指令 三、理解栈帧 3.1 main函数栈帧创建 3.1.1 main函数栈帧创建动态演示 3.2 局部变量创建 3.2.1 局部变量创建动态演示 3.3 函数传参与调用 3.3.1 函数传参 3.3.2 函数传参动态演示 3.3.3 函数调用 3.3.4 函数返回 四、END…

栈帧详解——C语言进阶

目录 传统艺能&#x1f60e;过渡区&#x1f923;正片开始&#x1f440;寄存器&#x1f44f;main函数创建&#x1f44f;局部变量创建&#x1f44f;函数部分&#x1f44f;形参与实参&#x1f44f; 传统艺能&#x1f60e; 小编是大一菜鸟不赘述&#xff0c;欢迎大佬指点江山&…