深入理解C++函数栈帧

目录
  • 一、什么是函数栈帧
  • 二、具体原理
    • 2.1 main函数的调用
    • 2.2 sum函数的调用
  • 参考:

一、什么是函数栈帧

每一次函数调用都是一个过程,为函数开辟栈空间,用于本次函数调用中临时变量的保存、现场保护。这块栈空间我们称为函数栈帧。栈是从高地址向低地址延伸的。寄存器ebp指向当前的栈帧的底部(高地址),寄存器esp指向当前的栈帧的顶部(低地址)

注:esp:栈指针寄存器(extended stack pointer),其内存放着一个指针,该指针永远指向系统栈最上面一个栈帧的栈顶。
bsp:基址指针寄存器(extended base pointer),其内存放着一个指针,该指针永远指向系统栈最上面一个栈帧的底部。

入栈push和出栈pop

push ebp就等于将ebp的值保存到栈中,并且将当前esp下移

pop ebp就等于将ebp的值从栈中取出来,将ebp指向这个值

内存空间大致可以用下图表示:

二、具体原理

我们来通过运行程序来分析,有如下程序

 int sum(int _a, int _b)
 {
	 int res = 0;
	 res = _a + _b;

	 return res;
 }

 int main()
 {
	 int a = 10;
	 int b = 20;

	 int ret = sum(a, b);
	 printf("ret=%d\n", ret);
         return 0;
}

使用vs2017调试,查看反汇编

2.1 main函数的调用

main在调用之前如图:

2.2 sum函数的调用

sum函数在调用之前

sum函数内的内存分布

在上述的汇编码中我们可以看到在函数开始的时候,习惯上以这么l两段代码开始

push ebp  

mov ebp,esp

按照字面上理解,上面两句话的意思是将ebp推入栈中,之后让ebp等于esp

在函数调用之前,将调用者的函数(caller)的ebp存入栈,以便于在执行完毕后恢复现场;

下一步,sum函数必须为它的局部变量分配空间,同时,也必须为它可能用到的一些临时变量分配空间;

 sub esp, 0cch; // 减去的值根据程序而定;

之后会根据情况看是否保存某些特定的寄存器(EBX,ESI和EDI);

而ebp的值会保持固定,局部变量和临时存储则都可以通过基准指针ebp加偏移量找到;

在函数执行完毕,控制流返回到调用者的函数(caller)之前会进行下述操作

所谓有始有终,这是会还原上面保存的寄存器值,之后还原esp的值(上一个函数调用之前的esp被保存在固定的ebp中)与ebp值。这一过程被称为还原现场之后通过ret返回上一个函数。

参考:

https://blog.csdn.net/u011822516/article/details/20001765

https://blog.csdn.net/u012218309/article/details/81669227

https://www.cnblogs.com/sddai/p/9762968.html

https://blog.csdn.net/weixin_42572273/article/details/104611337

