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

 更新时间:2022年05月20日 08:42:16   作者:头发没有代码多  
我们知道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函数进行维护

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

梳理一下上面的思路

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

main函数栈帧开辟

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

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

003118B0 push ebp

003118B1 mov ebp,esp

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

003118B3 sub esp,0E4h

003118B9 push ebx

003118BA push esi

003118BB push edi

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

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

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

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

调用Add函数

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

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

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

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

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

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

返回主函数

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

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

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

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

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

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

相关文章

  • c++拷贝构造函数防篡改示例

    c++拷贝构造函数防篡改示例

    这篇文章主要介绍了拷贝构造函数防篡改示例,需要的朋友可以参考下
    2014-04-04
  • C语言编写五子棋游戏

    C语言编写五子棋游戏

    这篇文章主要为大家详细介绍了C语言编写五子棋游戏,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-02-02
  • C++函数重载的定义与原因详解

    C++函数重载的定义与原因详解

    这篇文章主要为大家详细介绍了Python实现学生成绩管理系统,使用数据库,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-03-03
  • c语言printf函数的使用详解

    c语言printf函数的使用详解

    本篇文章是对c语言中printf函数的使用进行了详细的分析介绍,需要的朋友参考下
    2013-05-05
  • C语言中读写交替时出现的问题分析

    C语言中读写交替时出现的问题分析

    读写命令交替,一定要使用fseek重新定位,否则出现输入显示混乱,这篇文章主要介绍了C语言中读写交替时出现的问题分析,需要的朋友可以参考下
    2022-12-12
  • C+继承之同名覆盖,函数重写与多态详解

    C+继承之同名覆盖,函数重写与多态详解

    这篇文章主要介绍了C+继承之同名覆盖,函数重写与多态,是C++面向对象程序设计非常重要的概念,需要的朋友可以参考下,希望能够给你带来帮助
    2021-09-09
  • 一篇文章教你用C语言模拟实现字符串函数

    一篇文章教你用C语言模拟实现字符串函数

    这篇文章主要介绍了C语言模拟实现字符串函数,开发程序的时候经常使用到一些字符串函数,例如求字符串长度,拷贝字符串……,需要的朋友可以参考下
    2021-09-09
  • c语言snprintf函数的用法详解

    c语言snprintf函数的用法详解

    这篇文章主要给大家介绍了关于c语言snprintf函数用法的相关资料,snprintf()函数用于将格式化的数据写入字符串,文中通过代码介绍的非常详细,需要的朋友可以参考下
    2023-09-09
  • C语言职工信息管理系统源码

    C语言职工信息管理系统源码

    这篇文章主要为大家详细介绍了C语言职工信息管理系统源码,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-01-01
  • C++实现四则运算器(无括号)

    C++实现四则运算器(无括号)

    这篇文章主要为大家详细介绍了C++实现四则运算器,无括号的计算器,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-11-11

最新评论