函数栈帧的创建和销毁(图文详细)上

简介: 函数栈帧的创建和销毁(图文详细)上

预备知识:


相关汇编命令

mov:数据转移指令

push:数据入栈,同时esp栈顶寄存器也要发生改变

pop:数据弹出至指定位置,同时esp栈顶寄存器也要发生改变

sub:减法命令

add:加法命令

call:函数调用,1. 压入返回地址 2. 转入目标函数

jump:通过修改eip,转入目标函数,进行调用

ret:恢复返回地址,压入eip,类似pop eip命令


相关寄存器

eax:通用寄存器,保留临时数据,常用于返回值

ebx:通用寄存器,保留临时数据

ebp:栈底寄存器

esp:栈顶寄存器

eip:指令寄存器,保存当前指令的下一条指令的地址


什么是栈?


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


在经典的计算机科学中,栈被定义为一种特殊的容器,用户可以将数据压入栈中(入栈,push),也可以将已经压入栈中的数据弹出(出栈,pop),但是栈这个容器必须遵守一条规则:先入栈的数据后出栈(First In Last Out, FIFO)。

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


栈总是向下增长(由高地址向低地址)的。


相关知识


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

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

3.正在调用哪个函数,ebp,esp就维护哪个函数的栈帧

函数栈帧

什么是函数栈帧9600eaa14b8444b19ca2315f4e623b83.png

我们在写C语言代码的时候,经常会把一个独立的功能抽象为函数,所以C程序是以函数为基本单位的。

那函数是如何调用的?函数的返回值又是如何待会的?函数参数是如何传递的?这些问题都和函数栈帧有关系。


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

1.函数参数和函数返回值

2.临时变量(包括函数的非静态的局部变量以及编译器自动生产的其他临时变量)

3.保存上下文信息(包括在函数调用前后需要保持不变的寄存器)


下面用VS2013去演示,每个编译器产生的过程会有差异

演示代码:


#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);
  return 0;
}



函数的调用堆栈


首先按F10,进行编译,然后点击调试–>窗口–>调用堆栈

进入堆栈后可以看到main被调用ed34989bd141497b934ef83e25bd9d13.png

这时,我们会困惑main函数在被谁调用


继续按F10,让代码运行,当代b7ceac364e4c411ba2b1a8f257f72ea9.png码执行完时,会发现main函数被一个叫__tmainCRTStartup的函数调用

这里要知道一点:main函数也是被其他函数调用的


而__tmainCRTStaad13ccdec1cb48a4a4cd210f641378d8.pngrtup函数也97779b008c5949249da1637de28e2e99.png是被一个叫mainCRTStartup的函数调用

此时,我们可以获知一个大概的轮廓:

828089f35a0c45aa851e48cff1bcd0ae.png

转到反汇编


F10编译->单击右15ef0ff1ad6740e29a69f32a022aedc2.png键->转到反汇编


然后就可以看见代码对应的汇编代码


在进入main之前,mc8cdb237bffa49d3852bcd65db63db23.pngain就被__tmainCRTStartup调用,所以此时,走到了main函数中,所以__tmainCRTStartup的函数栈帧已经创建

f392a38498de4b0cba0ff74af1f3c1d0.png



1.执行00341410 push ebp 语句,把ebp的值压栈,同时esp指针向上移动,指向栈顶


c1e321da6f01454592fa3ffd69f12bc4.png


这里也可以通过监视窗口看到,执行push语句之后,esp的地址减小了,就说明esp向上移动了



a5645aba5ce5476dbeb230a764e51574.png




同时,在内存窗口中,也可以看到ebp的值被存到了esp指向的空间里·


3f45d812f92847b19a7a399a58573674.png



2.执行00341411 mov ebp,esp ,这句的作用是:把esp的值赋给ebp

此时esp,ebp的值相等



7a9e2df8401b4b95b842e536a460abda.png


694bd8e3b09246088461e0dd0b9e069a.png

3.执行00341413 sub esp,0E4h 语句,给esp的值减去0E4h


fbabbfcc88494ee69f2ea62ebdb241f9.png


,这就意味着esp指向上面的某一块区域,此时esp和ebp之间的空间,就是给main预开辟的空间


4a7e5d12282e4951be501c331ae73dd7.png



4.执行这段语句,在栈顶压入三个元素


2a6a95ea21ba47f2a2424f5d3062802a.png

5.0034141C lea edi,[ebp-0E4h] ,edi

