在产生
函数调用
时,有可能调用者
使用了某个寄存器,被调用者
也使用了这个寄存器并对修改了其中的值。如果调用结束后调用者还需要使用先前这个寄存器中的值,此时就会导致调用者
的状态遭到破坏
。所以在函数调用时需要对这个寄存器中的值进行保存,同时函数返回时再把它恢复到调用前的状态
。
由于栈
这种数据结构具有记忆功能
,也就是当你将某个元素压入栈中之后,再进行出栈
此时出栈
时的元素还是你先前压入栈中的元素。所以通常使用栈
来对寄存器进行保存与恢复
。首先将寄存器中的值压入到栈
中进行保存,然后才能对它们进行修改,最后再将之前保存在栈
中的值逐个恢复到寄存器中。
下面代码分别把ax,bx
这两个寄存器保存在栈中:
push(ax);
push(bx);
保存过程:
把栈中的值逐个恢复到寄存器中:
pop(bx);
pop(ax);
恢复过程:
这里要注意的是出栈和入栈的顺序是相反的,因为此时栈顶
是之前bx
的值,所以在恢复时需要先把栈顶
的值弹出到bx
,然后再把下一个值弹出至ax
,这样就把值与寄存器对应起来了。
并不是所有的寄存器都需要保存与恢复
,根据约定把寄存器中的一部分划分为被调用者保存
和调用者保存
:
-
被调用者保存
由
被调用者
来负责这组寄存器的保存与恢复
。由于任何一个函数都是一个被调用者
,因为函数总是被调用后才会运行,因此可以得出任何一个函数在修改这组寄存器时都需要对它们进行保存与恢复
。例如函数P调用函数Q,在Q被执行时,Q首先将这组寄存器中它需要修改的部分寄存器压入
栈
中进行保存,最后在返回时再由Q负责再把栈中保存的值弹出这些寄存器中进行恢复。 -
调用者保存
除了
被调用者保存
和栈指针
(sp)以外的其他寄存器被称为调用者保存
寄存器。由于任何一个函数都是一个被调用者
,因此可以得出任何一个函数在修改这组寄存器时都不需要对它们进行保存与恢复
。例如函数P调用函数Q,在Q被执行前,P首先将这组寄存器中它不希望在Q返回时
发生改变
的部分寄存器压入栈
中进行保存,最后Q返回后由P负责把栈中保存的值弹出这些寄存器中进行恢复。