过程调用的机器级表示
特别说明该表示是基于IA-32指令系统,x86 64指令系统不同于IA-32
机器级表示
可执行文件的存储器映像
调用过程
IA-32的寄存器使用约定 – 调用者保存寄存器:EAX、EDX、ECX 当过程P调用过程Q时,Q可以直接使用这三个寄存器,不用 将它们的值保存到栈中。如果P在从Q返回后还要用这三个寄 存器的话,P应在转到Q之前先保存,并在从Q返回后先恢复 它们的值再使用。 – 被调用者保存寄存器:EBX、ESI、EDI Q必须先将它们的值保存到栈中再使用它们,并在返回P之前 恢复它们的值。 – EBP和ESP分别是帧指针寄存器和栈指针寄存器,分别用来指 向当前栈帧的底部和顶部。
过程调用过程中栈和栈帧的变化 (Q为被调用过程)
看一个简单的例子
过程解析
一个C过程的大致结构如下: – 准备阶段 • 形成帧底:push指令 和 mov指令 • 生成栈帧(如果需要的话):sub指令 或 and指令 • 保存现场(如果有被调用者保存寄存器) :mov指令 – 过程(函数)体 • 分配局部变量空间,并赋值 • 具体处理逻辑,如果遇到函数调用时 – 准备参数:将实参送栈帧入口参数处 – CALL指令:保存返回地址并转被调用函数 • 在EAX中准备返回参数 – 结束阶段 • 退栈:leave指令 或 pop指令 • 取返回地址返回:ret指令
过程调用参数传递举例
看一个递归函数的例子
int nn_sum ( int n) { int result; if (n<=0 ) result=0; else result=n+nn_sum(n-1); return result; }
我们可以看出来,递归函数在不断的压栈生成栈帧,且没有到达最后一个递归的函数,他的栈帧并没有进行释放,所以
递归函数的空间和时间的开销都非常大(当达到他的极限值就会出现暴栈的情况)我们可以尽量不适用递归函数
原文地址:https://www.cnblogs.com/chenxuming/p/9689119.html
时间: 2024-10-13 10:47:25