到此这篇关于深入理解C++函数栈帧 的文章就介绍到这了,更多相关C++函数栈帧 内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • C/C++多参数函数参数的计算顺序与压栈顺序的示例代码

    一.前言 今天在看Thinking in C++这本书时,书中的一个例子引起了我的注意,具体是使用了下面这句 单看这条语句的语义会发现仅仅是使用一个简单的string的substr函数将所得子串push_back到strings.但是在阅读时我却对于substr的参数传递产生了疑惑,到底是先执行了++current,还是先执行了last-current? 经过查阅资料,发现了两个相关知识点----参数的计算顺序与压栈顺序. 二.参数压栈顺序 C/C++中规定了函数参数的压栈顺序是从右至左,对于含

  • C/C++函数调用栈的实现方法

    本文实例讲述了C/C++函数调用栈的实现方法.可用于实现简单的脚本解释器.分享给大家供大家参考.具体实现方法如下: 头文件声明部分: 复制代码 代码如下: #pragma once const int BUFFERSIZE = 1024; const int growfactor = 2;   // this stack is used as call stack. class TStack{ private: size_t size;   // the stack length size_t

  • C++使用递归函数和栈操作逆序一个栈的算法示例

    本文实例讲述了C++使用递归函数和栈操作逆序一个栈的算法.分享给大家供大家参考,具体如下: 题目: 一个栈依次压入1.2.3.4.5,那么栈顶到栈底分别为:5.4.3.2.1. 将这个栈逆置后栈顶到栈底分别为1.2.3.4.5. 用递归函数来实现,不能用其他数据结构. 解题思路及代码 1.递归函数一:将栈的栈底元素一个个返回并移除. 2.递归函数二:逆序栈,调用递归函数一实现. C++实现: class Solution { public: //递归函数一 static int getAndRe

  • 深入理解C++函数栈帧

    目录 一.什么是函数栈帧 二.具体原理 2.1 main函数的调用 2.2 sum函数的调用 参考: 一.什么是函数栈帧 每一次函数调用都是一个过程,为函数开辟栈空间,用于本次函数调用中临时变量的保存.现场保护.这块栈空间我们称为函数栈帧.栈是从高地址向低地址延伸的.寄存器ebp指向当前的栈帧的底部(高地址),寄存器esp指向当前的栈帧的顶部(低地址) 注:esp:栈指针寄存器(extended stack pointer),其内存放着一个指针,该指针永远指向系统栈最上面一个栈帧的栈顶. bsp

  • C语言深入讲解之从函数栈帧角度理解return关键字

    目录 初识函数栈帧 return 个人总结环节 初识函数栈帧 如上图可见,函数在被调用的时候会现在栈上开辟一个空间,我们称之为栈帧,之后函数内部的变量在这块区域进行空间开辟. 但是函数在调用的时候,怎么知道需要开辟多大空间呢??? void func() { int a, b; double c, d, e; } 按照示例代码,会先对需要的内存空间大小进行预估,然后进行空间开辟. 函数返回时,栈帧会被释放,但是,虽然栈帧被释放,里面的内容是不会被清空的,下面通过以下的例子进行分析. #inclu

  • 详细理解函C语言的函数栈帧

    目录 一.函数栈帧的创建 1.寄存器 2.函数栈帧 3.函数中调用函数 二.函数栈帧的销毁 总结 一.函数栈帧的创建 1.寄存器 一般来说,计算机中的寄存器有六种 分别是:eax, ebx, ecx,edx,ebp,esp 而ebp,esp这两个寄存器中存放的是地址,与此同时,这两个地址是来维护函数栈帧的. 2.函数栈帧 每一个函数的调用,都需要在栈区为其开辟一个空间,这块为其开辟的空间就是函数栈帧. ebp:栈底指针 esp:栈顶指针 对于栈这种数据结构一共有两种栈操作 1.pop 出栈 2.

  • C语言函数栈帧详解

    目录 前言 一.函数栈帧是什么? 二.栈帧准备知识 1.内存分区 2.什么是栈? 三.详解栈帧创建与销毁全过程 调用函数之前: 将传入函数的值放入栈中 函数执行: 1.保护当前ebp 2.创建所需调用函数的栈帧空间 3.保存局部变量 4.参数运算 函数返回: 1.存储返回值 2.销毁空间 3.ebp回上一栈帧栈底 4.销毁形参 5.main函数拿到返回值 总结 前言 在c语言中我们会将一些功能单独写成一个函数,以供主函数调用,在表面来看调用的过程就是写出一个函数后,只需要在调用时中通过函数名将实

  • C语言函数栈帧的创建和销毁介绍

    在初学c语言中,很多时候要记的内容有点多,有时候并不能深入的了解它.关于函数的栈帧可以帮助我们深入了解函数传参的过程,让我们了解c语言. 以下是我们平时接触过,但不了解的问题: 1.为什么局部变量在未赋值前是随机的. 2.局部变量创建的过程. 3.函数传参,传参的顺序问题. 4.形参与实参的关系什么. 5.调用函数是怎么调用的,调用的过程是什么. 6.调用函数结束后,是怎样返回的. 这些问题我们在学校可能并不会接触,也不会出现在考试的试卷上,但是作为计算机专业的学生,做一些认识和了解是很有必要的

  • C语言函数栈帧的创建和销毁详解

    目录 写在前面 Add函数的调用 函数传参 Add函数栈帧的创建 Add函数栈帧的销毁 main函数栈帧的销毁 总结 写在前面 我们知道,每一次函数调用都需要在栈区上为其开辟一块空间,这块空间就叫做这个函数的栈帧. 而栈是从高地址向低地址延伸的.每个函数的每次调用,都有它自己独立的一个栈帧,这个栈帧中维持着所需要的各种信息.寄存器ebp指向当前的栈帧的底部(高地址),寄存器esp指向当前的栈帧的顶部(低地址). 这样我们就了解了寄存器ebp和寄存器esp中存放的是地址,这两个地址是用来维护函数栈

  • C语言函数栈帧的创建与销毁详解

    目录 前言 一.函数栈帧是什么? 1.寄存器 2.ebp与esp 二.函数栈帧的创建 1.代码块 2.调用堆栈 3.esp与ebp如何维护栈帧 总结 前言 大家在学习的时候一定有以下困惑: 局部变量是怎么创建的?为什么局部变量的值是随机值?函数是怎么传参?传参的顺序是怎样的?形参与实参是什么关系?函数调用是怎么做到的?函数调用完成不是销毁了吗,如何带回的返回值? 以上这些都可以通过了解函数栈帧的创建与销毁来理解.接下来我就带大家来了解函数栈帧的创建与销毁. 本次使用的编辑器是VS2013,因为越

  • C语言中函数栈帧的创建和销毁的深层分析

    目录 一.本文目标 二.基础知识 1.寄存器 2.代码案例 3.总体栈帧概况 4.所需反汇编代码总览 三.函数栈帧创建销毁过程 1._tmainCRTStartup函数(调用main函数)栈帧的创建 2.main函数栈帧的创建 3.main函数内执行有效代码(变量) 4.Add函数栈帧的创建 5.Add函数内执行有效代码 6.Add函数栈帧的销毁 7.main函数栈帧的销毁 四.总结 一.本文目标 1.局部变量是怎么创建的? 2.为什么局部变量的值是随机值? 3.函数是怎么传参的?传参的顺序是怎

  • c语言函数栈帧的创建和销毁过程详解

    目录 1 相关知识介绍 1.1 寄存器 1.2 函数栈帧概述 2 栈帧创建与销毁过程 1 相关知识介绍 1.1 寄存器 一般计算机内通用寄存器包括eax,ebx,ecx,edx,esi,edi,esp,edp,其中esp,ebp这两个寄存器是用来存放地址的,这两个地址就是用来维护函数栈帧的 1.2 函数栈帧概述 我们知道c语言中函数都是被调用的,main函数里面能调用其他函数,其实main函数也是被别的函数调用的.main函数是在 _tmainCRTSartup 函数中被调用的,_tmainCR

  • C语言函数栈帧解析

    目录 一.什么是函数栈帧 1.寄存器: 2.函数栈帧 3.栈帧的作用和维护 4.栈帧结构 二.函数栈帧的创建 1.汇编代码 2.main函数 2.栈帧创建: 3.步骤 4.ADD函数栈帧的创建 三.函数栈帧的销毁 1.汇编语言 四.了解 1.函数传参 2.函数返回值如何返回 3.函数中变量如何初始化和赋值 总结 一.什么是函数栈帧 1.寄存器: eax, ebx, ecx ... ebp - 存放了指向函数栈帧栈底的地址 esp - 存放了指向函数栈帧栈顶的地址 2.函数栈帧 函数被调用时,系统

随机推荐