【C语言】深入浅出讲解函数栈帧(超详解 | 建议收藏)
创始人
2024-05-08 22:46:29
0

在这里插入图片描述

🚀write in front🚀
📝个人主页:认真写博客的夏目浅石.
🎁欢迎各位→点赞👍 + 收藏⭐️ + 留言📝
📣系列专栏:凡人修C传
💬总结:希望你看完之后,能对你有所帮助,不足请指正!共同学习交流 🖊
✉️为什么我们不知疲倦,因为我们都在做自己所热爱的事 ♐

文章目录

  • 前言
  • 一、寄存器概念
    •  寄存器百度百科简介:
    •  寄存器最起码具备的4种功能
    •  寄存器的类型
    •  指针和变址寄存器
    •  两个特别的寄存器
  • 二、函数栈帧的指令介绍
    •  函数栈帧中的几个重要指令
    •  所用用到的指令
  • 三、函数栈帧的创建
    •   函数__tmainCRTStartup的建立
    •   main函数建立
    •   Add函数建立
  • 四、函数栈帧的销毁
  • 总结


前言

在这里插入图片描述

之前学习C语言函数递归的时候,遇到了许多的疑惑和困难,所以今天就讲一讲函数递归的一些基本原理—函数栈帧的创建与销毁,来揭开函数递归的神秘面纱。

   之前学习递归的时候产生的疑惑:

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

  而这些疑惑,今天我都会带着大家解开。并且今天的内容,建议使用的环境是Visual Studio 2013,建议不要使用太高级的编译器,因为我们在学习的过程中需要随时对我们的程序运行过程进行观测,而越是高级的编译器会自动优化,封装更加复杂,随之而来的就是越不容易学习和观察。

  并且,在不同的编译器下,函数调用过程中栈帧的创建和销毁大体逻辑上是相同的,但细节上是略有差异的,具体细节取决于编译器的实现。


一、寄存器概念

在这里插入图片描述

  在开始了解函数栈帧的创建与销毁之前,我们首先要了解一下计算机CPU内部的重要组成——寄存器

 寄存器百度百科简介:

  寄存器是CPU内部用来存放数据的一些小型存储区域,用来暂时存放参与运算的数据和运算结果。其实寄存器就是一种常用的时序逻辑电路,但这种时序逻辑电路只包含存储电路。寄存器的存储电路是由锁存器或触发器构成的,因为一个锁存器或触发器能存储1位二进制数,所以由N个锁存器或触发器可以构成N位寄存器。寄存器是中央处理器内的组成部分。寄存器是有限存储容量的高速存储部件,它们可用来暂存指令、数据和位址


 寄存器最起码具备的4种功能

  • 清除数码:将寄存器里的原有数码清除。
  • 接收数码:在接收脉冲作用下,将外输入数码存入寄存器中。
  • 存储数码:在没有新的写入脉冲来之前,寄存器能保存原有数码不变。
  • 输出数码:在输出脉冲作用下,才通过电路输出数码。

  仅具有以上功能的寄存器称为数码寄存器;有的寄存器还具有移位功能,称为—移位寄存器


 寄存器的类型

在这里插入图片描述

  • 通用寄存器组
  • 指针和变址寄存器
  • 段寄存器
  • 指令指针寄存器IP
  • 标志寄存器FR

 指针和变址寄存器

在这里插入图片描述


 两个特别的寄存器

  • EBP:扩展基址指针寄存器(extended base pointer),其内存放着一个指针,该指针永远指向系统栈最上面一个栈帧的栈底

  • ESP:扩展堆栈指针寄存器(extended stack pointer),其内存放着一个指针,该指针永远指向系统栈最上面一个栈帧的栈顶


二、函数栈帧的指令介绍

在这里插入图片描述

  对于每一个函数在进行创建和使用时,都会在内存中创建一块临时空间,并在临时空间内进行函数的处理。

  每一个函数被创建就会在栈上创建一块空间,并且会使EBP与ESP来进行维护,也就是说,ESPEBP是专门维护新创立的函数的。


 函数栈帧中的几个重要指令

  • push—学过c++的stl的同学我感觉应该熟悉,push意思就是推、压,这里就是创建一块空间。
  • sub—就是相减,作差。
  • mov—就是赋值的意思。
  • lea,mov,mov,rep stos的意思是,把lea这个为起始到reo stos这里之间的16进制数字,将第一个mov的值全部改写成第二个mov的值。
  • pop—学过stl的其实知道就是减,其实应用这里就是释放栈帧其实就是销毁。

 所用用到的指令

int main()
{
001C18B0  push        ebp  
001C18B1  mov         ebp,esp  
001C18B3  sub         esp,0E4h  
001C18B9  push        ebx  
001C18BA  push        esi  
001C18BB  push        edi  
001C18BC  lea         edi,[ebp-24h]  
001C18BF  mov         ecx,9  
001C18C4  mov         eax,0CCCCCCCCh  
001C18C9  rep stos    dword ptr es:[edi]  
001C18CB  mov         ecx,1CC008h  
001C18D0  call        001C131B  int a = 10;
001C18D5  mov         dword ptr [ebp-8],0Ah  int b = 20;
001C18DC  mov         dword ptr [ebp-14h],14h  int c = Add(a, b);
001C18E3  mov         eax,dword ptr [ebp-14h]  
001C18E6  push        eax  
001C18E7  mov         ecx,dword ptr [ebp-8]  
001C18EA  push        ecx  
001C18EB  call        001C10B4  
001C18F0  add         esp,8  
001C18F3  mov         dword ptr [ebp-20h],eax  printf("%d + %d = %d\n", a, b, c);
001C18F6  mov         eax,dword ptr [ebp-20h]  
001C18F9  push        eax  
001C18FA  mov         ecx,dword ptr [ebp-14h]  
001C18FD  push        ecx  
001C18FE  mov         edx,dword ptr [ebp-8]  
001C1901  push        edx  
001C1902  push        1C7B30h  
001C1907  call        001C10D2  
001C190C  add         esp,10h  return 0;
001C190F  xor         eax,eax  
}
001C1911  pop         edi  
001C1912  pop         esi  
001C1913  pop         ebx  
001C1914  add         esp,0E4h  
001C191A  cmp         ebp,esp  
001C191C  call        001C1244  
001C1921  mov         esp,ebp  
001C1923  pop         ebp  
001C1924  ret

  (一)这里先写一个程序以便于后续的讲解:

