本文使用一个简单的C语言的例子探索一下函数的调用机制,函数调用关系如下:
int g(int x)
{
return x + 10;
}
int f(int x)
{
return g(x);
}
int main(void)
{
return f(10) + 5;
}
通过编译生成汇编代码分析调用过程:
gcc –S –o main.s main.c -m32
生成汇编代码如下(main.s文件的原始内容):
简化代码后:
注释后代码:
函数的参数传递是通过堆栈传递的, *在函数调用之前将要传递的参数压入栈中,然后调用call指令
跳转到被调函数地址,同时先把当前PC指针压入栈中。跳转到被调函数之后,要先建立栈帧(通过
指令pushl %ebp 和 movl %esp %ebp完成),通过ebp加偏移取得调用函数的参数值,在函数返回
时通过leave 完成上述的逆过程,使堆栈恢复到调用函数的栈帧,再通过ret使代码恢复到调用函数,
这样就可以完整的回到调用函数中了*。
计算机的工作原理
用户程序运行在操作系统提供的虚拟的环境中,它有自己的内存空间, 分为代码段、数据段、bss段、
堆空间和堆栈,代码段、数据段和bss段是从可执行文件中加载的,堆空间和堆栈是动态创建的。程序
使用堆栈来完成函数的调用过程。