1.69、函数调用进行的操作?

1. 参数传递:调用者(caller)将实参按从右到左的顺序压入栈中,这样设计便于支持可变参数函数(如printf)和参数访问。

2. 保存返回地址:调用者将调用指令的下一条指令地址(返回地址)压入栈,以便被调用函数执行完毕后能正确返回调用点。

3. 建立栈帧:被调用者(callee)先将调用者的帧指针(如x86的%ebp寄存器)压入栈中,随后将栈指针(%esp)赋值给帧指针,形成新的栈帧基址,便于访问参数和局部变量。

4. 局部变量分配:被调用函数根据需要在栈帧中为局部变量分配空间,通常通过调整栈指针完成。

5. 执行函数体:函数体执行过程中,参数和局部变量均通过相对于帧指针的偏移访问,保证访问的稳定性。

6. 返回与恢复现场:函数执行完毕后,将返回值(通常放在寄存器如eax)传回调用者,恢复调用者的帧指针和栈指针,弹出当前栈帧,最后跳转到返回地址继续执行。

7. 调用约定:C++函数调用遵循特定调用约定(如cdecl),规定参数压栈顺序、返回值存放寄存器及栈清理责任(通常调用者清理)。

8. 虚函数调用:对于虚函数,调用时先通过对象的this指针找到虚函数表,再从表中取出函数指针,最后按普通函数调用流程执行,实现运行时多态。

总结来说,C++函数调用是通过栈帧机制实现的,调用者负责参数和返回地址的压栈,被调用者负责建立新的栈帧和局部变量管理,调用完成后恢复现场返回。此机制保证了函数调用的有序性、参数传递的准确性及调用现场的完整性。
本文首发于【讳疾忌医-note】公众号,未经授权,不得转载。
(加入我的知识星球,免费获取账号,解锁所有文章。)

阅读剩余
THE END