服务器之家:专注于VPS、云服务器配置技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|VB|R语言|JavaScript|易语言|vb.net|

服务器之家 - 编程语言 - C/C++ - C语言函数栈帧的创建与销毁原理图解

C语言函数栈帧的创建与销毁原理图解

2022-12-06 14:10头发没有代码多 C/C++

我们知道c语言中函数都是被调用的,main函数里面能调用其他函数,其实main函数也是被别的函数调用的,下面通过本文给大家分享c语言函数栈帧的创建和销毁过程,一起看看吧

什么是函数栈帧

我们在写C语言代码的时候,经常会把一个独立的功能抽象为函数,所以C程序是以函数为基本单位的。

那函数是如何调用的?函数的返回值又是如何待会的?函数参数是如何传递的?这些问题都和函数栈帧有关系。

函数栈帧(stack frame)就是函数调用过程中在程序的调用栈(call stack)所开辟的空间,这些空间是用来存放:

  • 函数参数和函数返回值
  • 临时变量(包括函数的非静态的局部变量以及编译器自动生产的其他临时变量)
  • 保存上下文信息(包括在函数调用前后需要保持不变的寄存器)。

 

什么是栈?

栈(stack)是现代计算机程序里最为重要的概念之一,几乎每一个程序都使用了栈,没有栈就没有函 数,没有局部变量,也就没有我们如今看到的所有的计算机语言。

 

与函数栈帧有关的汇编语句

eax:通用寄存器,保留临时数据,常用于返回值

ebx:通用寄存器,保留临时数据

ebp:栈底寄存器

esp:栈顶寄存器

eip:指令寄存器,保存当前指令的下一条指令的地址

mov:数据转移指令

push:数据入栈,同时esp栈顶寄存器也要发生改变

pop:数据弹出至指定位置,同时esp栈顶寄存器也要发生改变

sub:减法命令

add:加法命令

call:函数调用,1. 压入返回地址 2. 转入目标函数

jump:通过修改eip,转入目标函数,进行调用

ret:恢复返回地址,压入eip,类似pop eip命令(返回子程序)

 

函数如何创建栈帧并销毁

当程序进入main函数时,要给main函数在栈区创建空间,esp(栈顶)和ebp(栈底)对main函数进行维护

C语言函数栈帧的创建与销毁原理图解

当程序执行时,我们在调试窗口对堆栈段进行调用,我们可以看到main函数是被__tmainSRTStartup函数所调用,说明main函数是它的内部函数,而__tmainSRTStartup又是被mainCRStartup这个函数调用

C语言函数栈帧的创建与销毁原理图解

梳理一下上面的思路

C语言函数栈帧的创建与销毁原理图解

这些函数在堆栈当中的存储

C语言函数栈帧的创建与销毁原理图解

 

main函数栈帧开辟

接下来重新调试,我们转到反汇编

C语言函数栈帧的创建与销毁原理图解

调用main函数之前,esp和ebp对调用main函数的函数进行维护 ,当栈顶发生改变时,esp会指向新的栈顶

C语言函数栈帧的创建与销毁原理图解

003118B0 push ebp

003118B1 mov ebp,esp

先把ebp入栈,然后把ebp移动到esp的位置

C语言函数栈帧的创建与销毁原理图解

003118B3 sub esp,0E4h

003118B9 push ebx

003118BA push esi

003118BB push edi

之后又把esp往上移动,移动完把ebx,esi,edi压栈,esp和ebp现在指的这块空间是为main函数预先开辟好的

C语言函数栈帧的创建与销毁原理图解

C语言函数栈帧的创建与销毁原理图解

C语言函数栈帧的创建与销毁原理图解

把edi-0EFH也就是main函数开始的这里的地址,放到edi里面去,然后从这个地址开始赋值39次的双字节数据,赋值为CCCC

C语言函数栈帧的创建与销毁原理图解

到这里main函数栈帧开辟完成

C语言函数栈帧的创建与销毁原理图解

接下来就是在main函数的空间里,创建三个变量,并给赋值

C语言函数栈帧的创建与销毁原理图解

 

调用Add函数

C语言函数栈帧的创建与销毁原理图解

对函数进行传参,创建俩个临时变量,然后压栈进去

C语言函数栈帧的创建与销毁原理图解

