C语言之函数调用-栈帧
学过汇编的都知道在汇编中子程序调用是怎样实现的
那高级语言中的函数调用是怎样实现的?
通过栈帧,什么是栈帧?
栈帧是函数调用的过程记录
栈帧是怎么实现的?
有如下代码
反汇编代码如下
我们发现在call指令调用add函数前进行了两次push 操作把add函数所需的参数压入栈中,这就是调用前的准备工作,而add esp,8指令是函数调用后的清除工作(释放参数所占的栈空间),
接下来让我们进入add函数的内部看看编译器是怎样用栈帧实现函数调用的以及栈帧是怎样生成的
下面我画个图来表示表示栈帧以及这段代码所做的事(生成一个栈帧)
红色标识的是main函数的栈帧,蓝色标识的是add函数的栈帧,单箭头表示单元存放的是XX的值,双箭头表示XX寄存器的值指向
进入函数的第一个操作就是push ebp保存main的ebp,
第二个操作把mov ebp,esp main 的栈顶指针做为add函数基栈指针,生成基栈指针
第三个操作sub esp,40h为add函数分配64字节的栈空间用来保存局部变量(尽管add函数没有局部变量),生成栈顶指针
第4,5,6个操作分别在栈中保存ebx,esi,edi寄存器的值
第7,8,9,10操作把分配的64字节栈空间,以4个字节为单位分16次,把每个字节赋值为0(栈初始化),,,,
第11,12,13操作是a=a+b
第14,15,16操作恢复esi,edi,ebx的值
第17个操作mov esp,ebp恢复main函数的栈顶指针
第18个操作pop pbp 恢复main函数的基栈指针
第19个操作从add函数中返回到main函数中
ebp与esp间的内容就是函数的调用的过程记录即栈帧
所有操作中我们都没有看到关于“call指令的下一条指令地址”的压栈与出栈操作
那么它是什么时候被push 什么时候被pop的?
它的作用是什么?
在执行call指令时会把它压栈,执行ret指令时会把它pop 到pc寄存器中
现在你知道它的做用是什么了?
就是保存函数调用后的返回地址
返回到?
当然是返回到调用者中
现在你知道c语言的函数调用是怎样实现的了?
注:vc6.0下