第6讲补充:函数的栈帧的创建和销毁

前言:这里补充的全是概念性的知识,基本上都是汇编语言的代码,可能文字理解比较费劲,大家多看几遍图解大概就明白了

该讲的需要弄懂的问题如下:

1 什么叫函数的栈帧

2 函数栈帧的创建是什么?

3 函数栈帧的销毁又是什么?

4 函数栈帧的创建和销毁有什么用?

先把这4个问题回答了:

想要理解函数栈帧首先要理解两个寄存器(也就是存储数据的单元,通俗来说就是存放地址的)

                                           ​​​​​​​        ​​​​​​​   一个是ebp

                                                      另一个esp

这两个寄存器是用来维护函数栈帧的。

之前讲过:每一个函数在调用过程中,都会在栈区创建一块空间,也叫函数栈帧的创建,每次调用完后,这个函数就没用了,系统就把它在内存中的空间销毁了,也叫函数栈帧的销毁

函数栈帧的创建和销毁便于系统对内存空间的管理,如果没用创建和销毁,那么系统内存的空间就会紊乱。

下面拿一个示例来阐述:

#define _CRT_SECURE_NO_WARNINGS 1
#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", c);
	return 0;
}

讲解示例反汇编语言的同时,我们先来看看数据在内存中存储时,是从高地址指向低地址的

下面讲解几种汇编语言常用的寄存器:

eax:通用寄存器,保留临时数据,常用于返回值
ebx:通用寄存器,保留临时数据
ebp:栈底寄存器
esp:栈顶寄存器
eip:指令寄存器,保存当前指令的下一条指令的地址
相关汇编指令:
mov:数据转移指令
push:数据入栈,同时esp栈顶寄存器也要发生改变
pop:数据弹出至指定位置,同时esp栈顶寄存器也要发生改变
sub:减法命令
add:加法命令
call:函数调用,1. 压入返回地址 2. 转入目标函数
jump:通过修改eip,转入目标函数,进行调用
ret:恢复返回地址,压入eip,类似pop eip命令
准备环境:
为了让我们研究函数栈帧的过程足够清晰,不要太多干扰,我们可以关闭下面的选项,让汇编代码中排
除一些编译器附加的代码:
然后将从main函数第一行开始调用函数,先按F10然后转到反汇编:
可以看到在调用main函数之前,先调用invoke_main()函数,先调用invoke_main()函数之前,又要调用 :tmainCRTStartup(void * __formal) 函数。
所以main函数不是第一个调用的函数,main函数也是受前面两个函数调用控制的。
函数栈帧的创建。
下面是核心代码
lea的意思是:load effective adderss 加载有效的指令,用于将内存中的地址加载到寄存器中,将内存地址与寄存器进行组合,从而获取指向内存中某个位置的指针。
函数栈帧的销毁:(函数调用完后就销毁了)

猜你喜欢

转载自blog.csdn.net/2301_79811170/article/details/134230773