函数栈帧的创建与销毁

函数栈帧的创建与销毁_第1张图片

文章目录

  • 函数栈帧的创建与销毁
  • 总结


函数栈帧的创建与销毁

  • 前置知识
    要想理解函数栈帧的创建与销毁的实现过程,我们要对一些寄存器和汇编指令有所了解
    如下:
    函数栈帧的创建与销毁_第2张图片

那么接下了,我们将通过简单的代码来理解函数栈帧的形成
代码如下:

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;
}

下面我将详细讲解Add函数的栈帧的创建与销毁过程。

  • 变量a,b,c的创建
    函数栈帧的创建与销毁_第3张图片
    mov(001718F5)指令是开辟四个字节大小的空间并将0Ah(十六进制)(也就是10)放入ebp-8(地址为0x00F8F74C)处
    mov(001718FC)指令是开辟四个字节大小的空间并将14h(十六进制)(也就是20)放入ebp-14h(地址为0x00F8F740)处
    mov(00171903)指令是开辟四个字节大小的空间并将0(十六进制)(也就是0)放入ebp-20h(地址为0x00F8F734)处
    如下:
    函数栈帧的创建与销毁_第4张图片
  • Add函数参数的形成

函数栈帧的创建与销毁_第5张图片
mov(0017190A)指令是将ebp-14h(变量b)的值赋给eax,push(0017190D)是将eax的值压入栈顶,esp寄存器大小-4。
mov(0017190E)指令是将ebp-8(变量a)的值赋给ecx,push(00171911)是将ecx的值压入栈顶,esp寄存器大小-4。
如下:
函数栈帧的创建与销毁_第6张图片

也就是说,函数参数的实例化是从左向右依次进行的。

  • Add函数的调用
    函数栈帧的创建与销毁_第7张图片
    call(00171912)指令是压入返回地址并跳转入目标函数,也就是先转入001710B9,再转入00171790,压入返回地址(00171917)。
    如下:
    函数栈帧的创建与销毁_第8张图片

  • Add函数栈帧的创建
    函数栈帧的创建与销毁_第9张图片
    push(00171790)指令压入ebp的值,保存ebp的返回地址。
    mov(00171791)指令将esp的值赋给ebp。
    sub(00171793)指令将esp-0CCh。
    push(00171799),push(0017179A),push(0017179B)就是分别压入ebx,esi,edi。
    如下:
    函数栈帧的创建与销毁_第10张图片

lea(0017179C)是加载有效地址,将ebp-0Ch的值放入edi中,mov(0017179F)将3放入ecx中,mov(001717A4)将0cccccccch的值放入eax中,rep stos(001717A9)从ebp到edi(ebp-0Ch),中的内容改为eax,循环ecx次。
如下:
函数栈帧的创建与销毁_第11张图片

至此,我们就理解了函数栈帧的创建。

  • Add函数内部语句的实现
    函数栈帧的创建与销毁_第12张图片
    mov(001717B5)开辟4个字节大小的空间并将0赋给ebp-8(变量z)处。
    add(001717BC)将ebp+8处(形参x)的值赋给eax,add(001717BF)让eax的值加上ebp+0Ch处(形参y)的值。
    mov(001717C2)将eax的值放入ebp-8处(变量z)。
    如下:
    函数栈帧的创建与销毁_第13张图片
    假如我们只是定义了变量z,而没有进行初始化,那么其z的值就是cc cc cc cc也就是随机值。也就是未初始化的局部变量的值是随机值。

  • Add函数的返回值
    函数栈帧的创建与销毁_第14张图片
    mov(001717C5)将ebp-8处(变量z)的值赋给eax,eax的值并不会随着函数的销毁而改变。

  • Add函数的销毁
    函数栈帧的创建与销毁_第15张图片
    pop(001717C8),pop(001717C9),pop(001717CA)连续弹出三次,并将值依次赋给edi,esi,edx。
    如下:
    函数栈帧的创建与销毁_第16张图片
    函数栈帧的创建与销毁_第17张图片
    mov(001717D8)将ebp的值赋给esp。Add的函数栈帧也就销毁了。
    如下:
    函数栈帧的创建与销毁_第18张图片

函数栈帧的创建与销毁_第19张图片
pop(001717DA)弹出此时esp的值,并赋给ebp。也就是将ebp在main函数的地址赋给ebp。
如下:

函数栈帧的创建与销毁_第20张图片

函数栈帧的创建与销毁_第21张图片

ret(001717DB)回复返回地址。返回到add(00171917)处,也就是call(00171712)指令压入的地址。
add(00171917)将esp的值加8。
mov(0017191A)就是将eax的值(0x0000001e)放入ebp-20h处(变量c)。
如下:
函数栈帧的创建与销毁_第22张图片

至此Add函数栈帧的创建与销毁就全部完成。


总结

以上就是我对于函数栈帧的创建与销毁的理解。如果有那里不对,请大佬们指出。感谢观看!!!
函数栈帧的创建与销毁_第23张图片

你可能感兴趣的:(算法,c语言,c++)