要对过程提供机器级支持,需要实现三个动作机制,现在假设过程P调用过程Q,Q执行后返回到P:
3.7.1 运行时栈
- 栈用来传递参数、存储返回信息、保存寄存器以及局部存储。
- 当过程P调用过程Q时,会把返回地址压入栈内,指明当Q返回时,要从P的哪个位置继续执行。
- 大多数过程的栈帧都是定长的,在过程的开始就分配好了,但是有些过程需要变长的帧。
-
通过寄存器,过程P可以传递最多6个整数值(指针和整数),但是如果Q需要更多的参数,P可以在调用Q之前在自己的栈帧里存储好这些参数。
3.7.2 转移控制
关键点就是调用call指令时,会把父过程继续执行的地址压入栈内,这样在子过程调用完成后,会弹出栈顶,程序计数器PC更新为弹出的栈顶值,程序流转回正确的父过程执行位置。
3.7.3 数据传送
- x86-64中,大部分过程间的数据传送是通过寄存器实现的,比如常见的%rdi、%rsi,而返回值可以通过访问寄存器%rax。
-
通过寄存器最多可以传递6个参数,寄存器使用有特殊顺序,并且使用的名字跟传递的参数大小也有关系。
- 如果一个函数有大于6个整型参数,超过6个的部分要通过栈来传递。通过栈传递参数,所有的参数大小都向8的整数倍对齐。参数到位以后,再调用call指令进行控制转移。
3.7.4 栈上的局部存储
有些时候,局部数据必须存放在内存中,常见情况如下:
3.7.5 寄存器中的局部存储空间
- 寄存器是唯一被所有过程共享的资源。
- 寄存器%rbx、%rbp、%r12-%r15被划分为被调用者保存寄存器。
-
过程P调用过程Q,为了保证P的一些寄存器的值不被Q覆盖,调用之前必须把这些寄存器内的值入栈保存起来,然后在Q执行完返回后,把这些值恢复到寄存器内
3.7.6 递归过程
递归调用一个函数本身和调用其他函数是一样的