MIPS汇编语言,是函数调用后保存的$ ra寄存器吗?

时间:2017-10-23 04:57:49

标签: assembly mips

我是一名开始学习MIPS的学生。

我一直在网上搜索$ ra(返回地址)是否被保存(保留)被调用者。有些表说它是一个被保存的被叫者而另一些表示它不是。

我认为$ ra不是被叫方保存的注册表,这意味着它是一个来电者保存的注册表。

这是因为如果$ ra是被调用者保存的寄存器,我相信存在问题。如果我们通过jal调用一个函数(子例程),则callee函数无法保留之前的$ ra值,因为$ ra将在jal指令之后更改为PC + 4;调用函数应事先在栈中保存$ ra。因此,考虑到这种情况,$ ra将成为调用者保存的寄存器。

我说错了吗?

1 个答案:

答案 0 :(得分:2)

  

我说错了吗?

正如您已经发现$ra是一个非常特殊的情况:

jal指令在输入被调用函数之前已经将值写入$ra。所以调用函数已经" destroy" $ra注册。

然而有人已经提出了一个与你非常相似的问题:

Whether $ra register callee saved or caller saved in mips?

一个答案指出被调用函数允许修改$ra寄存器,因此调用函数不能假设 $ra真正包含退货地址。该答案中给出的例子是:

move $v0,$ra
li   $ra,0
jr   $v0
  

除了jal指令外,syscall指令是否始终保留$ ra寄存器?

在模拟器(SPIM,MARS,...)上,syscall指令是一条单CPU指令,它不访问任何寄存器,但记录了这些寄存器。

在真正的MIPS CPU上,syscall指令会导致所谓的"软件中断"在x86 CPU上。软件中断是函数调用的一种特殊形式。

然而,与jal指令不同,syscall指令不会将返回地址写入$ra寄存器,而是写入特殊寄存器(MIPS R4400 CPU上名为EPC) ,只能使用特殊说明访问。

被调用的函数("异常处理程序")当然会修改寄存器。如果该函数调用其他函数,它将修改$ra寄存器。

但是我认为几乎所有操作系统都会保留所有寄存器,但是根据文档明确修改的那些(在Linux $v0的情况下,$v1$a3syscall修改。