函数栈帧的创建和销毁讲解

本文详细介绍了C语言中函数栈帧的概念及其作用,探讨了栈帧如何解决局部变量、参数传递和返回值的问题。通过解析栈的原理、相关寄存器及汇编指令,揭示了函数栈帧的创建与销毁过程,帮助读者理解函数调用的内部机制。
摘要由CSDN通过智能技术生成

本章主题:

什么是函数栈帧?

理解函数栈帧能解决什么问题?

函数栈帧的创建和销毁解析

1. 什么是函数栈帧

我们在写C语言代码的时候,经常会把一个独立的功能抽象为函数,所以C程序是以函数为基本单位的。那函数是如何调用的?函数的返回值又是如何带回的?函数参数是如何传递的?这些问题都和函数栈帧有关系。

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

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

2. 理解函数栈帧能解决什么问题呢?

理解函数栈帧有什么用呢?

只要理解了函数栈帧的创建和销毁,以下问题就能够很好的额理解了:

  • 局部变量是如何创建的?
  • 为什么局部变量不初始化内容是随机的?
  • 函数调用时参数时如何传递的?传参的顺序是怎样的?
  • 函数的形参和实参分别是怎样实例化的?
  • 函数的返回值是如何带回的?

让我们一起走进函数栈帧的创建和销毁的过程中。

3. 函数栈帧的创建和销毁解析

3.1 什么是栈?

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

在经典的计算机科学中,栈被定义为一种特殊的容器,用户可以将数据压入栈中(入栈,push),也可以将已经压入栈中的数据弹出(出栈,pop),但是栈这个容器必须遵守一条规则:先入栈的数据后出栈(First In Last Out, FIFO)。就像叠成一叠的术,先叠上去的书在最下面,因此要最后才能取出。

在计算机系统中,栈则是一个具有以上属性的动态内存区域。程序可以将数据压入栈中,也可以将数据从栈顶弹出。压栈操作使得栈增大,而弹出操作使得栈减小。

在经典的操作系统中,栈总是向下增长(由高地址向低地址)的。

在我们常见的i386或者x86-64下,栈顶由成为 esp 的寄存器进行定位。

3.2 认识相关寄存器和汇编指令

相关寄存器

相关寄存器 作用(简介)
eax 通用寄存器,保留临时数据,常用于返回值
ebx 通用寄存器,保留临时数据
ebp 栈底寄存器
esp 栈顶寄存器
eip 指令寄存器,保存当前指令的下一条指令的地址

相关汇编命令

相关汇编命令 作用(简介)
mov 数据转移指令
push 数据入栈,同时esp栈顶寄存器也要发生改变
pop 数据弹出至指定位置,同时esp栈顶寄存器也要发生改变
sub 减法命令
add 加法命令
call 函数调用,1. 压入返回地址 2. 转入目标函数
jump 通过修改eip,转入目标函数,进行调用
ret 恢复返回地址,压入eip,类似pop eip命令

3.3 解析函数栈帧的创建和销毁

3.3.1 预备知识

首先我们达成一些预备知识才能有效的帮助我们理解,函数栈帧的创建和销毁。

  1. 每一次函数调用,都要为本次函数调用开辟空间,就是函数栈帧的空间。

  2. 这块空间的维护是使用了2个寄存器: espebpebp 记录的是栈底的地址, esp 记录的是栈顶的地址。

如图所示:

在这里插入图片描述

  1. 函数栈帧的创建和销毁过程,在不同的编译器上实现的方法大同小异,本次演示以VS2019为例。

3.3.2 函数的调用堆栈

演示代码:

#include <stdio.h> 

int Add(int x, int y) 
{
    
    int z = 0; 
    z = x + y; 
    return z;
}

int main() 
{
    
    int a = 3;
    int b = 5; 
    int ret = 0; 
    ret = Add(a, b); 
    printf("%d\n", ret); 
    return 0; 
}

这段代码,如果我们在VS2019编译器上调试,调试进入Add函数后,我们就可以观察到函数的调用堆栈(右击勾选【显示外部代码】),如下图:

在这里插入图片描述

函数调用堆栈是反馈函数调用逻辑的,那我们可以清晰的观察到, main 函数调用之前,是由 invoke_main 函数来调用main函数。

invoke_main 函数之前的函数调用我们就暂时不考虑了。

那我们可以

  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Morning_Yang丶

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值