C语言函数栈帧的创建与销毁原理图解

接下来进入call开始调用函数call此时的地址是00C2144B

C语言函数栈帧的创建与销毁原理图解

此时按下F11,我们发现call指令的下一条地址被压到了栈区

C语言函数栈帧的创建与销毁原理图解

把call的下一个地址压栈,ps:后面会用到这条指令,可先放在这不管

C语言函数栈帧的创建与销毁原理图解

接下来进入Add函数,跟前面main函数一样,先开辟空间,然后赋值为CCCCCC,再为变量在函数里创建空间并赋值

C语言函数栈帧的创建与销毁原理图解

接下来执行加法运算,由于刚才已经创建好了零时变量,所以把他俩进行相加,加完之后把结果传过来就行,传过来之后把这个值放在eax里面去

C语言函数栈帧的创建与销毁原理图解

 

返回主函数

按顺序出栈,之后把ebp赋值给esp

C语言函数栈帧的创建与销毁原理图解

C语言函数栈帧的创建与销毁原理图解

C语言函数栈帧的创建与销毁原理图解

之后pop,ebp把ebp进行出栈,ebp便回到main函数这里,ebp此时回到这里,esp也自然而然的往下指一个,ret指令是返回,然后esp来到了call指令的下一条指令

C语言函数栈帧的创建与销毁原理图解

C语言函数栈帧的创建与销毁原理图解

把栈顶指针弹出去,esp自然向下指一条

C语言函数栈帧的创建与销毁原理图解

C语言函数栈帧的创建与销毁原理图解

之后给esp加8即释放这俩个临时变量

C语言函数栈帧的创建与销毁原理图解

之后把eax放到ebp-20h,eax是存放刚才加法和的地方

C语言函数栈帧的创建与销毁原理图解

到此这篇关于C语言函数栈帧的创建与销毁原理图解的文章就介绍到这了,更多相关C语言函数栈帧内容请搜索服务器之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持服务器之家!

原文链接:https://blog.csdn.net/weixin_49449676/article/details/124508436

延伸 · 阅读

精彩推荐
  • C/C++C语言中获取文件状态的相关函数小结

    C语言中获取文件状态的相关函数小结

    这篇文章主要介绍了C语言中获取文件状态的相关函数小结,包括stat()函数和fstat()函数以及lstat()函数的使用,需要的朋友可以参考下...

    C语言教程网5442021-03-10
  • C/C++2~62位任意进制转换方法(c++)

    2~62位任意进制转换方法(c++)

    下面小编就为大家带来一篇2~62位任意进制转换方法(c++)。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧...

    jingxian12432021-05-19
  • C/C++Linux下C语言实现贪吃蛇小游戏

    Linux下C语言实现贪吃蛇小游戏

    这篇文章主要为大家详细介绍了Linux下C语言实现贪吃蛇小游戏,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...

    RICKO-_-4032021-10-28
  • C/C++详解C++ cin.getline函数

    详解C++ cin.getline函数

    这篇文章主要介绍了C++ cin.getline函数的相关资料,帮助大家更好的理解和学习C++,感兴趣的朋友可以了解下...

    chuyaoxin12072021-09-28
  • C/C++C++编程语言实现单链表详情

    C++编程语言实现单链表详情

    这篇文章主要介绍的是利用C语言实现单链表,实现的是链表中最简单的一种单链表且每个结点中只含有一个指针域,下面将详细举例说明,需要的朋友可以...

    tyl20215212022-01-19
  • C/C++详解C语言正确使用extern关键字

    详解C语言正确使用extern关键字

    这篇文章主要介绍了C语言正确使用extern关键字,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随...

    xingjiarong10652021-07-28
  • C/C++Qt学习笔记之QPalette调色板类

    Qt学习笔记之QPalette调色板类

    这篇文章主要为大家详细介绍了Qt学习笔记之QPalette调色板类,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...

    Saqino8692021-08-01
  • C/C++c语言求两个字符串的交集

    c语言求两个字符串的交集

    大家好,本篇文章主要讲的是c语言求两个字符串的交集,感兴趣的同学赶快来看一看吧,对你有帮助的话记得收藏一下,方便下次浏览...

    半夜偷吃雪糕5022022-08-07