MIPS 汇编语言,函数调用后是否保留 $ra 寄存器?
MIPS assembly language, is $ra register preserved after function call?
我是一个刚开始学习MIPS的学生
我一直在网上搜索$ra(return address) 是否被调用者保存(保留)。一些表声明它是一个被保存的被调用者,而另一些声明它不是。
我认为 $ra 不是被调用者保存的寄存器,这意味着它是调用者保存的寄存器。
因为如果$ra是一个callee saved register,我相信是有问题的。如果我们通过 jal 调用函数(子例程),被调用函数无法保留之前的 $ra 值,因为 $ra 在 jal 指令之后将更改为 PC+4;调用函数应该事先将 $ra 保存在堆栈中。因此,考虑到这种情况,$ra 将是调用者保存的寄存器。
我说的对吗?
Am I correct?
您已经发现 $ra
是一个非常特殊的情况:
jal
指令在进入被调用函数之前已经将值写入 $ra
。所以调用函数已经 "destroy" $ra
注册。
但是有人已经问了一个与你的问题非常相似的问题:
一个回答指出被调用函数被允许修改$ra
寄存器所以调用函数不能假设 $ra
确实包含 return 地址。该答案中给出的示例是:
move $v0,$ra
li $ra,0
jr $v0
Besides the jal instruction, does syscall instruction always preserve the $ra register?
在模拟器(SPIM、MARS 等)上,syscall
指令是一个单独的 CPU 指令,它不访问任何寄存器,但记录在案。
在真正的 MIPS CPU 上,syscall
指令导致 x86 CPUs 上所谓的 "software interrupt"。软件中断是函数调用的一种特殊形式。
然而,与 jal
指令不同,syscall
指令不会将 return 地址写入 $ra
寄存器,而是写入一个特殊寄存器(名为 EPC
在 MIPS R4400 CPUs) 上,只能使用特殊指令访问。
被调用的函数("exception handler")当然会修改寄存器。如果该函数调用其他函数,它将修改 $ra
寄存器。
但是我认为几乎所有操作系统都会保留 所有 寄存器,但根据文档明确修改的那些(在 Linux $v0
, $v1
和 $a3
由 syscall
).
修改
我是一个刚开始学习MIPS的学生
我一直在网上搜索$ra(return address) 是否被调用者保存(保留)。一些表声明它是一个被保存的被调用者,而另一些声明它不是。
我认为 $ra 不是被调用者保存的寄存器,这意味着它是调用者保存的寄存器。
因为如果$ra是一个callee saved register,我相信是有问题的。如果我们通过 jal 调用函数(子例程),被调用函数无法保留之前的 $ra 值,因为 $ra 在 jal 指令之后将更改为 PC+4;调用函数应该事先将 $ra 保存在堆栈中。因此,考虑到这种情况,$ra 将是调用者保存的寄存器。
我说的对吗?
Am I correct?
您已经发现 $ra
是一个非常特殊的情况:
jal
指令在进入被调用函数之前已经将值写入 $ra
。所以调用函数已经 "destroy" $ra
注册。
但是有人已经问了一个与你的问题非常相似的问题:
一个回答指出被调用函数被允许修改$ra
寄存器所以调用函数不能假设 $ra
确实包含 return 地址。该答案中给出的示例是:
move $v0,$ra
li $ra,0
jr $v0
Besides the jal instruction, does syscall instruction always preserve the $ra register?
在模拟器(SPIM、MARS 等)上,syscall
指令是一个单独的 CPU 指令,它不访问任何寄存器,但记录在案。
在真正的 MIPS CPU 上,syscall
指令导致 x86 CPUs 上所谓的 "software interrupt"。软件中断是函数调用的一种特殊形式。
然而,与 jal
指令不同,syscall
指令不会将 return 地址写入 $ra
寄存器,而是写入一个特殊寄存器(名为 EPC
在 MIPS R4400 CPUs) 上,只能使用特殊指令访问。
被调用的函数("exception handler")当然会修改寄存器。如果该函数调用其他函数,它将修改 $ra
寄存器。
但是我认为几乎所有操作系统都会保留 所有 寄存器,但根据文档明确修改的那些(在 Linux $v0
, $v1
和 $a3
由 syscall
).