返回顶部
首页 > 资讯 > 后端开发 > 其他教程 >C语言函数栈帧如何创建和销毁
  • 391
分享到

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

2023-06-29 05:06:52 391人浏览 独家记忆
摘要

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

这篇文章主要为大家展示了“C语言函数栈帧如何创建和销毁”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“C语言函数栈帧如何创建和销毁”这篇文章吧。

    写在前面

    我们知道,每一次函数调用都需要在栈区上为其开辟一块空间,这块空间就叫做这个函数的栈帧。

    而栈是从高地址向低地址延伸的。每个函数的每次调用,都有它自己独立的一个栈帧,这个栈帧中维持着所需要的各种信息。寄存器ebp指向当前的栈帧的底部(高地址),寄存器esp指向当前的栈帧的顶部(低地址)。

    这样我们就了解了寄存器ebp和寄存器esp中存放的是地址,这两个地址是用来维护函数栈帧的。比如:调用main函数, 我们为main函数分配栈帧空间, 那么栈帧维护如下:

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

    下面我们通过一段代码分析一下,函数栈帧创建和销毁的过程:(栈帧这部分内容在不同的编译器上实现存在差异, 但是思想大致都是一致的。本文是在vs2013编译器下实现的。)

    #include <stdio.h>int Add(int x, int y){int z = 0;z = x + y;return z;}int main(void){int a = 10;int b = 20;int ret = 0;ret = Add(a, b);//计算a+bprintf("%d\n", ret);return 0;}

    我们在调试过程打开调用堆栈

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

    可以看出,main函数是在__tmainCRTStartup函数内部被调用的,而__tmainCRTStartup函数又是在mainCRTStartup函数内部调用的。

    为了能更加清楚的看到栈帧创建和销毁的过程,我们转到上面代码对应的反汇编代码:

    int main(void){009D3F40  push        ebp  //将edp压入栈帧009D3F41  mov         ebp,esp  //将esp的值赋给edp009D3F43  sub         esp,0E4h  //esp-0E4h009D3F49  push        ebx  009D3F4A  push        esi  009D3F4B  push        edi  009D3F4C  lea         edi,[ebp+FFFFFF1Ch]  009D3F52  mov         ecx,39h  009D3F57  mov         eax,0CCCCCCCCh  009D3F5C  rep stos    dWord ptr es:[edi]  int a = 10;009D3F5E  mov         dword ptr [ebp-8],0Ah  int b = 20;009D3F65  mov         dword ptr [ebp-14h],14h  int ret = 0;009D3F6C  mov         dword ptr [ebp-20h],0  ret = Add(a, b);//计算a+b009D3F73  mov         eax,dword ptr [ebp-14h]  009D3F76  push        eax  009D3F77  mov         ecx,dword ptr [ebp-8]  009D3F7A  push        ecx  009D3F7B  call        009D11F9  009D3F80  add         esp,8  009D3F83  mov         dword ptr [ebp-20h],eax  printf("%d\n", ret);009D3F86  mov         esi,esp  009D3F88  mov         eax,dword ptr [ebp-20h]  009D3F8B  push        eax  009D3F8C  push        9D5860h  009D3F91  call        dword ptr ds:[009D9118h]  009D3F97  add         esp,8  009D3F9A  cmp         esi,esp  009D3F9C  call        009D1140  return 0;009D3FA1  xor         eax,eax  }009D3FA3  pop         edi  009D3FA4  pop         esi  009D3FA5  pop         ebx  009D3FA6  add         esp,0E4h  009D3FAC  cmp         ebp,esp  009D3FAE  call        009D1140  009D3FB3  mov         esp,ebp  009D3FB5  pop         ebp  009D3FB6  ret

    main函数的调用 main函数栈帧的创建

    经过刚才我们的理解,在准备调用main函数的时候,调用main函数的那个函数的栈帧已经开辟好了。

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

    然后将ebp压入栈帧,保存了指向栈底的ebp的地址,而此时esp指向新的栈顶位置;接着将esp的值赋给了ebp,产生了新的ebp;用esp减去一个16进制数0E4H(这里就是为main函数预开辟空间)。紧接着三个压栈指令,分别将ebx,esi,edi,压入栈帧。加载完有效地址以后,将为main函数预开辟空间全部初始化为0xCCCCCCCC。最后创建了三个局部变量a,b,ret并进行了初始化。

    Add函数的调用

    函数传参

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

    将b的值存入寄存器eax中,再将eax压入栈中;将a的值存入寄存器ecx中,再将将ecx压入栈中;这里看出参数是从右向左传递的。紧接着执行call指令,这里就是调用Add函数,同时将call指令的下一条指令的地址压入栈中,然后执行call指令的时候按F11 , 就进入了Add函数内部。

    Add函数栈帧的创建

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

    首先将main()函数的ebp压入栈,保存指向main()函数栈帧底部的ebp的地址,此时esp指向新的栈顶位置;将esp的值赋给ebp,产生新的ebp,即Add()函数栈帧的ebp;给esp减去一个16进制数0E4H,这里是为Add()函数预开辟空间;紧接着三个压栈指令,分别将ebx,esi,edi,压入栈帧。加载完有效地址以后,将为Add函数预开辟空间全部初始化0xCCCCCCCC。在紧接着创建了变量z,将形参的a和b相加的结果存储到z中;最后将结果存储到eax寄存器中,通过寄存器带回了函数的返回值。

    Add函数栈帧的销毁

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

    edi、esi、ebx依次出栈,esp 会向下移动;然后将ebp的值赋给esp,使esp指向ebp指向的地方;接着ebp 出栈,同时将出栈的内容给ebp,此时ebp又指向了main函数栈帧的底部,最后执行ret 指令,表示出栈一次,并跳转到出栈的内容的地址处,也就是call指令的下一条指令处。

    main函数栈帧的销毁

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

    main函数栈帧的销毁和Add函数栈帧销毁的过程的思想都是一样的,这里就不做多赘述了。

    以上是“C语言函数栈帧如何创建和销毁”这篇文章的所有内容,感谢各位的阅读!相信大家都有了一定的了解,希望分享的内容对大家有所帮助,如果还想学习更多知识,欢迎关注编程网其他教程频道!

    --结束END--

    本文标题: C语言函数栈帧如何创建和销毁

    本文链接: https://lsjlt.com/news/322692.html(转载时请注明来源链接)

    有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

    猜你喜欢
    • C语言函数栈帧如何创建和销毁
      这篇文章主要为大家展示了“C语言函数栈帧如何创建和销毁”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“C语言函数栈帧如何创建和销毁”这篇文章吧。写在前面我们知道,每一次函数调用都需要在栈区上为其开...
      99+
      2023-06-29
    • C语言函数栈帧的创建和销毁详解
      目录写在前面Add函数的调用函数传参Add函数栈帧的创建Add函数栈帧的销毁main函数栈帧的销毁总结写在前面 我们知道,每一次函数调用都需要在栈区上为其开辟一块空间,这块空间就叫做...
      99+
      2024-04-02
    • C语言函数栈帧的创建和销毁介绍
      在初学c语言中,很多时候要记的内容有点多,有时候并不能深入的了解它。关于函数的栈帧可以帮助我们深入了解函数传参的过程,让我们了解c语言。 以下是我们平时接触过,但不了解的问题: 1...
      99+
      2024-04-02
    • C语言函数栈帧的创建与销毁详解
      目录前言一、函数栈帧是什么?1.寄存器2.ebp与esp二、函数栈帧的创建1.代码块2.调用堆栈3.esp与ebp如何维护栈帧总结 前言 大家在学习的时候一定有以下困惑: ...
      99+
      2024-04-02
    • 如何进行C语言函数栈帧的创建和销毁分析
      如何进行C语言函数栈帧的创建和销毁分析,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。以下是我们平时接触过,但不了解的问题:1.为什么局部变量在未赋值前是随机的。2.局部变量...
      99+
      2023-06-22
    • c语言函数栈帧的创建和销毁过程详解
      目录1 相关知识介绍 1.1 寄存器1.2 函数栈帧概述2 栈帧创建与销毁过程1 相关知识介绍  1.1 寄存器 一般计算机内通用寄存器包括eax,ebx,ec...
      99+
      2024-04-02
    • C语言超详细讲解函数栈帧的创建和销毁
      目录1、本节目标2、相关寄存器3、相关汇编指令4、什么是函数栈帧5、什么是调用堆栈6、函数栈帧的创建和销毁(1)、main函数栈帧的创建与初始化(2)、main函数的核心代码(3)、...
      99+
      2024-04-02
    • C语言函数栈帧的创建与销毁原理图解
      目录什么是函数栈帧什么是栈?与函数栈帧有关的汇编语句函数如何创建栈帧并销毁main函数栈帧开辟调用Add函数返回主函数什么是函数栈帧 我们在写C语言代码的时候,经常会把一个独立的功能...
      99+
      2024-04-02
    • C语言中函数栈帧的创建和销毁的深层分析
      目录一、本文目标二、基础知识1、寄存器2、代码案例  3、总体栈帧概况4、所需反汇编代码总览三、函数栈帧创建销毁过程1、_tmainCRTStartup函数(调用main函...
      99+
      2024-04-02
    • C语言详尽图解函数栈帧的创建和销毁实现
      目录常见寄存器基本的汇编语言知识具体实现关于栈帧创建与销毁的问答题注:本文章所使用的编译器是VS2010,由于不同编译器的函数栈帧与销毁略有差异,所以具体细节请读者自行实践! 常见寄...
      99+
      2024-04-02
    • C语言函数栈帧解析
      目录一、什么是函数栈帧 1.寄存器:2.函数栈帧 3.栈帧的作用和维护 4.栈帧结构二、函数栈帧的创建1.汇编代码2.main函数 2.栈帧创...
      99+
      2024-04-02
    • C语言函数栈帧详解
      目录前言一.函数栈帧是什么?二、栈帧准备知识1.内存分区2.什么是栈?三、详解栈帧创建与销毁全过程调用函数之前:将传入函数的值放入栈中函数执行:1.保护当前ebp2.创建所需调用函数...
      99+
      2024-04-02
    • C语言堆栈帧的介绍与创建
      什么是堆栈帧?        堆栈帧(stack frame)是一块堆栈保留区域,用于存放被传递的实际参数,子程序的返回...
      99+
      2024-04-02
    • 详细理解函C语言的函数栈帧
      目录一、函数栈帧的创建1.寄存器2.函数栈帧3.函数中调用函数二、函数栈帧的销毁总结一、函数栈帧的创建 1.寄存器 一般来说,计算机中的寄存器有六种 分别是:eax, ebx, e...
      99+
      2024-04-02
    • C语言堆栈帧的介绍与创建方式
      本篇内容主要讲解“C语言堆栈帧的介绍与创建方式”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“C语言堆栈帧的介绍与创建方式”吧!什么是堆栈帧?    &nb...
      99+
      2023-06-20
    • C语言超详细解析函数栈帧
      目录一、前面二、预备知识三、栈帧创建与销毁四、总结一、前面 本章将以汇编视角看函数栈帧的内存是如何使用与回收的,为了降低汇编语言的理解成本,以图示的方式讲解每一步汇编指令所带来的效果...
      99+
      2024-04-02
    • 怎么理解C语言的函数栈帧
      本篇内容介绍了“怎么理解C语言的函数栈帧”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!一、函数栈帧的创建1.寄存器一般来说,计算机中的寄存器...
      99+
      2023-06-25
    • C语言中单链表的基本操作(创建、销毁、增删查改等)
      目录链表分类单链表的介绍单链表的基本操作创建打印尾插头插尾删头删查找任意位置插入任意位置删除销毁完整代码总结链表分类 链表主要有下面三种分类方法: 单向或者双向带头或者不带头循环或者...
      99+
      2023-02-05
      C语言单链表 单链表的创建 单链表的销毁 单链表的增删查改
    • C语言深入讲解之从函数栈帧角度理解return关键字
      目录初识函数栈帧return个人总结环节初识函数栈帧 如上图可见,函数在被调用的时候会现在栈上开辟一个空间,我们称之为栈帧,之后函数内部的变量在这块区域进行空间开辟。 但是函数在调...
      99+
      2024-04-02
    • C语言栈和队列如何实现
      这篇文章主要讲解了“C语言栈和队列如何实现”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“C语言栈和队列如何实现”吧!一、栈与队列以及双端队列的概念1.1 栈的概念及结构栈:一种特殊的线性表,...
      99+
      2023-06-30
    软考高级职称资格查询
    编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
    • 官方手机版

    • 微信公众号

    • 商务合作