【函数栈帧解析:代码的迷人堆积和无限嵌套】(上)

简介: 【函数栈帧解析:代码的迷人堆积和无限嵌套】

本章重点


一、何为函数栈帧

二、函数栈帧特性 - 同栈 - 后进先出

三、认识内存空间布局图

四、认识相关寄存器

五、认识相关汇编命令

六、测试代码:

七、函数栈帧全过程


要解决的问题


  • 局部变量是怎么创建的?
  • 为什么局部变量的值是随机值?
  • 函数是怎么传参的?传参的顺序是怎么样的?
  • 形参和实参是什么关系?
  • 函数调用是怎么做的?
  • 函数调用结束后怎么返回的?


一、何为函数栈帧


 函数栈帧(Function Stack Frame),也被称为调用栈帧(Call Stack Frame),是在计算机程序中用于管理函数调用和执行的一种数据结构。每当函数被调用时,都会创建一个新的函数栈帧,用于存储该函数的局部变量、参数、返回地址和其他执行相关的信息。当函数执行完毕或返回时,相应的函数栈帧将被销毁,控制权回到上一个函数的栈帧中。


二、函数栈帧特性 - 同栈 - 后进先出


       函数栈帧的管理遵循一种后进先出(Last-In, First-Out,LIFO)的原则。这意味着最后调用的函数的栈帧会首先被执行,然后在函数返回时销毁,程序控制权回到上一个函数的栈帧中,以此类推,直到回到主程序的栈帧,整个程序执行完毕。


三、认识内存空间布局图



栈(Stack):


栈是一种线性数据结构,用于存储函数调用时的局部变量、函数参数以及函数调用的返回地址。

栈内存是有限的,以栈帧的方式分配和释放,遵循后进先出(Last-In, First-Out,LIFO)原则。

栈内存的生命周期与函数调用关联,当函数返回时,其栈帧上的数据会被销毁。


堆(Heap):


堆是一块较大的、动态分配的内存区域,用于存储程序运行时动态分配的数据,如动态分配的对象和数组。

堆内存的生命周期不受函数调用的影响,需要手动分配和释放,否则可能导致内存泄漏。

在C中,通常使用malloc()、calloc()和realloc()等函数来分配堆内存,使用free()来释放堆内存。


全局变量区(Global Variables):

全局变量区存储程序中的全局变量,这些变量在整个程序的生命周期内都可访问。

全局变量在程序启动时被分配,在程序结束时被释放。


常量区(Constants):

常量区存储常量数据,如字符串文字和全局常量。

这些数据在程序运行期间是只读的。


代码区(Code):

代码区存储程序的二进制代码,包括所有函数的机器代码。

代码区通常是只读的,不允许修改程序代码。


四、认识相关寄存器


  • eax:通用寄存器,保留临时数据,常用于返回值
  • ebx:通用寄存器,保留临时数据
  • ebp:栈底寄存器
  • esp:栈顶寄存器
  • eip:指令寄存器,保存当前指令的下一条指令的地址

注:ebp和esp主要用于维护当前存在的这个函数栈帧。


问:函数是被调用的,那main函数呢???它是谁调用的???


 在VS2013,main函数也是被其他函数调用的,该函数是_tmainCRTStartup,而该函数又是mainCRTStartup函数调用的,而mainCRTStartup函数则是由操作系统调用的。所以从编程者的角度来看,main函数似乎是程序的入口点,但实际上,在特定的编程环境中,它是由启动代码调用的。这些启动代码负责设置程序环境并确保main函数能够正确执行。


五、认识相关汇编命令


  • mov:数据转移指令
  • push:数据入栈,同时esp栈顶寄存器也要发生改变
  • pop:数据弹出至指定位置,同时esp栈顶寄存器也要发生改变
  • sub:减法命令
  • add:加法命令
  • call:函数调用,1. 压入返回地址 2. 转入目标函数
  • jump:通过修改eip,转入目标函数,进行调用
  • ret:恢复返回地址,压入eip,类似pop eip命令
  • lea:将表达式addr的值放入寄存器


六、测试代码:


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


七、函数栈帧全过程


1.ebp寄存器push压栈,同时esp栈顶寄存器地址值改变 - 变小



2.ebp寄存器数据转移到esp寄存器



3.0E4h的十进制是288,sub减法指令,此时开始创建main函数栈帧,main函数此时空间大小就是ebp寄存器-esp寄存器的差 = 0E4h



4.ebx寄存器,esi寄存器和edi寄存器push压栈,同时esp栈顶寄存器地址值改变 - 变小



5. 将表达式ebp-24h的值放入edi寄存器



【函数栈帧解析:代码的迷人堆积和无限嵌套】(下):https://developer.aliyun.com/article/1424913

相关文章
|
19天前
|
测试技术
函数式编程代码片段(无解析,代码纯享版)
函数式编程代码片段(无解析,代码纯享版)
24 0
|
3天前
|
JSON 监控 网络协议
局域网管理软件的DNS解析代码实践
本文介绍了如何使用Python实现DNS解析,通过示例代码展示了构建和解析DNS请求的过程。此外,还讨论了网络流量监控,利用psutil库获取网络接口的流量数据。最后,探讨了自动将监控数据提交到网站的方法,使用requests库将网络数据以JSON格式发送到指定网站。这些自动化工具提升了局域网管理效率和安全性。
209 1
|
5天前
|
C语言
C语言函数嵌套与递归调用的深入解析
C语言函数嵌套与递归调用的深入解析
13 0
|
5天前
|
存储 程序员 C语言
C语言中的嵌套语句与Switch语句的深入解析
C语言中的嵌套语句与Switch语句的深入解析
13 1
|
14天前
|
机器学习/深度学习 存储 并行计算
深入解析xLSTM:LSTM架构的演进及PyTorch代码实现详解
xLSTM的新闻大家可能前几天都已经看过了,原作者提出更强的xLSTM,可以将LSTM扩展到数十亿参数规模,我们今天就来将其与原始的lstm进行一个详细的对比,然后再使用Pytorch实现一个简单的xLSTM。
31 2
|
19天前
|
机器学习/深度学习 编解码
【论文笔记】图像修复MPRNet:Multi-Stage Progressive Image Restoration 含代码解析2
【论文笔记】图像修复MPRNet:Multi-Stage Progressive Image Restoration 含代码解析
27 2
|
19天前
|
机器学习/深度学习 计算机视觉
【论文笔记】图像修复MPRNet:Multi-Stage Progressive Image Restoration 含代码解析1
【论文笔记】图像修复MPRNet:Multi-Stage Progressive Image Restoration 含代码解析
25 1
【51单片机】烧写教程:将代码下载到单片机中(图示&解析)
【51单片机】烧写教程:将代码下载到单片机中(图示&解析)
|
19天前
|
C++
【期末不挂科-C++考前速过系列P6】大二C++实验作业-模板(4道代码题)【解析,注释】
【期末不挂科-C++考前速过系列P6】大二C++实验作业-模板(4道代码题)【解析,注释】
【期末不挂科-C++考前速过系列P6】大二C++实验作业-模板(4道代码题)【解析,注释】
|
19天前
|
Serverless C++ 容器
【期末不挂科-C++考前速过系列P5】大二C++实验作业-多态性(3道代码题)【解析,注释】
【期末不挂科-C++考前速过系列P5】大二C++实验作业-多态性(3道代码题)【解析,注释】

推荐镜像

更多