6.00341422 mov ecx,39h 把39h这个值赋给ecx

7.00341427 mov eax,0CCCCCCCCh 把0CCCCCCCCh赋给eax

8.0034142C rep stos dword ptr162e063a8e0e4dd4988396c4809228f9.png es:[edi] 这句的意思是把从edi向下ecx(39h)大小的空间,改为eax的值,也就是0CCCCCCCCh



7b35727f30ee4d6bbfa37bceda6fec36.png



此时main的栈帧已经真正意义上开辟好了


48a9bbe39e94472da598a5b71d0af3aa.png



9.0034142E mov dword ptr [ebp-8],0Ah ,把0Ah的值放到[ebp-8]中去



727a4ca8e16f48ed9815fc410b254de9.png1851398a3ecc4cb79587aa0211011341.png





在程序中定义变量时进行了初始化,所以在相应位置把值存入栈中,如果没有初始化,栈中对应位置中的值就是cccccccccc,这也就是有时未初始化变量而导致打印烫烫烫烫烫烫烫烫烫烫烫烫的原因


10.00341435 mov dword ptr [ebp-14h],14h ,把14h的值放到[ebp-14h]中去


146c3f713e1449228cc90566efb2a0ec.png





11.0034143C mov dword ptr [ebp-20h],0 把0的值放到[ebp-20h]中去



8b4b5dbf8ea6467c845917d12f0db641.png




12.00341443 mov eax,dword ptr [ebp-14h] 把[ebp-14h]的值放到eax里,00341446 push eax 再把eax压入栈中




6b7d1d2ba51f4e3fb6087e6878a313a6.png



13.00341447 mov ecx,dword ptr [ebp-8] 把[ebp-14h]的值放到eax里,0034144A push ecx 再把ecx压入栈中




a289aab1ea1b436eb645bcbe235beece.png






12.13.步实际上是在传参,先压b,再压a,参数是从右往左传的


目录
相关文章
|
人工智能 Kubernetes Perl
2025 AI 原生编程挑战赛 术语说明与FAQ
本文档介绍了天池2025比赛的相关术语和一些疑问的解答。包括云监控平台(CloudMonitor 2.0)、日志服务(SLS)、观测数据租户(Workspace)、地域(Region)等平台与入口概念,并详解了Trace、Span、Log、Metric、Event等核心数据模型及其关键字段。文档还涵盖了PromQL告警规则、SPL日志查询、Kubernetes实体层级、诊断方法论术语等内容,同时提供了根因分析的命名规范、提交格式(JSONL)、时间窗口要求及常见问题解答,旨在帮助参赛者高效定位并解决系统故障。
678 2
|
Java 应用服务中间件 微服务
信创迁移适配实战-SpringBoot项目打包war部署至TongWeb7
信创迁移适配实战-SpringBoot项目打包war部署至TongWeb7
4250 0
信创迁移适配实战-SpringBoot项目打包war部署至TongWeb7
|
SQL 缓存 关系型数据库
技术好文:sqlx使用指南
技术好文:sqlx使用指南
342 0
|
人工智能
Coze 识别用户意图
Coze 识别用户意图
684 0
|
运维 监控 NoSQL
|
Java Spring
nssctf 逆向 周更 菜鸟
nssctf 逆向 周更 菜鸟
86 1
|
PHP
[SWPUCTF 2021 新生赛] ez_unserialize
[SWPUCTF 2021 新生赛] ez_unserialize
215 1
|
Windows 数据处理
WindowsAPI每日一练(1) MessageBoxA
WindowsAPI每日一练系列 :https://www.cnblogs.com/LexMoon/category/1246238.html  WindowsAPI每日一练(1) WinMain 要跟计算机进行交互,就需要计算机显示信息给人看到,或者发出声音给人听到,然后人看到或听到相应的信息后,再输入其它信息给计算机,这样就可以让计算机进行数据处理,把结果显示给我们。
6142 1
|
安全 测试技术 定位技术
【网络安全】渗透测试工具——Burp Suite(中)
【网络安全】渗透测试工具——Burp Suite(中)
1287 0
【网络安全】渗透测试工具——Burp Suite(中)
|
存储 机器学习/深度学习 编译器
函数栈帧深度剖析(一篇带你牢牢掌握函数栈帧)(一)
函数栈帧深度剖析(一篇带你牢牢掌握函数栈帧)(一)
1699 0