#includeint 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; 
}

  (二)这里根据VS2013就可以看到这里的指令

在这里插入图片描述

  这里是为了main函数做准备,所以下面就开始讲解函数栈帧的


三、函数栈帧的创建

在这里插入图片描述

  函数__tmainCRTStartup的建立

  (一) 指令1.push

在这里插入图片描述

  (二) 指令2.move

在这里插入图片描述

  (三) 指令3.sub

在这里插入图片描述

  (四) 指令4,5,6.push

在这里插入图片描述
前面指令的汇总:
在这里插入图片描述

  (五) 指令7,8,9,10

在这里插入图片描述

PS:mov39h个内容,全部改成0cccccccch
   dword是四个字节的意思

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


  main函数建立

在这里插入图片描述

  (一) 指令1.将0Ah赋值给[ebp-8]

  (二) 指令2.将14h赋值给[ebp-14h]

  (三) 指令3.将0赋值给[ebp-20h]

在这里插入图片描述


  Add函数建立


这里没见过的 详细讲,见过的就不说了。比如push
指令1.把[ebp-14h]放到eax
指令2.把[ebp-8]放到ecx
指令3.call指令
在这里插入图片描述
在这里插入图片描述

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

在这里插入图片描述
这里由于前面讲解,并且指令简单,所以就直接给大家上图啦~

在这里插入图片描述
  以上是整理栈帧建立的知识图谱


四、函数栈帧的销毁

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

  三连pop之后就是把我的ebp赋值给esp

在这里插入图片描述
  最后,执行最后一条ret指令,而此时 ret 指令要回到的,又恰恰是此前 call 指令存储在EBP弹出后变为栈顶的那个地址:00C21450

  然后按照指令依次释放就算是销毁了之前的函数栈帧,直到主函数的return 0


总结

  写到这里,函数栈帧的创建以及销毁算是讲完了,但是奈不住我讲的不好或者同学们没听懂,我的建议是给我提意见或者仔细多看几遍,这样才能学明白函数栈帧。

  我是夏目浅石,希望和你一起学习进步,刷题无数!!!希望各位大佬能一键三连支持一下博主,hhhh~我们下期见喽

在这里插入图片描述

✨原创不易,还希望各位大佬支持一下\textcolor{blue}{原创不易,还希望各位大佬支持一下}原创不易,还希望各位大佬支持一下

👍 点赞,你的认可是我创作的动力!\textcolor{9c81c1}{点赞,你的认可是我创作的动力!}点赞,你的认可是我创作的动力!

⭐️ 收藏,你的青睐是我努力的方向!\textcolor{ed7976}{收藏,你的青睐是我努力的方向!}收藏,你的青睐是我努力的方向!

✏️ 评论,你的意见是我进步的财富!\textcolor{98c091}{评论,你的意见是我进步的财富!}评论,你的意见是我进步的财富!

相关内容

热门资讯

甘肃武威市天祝县发生3.6级地...   中国地震台网正式测定:01月16日08时39分在甘肃武威市天祝县(北纬37.74度,东经102....
热评丨冰雪“冷资源”催生“热制...   雪地风筝、冰爬犁、雪圈追逐……大寒将至,各地冰雪活动异彩纷呈,冰雪经济正热气腾腾。我国冰雪旅游人...
星火成炬|打开世界的方式   同样的夜晚灯火,有人看到璀璨街景,有人感怀思念故乡;同样的树叶飘落,有人伤感时间流逝,有人想到生...
权威数读丨金融支持实体经济:效...   2025年中国金融总量较快增长、社会综合融资成本进一步降低、金融结构不断优化、金融市场平稳运行,...
视频丨日本民众集会反对政府推进...   14日,部分日本民众在首相官邸前举行集会,要求日本首相高市早苗立即撤回错误言论,强烈抗议日本政府...
【中国那些事儿】外资持续加码彰...   中国日报网1月15日电 新年伊始,外资企业纷纷加码中国市场,多家企业宣布增加投资或启动新设施规划...
新华社评论员:切实把党中央重大...   新华社北京1月14日电 题:切实把党中央重大决策部署贯彻落实好——二论学习贯彻习近平总书记在二十...
“十五五”开好局起好步丨冰面上...   今年是“十五五”开局之年,我国将出台智能网联新能源汽车产业发展规划,以此推动新能源汽车产业高质量...
“十五五”电网投资4万亿元,创...   国家电网公司全面贯彻习近平新时代中国特色社会主义思想,深入贯彻党的二十大和二十届历次全会精神,坚...
著名电影表演艺术家陶玉玲逝世 ...   总台记者获悉,著名电影表演艺术家陶玉玲于今天(1月15日)下午在北京去世,享年92岁。其代表作有...