函数的栈帧的创建和销毁

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

文章目录

  • 1. 函数栈帧

1. 函数栈帧

我们知道寄存器有eax,ebx,ecx,edx,并且还有ebp,esp。其中ebp,esp这两个寄存器存放的是地址,这两个地址是用来维护函数栈帧的
我们知道,每一个函数调用,都要在栈区创建一个空间。

举个例子:
函数的栈帧的创建和销毁_第2张图片
我们知道main函数也会开辟自己的栈帧:
函数的栈帧的创建和销毁_第3张图片
那么main函数被调用了,是被谁调用了呢
函数的栈帧的创建和销毁_第4张图片
在VS2013中,main函数是被__tmainCRTStartup调用的,而__tmainCRTStartup是被mainCRTStartup调用的。所以,__tmainCRTStartup和mainCRTStartup也会被创建函数栈帧。

下面我们就开始详细讲解上面函数创建的过程
函数的栈帧的创建和销毁_第5张图片
在main被调用前,有esp和ebp来指向这个函数的栈帧。下面我们来看一下这个例子的反汇编:
函数的栈帧的创建和销毁_第6张图片
第一步将寄存器ebp给push到main函数的栈帧中:
函数的栈帧的创建和销毁_第7张图片
那么压栈是从高地址到低地址的,就说明esp的地址会从高变低:
在这里插入图片描述
在这里插入图片描述
第二步的意思是:把esp的值赋值给ebp:
函数的栈帧的创建和销毁_第8张图片
在这里插入图片描述
第三步给esp减去一个0E4h的值:
函数的栈帧的创建和销毁_第9张图片
这段空间就是给main函数申请的空间。后面三步是push三个值进去。
函数的栈帧的创建和销毁_第10张图片
lea的意思是:加载有效地址。这个步骤的意思是:将后面的值赋给epi。后面两个步骤也是赋值。rep stos意思是:从edi里面地址开始的39h个数据全部变成eax里面的数据。
函数的栈帧的创建和销毁_第11张图片
函数的栈帧的创建和销毁_第12张图片
然后将10放到ebp-8的位置上,把20放到ebp-14h上,把0放到ebp-20h上。
函数的栈帧的创建和销毁_第13张图片
下面我们就需要进行函数调用的传参:
函数的栈帧的创建和销毁_第14张图片
这里首先把20放到eax中,把10放到ecx中。call就是去调用这个函数,并且会把下一个指令的地址压栈,因为当我们调用函数时会再回来往下执行。
函数的栈帧的创建和销毁_第15张图片
然后我们进入到函数当中:
函数的栈帧的创建和销毁_第16张图片
第一步是将ebp给push到栈里,然后将esp赋值给ebp,最后将esp减0CCh数据,这三步是给Add函数开辟函数栈帧。然后将三个寄存器压栈,初始化Add函数的栈帧为0CCCCCCCCh。
函数的栈帧的创建和销毁_第17张图片
然后我们将ebp-8的位置上设置为0,ebp+8上面说过放的是10,ebp+0Ch放的是20。Add的意思是:在eax寄存器中加上20。最后将eax中的值放到ebp-8地方,也就是z处。
函数的栈帧的创建和销毁_第18张图片
这里是先压栈的b,然后压栈的是a。所以函数在传参是时候是从右向左传的
函数的栈帧的创建和销毁_第19张图片
把z通过寄存器返回后,pop出edi,esi,ebx。
函数的栈帧的创建和销毁_第20张图片
然后将ebp赋值给esp:
函数的栈帧的创建和销毁_第21张图片
这样Add函数栈帧就销毁了。最后再pop掉ebp,就弹出了main函数的ebp了。此时ebp和esp就重新指向main函数的栈帧了。
在这里插入图片描述
Add函数结束后,将esp地址加8。意思是:把两个形参销毁了。
在这里插入图片描述
最后的mov是把寄存器里的值赋给c。

你可能感兴趣的:(C语言,C语言,函数栈帧的创建和销毁)