在MIPS架构中,保留寄存器和非保留寄存器在调用中的区别是什么?

huangapple go评论44阅读模式
英文:

In MIPS architecture, what is the difference between a register which is preserved and non preserved on calls?

问题

I do understand that preserved on call registers are automatically reverted back to their original value once the function is over.
我理解,保留在调用寄存器中的值在函数结束后会自动恢复为其原始值。

I tried to undertand how preserved on call registers work. It makes sense to use $s0-$s7 in the loops to store the intermediary results and memory addresses. But when it comes to $ra, I am so confused...
我试图理解保留在调用寄存器中的工作原理。在循环中使用 $s0-$s7 存储中间结果和内存地址是有道理的。但是当涉及到 $ra 时,我感到很困惑...

英文:

I do understand that preserved on call registers are automatically reverted back to their original value once the function is over.

I tried to undertand how preserved on call registers work. It makes sense to use $s0-$s7 in the loops to store the intermediary results and memory addresses. But when it comes to $ra, I am so confused...

答案1

得分: 0

Call preserved registers 在函数返回时不会自动恢复 —— 它们需要由修改它们的任何函数的出口代码(称为结尾代码)手动恢复。这种恢复是由调用约定规定的,每个函数都遵循调用约定规定的规则(否则程序可能会出错,可能会工作,也可能会崩溃)。


在保留寄存器和临时寄存器之间没有硬件差异 —— 任何差异都是由约定和支持它的寄存器使用模型引起的。


$ra 是由调用者提供的参数,函数用来返回到正确的调用点,因为一个函数可以从不同的调用点调用。如今,我们会描述参数 $ra 的内容为返回地址(不要与函数返回值混淆);在较旧的术语中,这被称为链接。jal 指令会隐式地将返回地址定位到 jal 后的下一条指令。您不一定要使用 jal 来调用函数,但您需要在该寄存器中传递有效的返回地址。使用给定的指令来进行调用和返回有助于硬件分支预测(如果存在)。

如果您的函数进行了调用,这将涉及总共两个返回地址 —— 即此函数自身的返回地址,以及用于返回到此函数的被调用函数的返回地址。调用将必然重新分配 $ra 寄存器用于此调用。这种重新分配会清除寄存器中保存的先前值,而这些值是需要返回给调用者的,因此进行函数调用的函数必须考虑自己的返回地址,并保存和恢复它们以便自己使用。调用者不依赖于 $ra 被恢复。

$ra 的恢复通常与 $s 寄存器的恢复一起出现,使 $ra 看起来有点像保留调用寄存器;但是,它在结尾本身中直接用于返回给调用者,而不是为调用者恢复 —— 它的最后一次使用是在函数本身内部,而与此相反,$s 寄存器是为某些调用者的好处而恢复的。


相比之下,$s 寄存器是为某些调用者的好处而保留的。我们不知道哪个调用者在这些寄存器中有什么值,但只要我们保留这些寄存器中的值,我们就不需要知道 —— 要么是通过不使用它们,要么是通过保存和恢复使用了的寄存器。

英文:

Call preserved registers are not automatically reverted upon function return — they are manually restored by the exit code (called epilogue) of any function that modifies them.  This restoration is mandated by the calling convention, and every function follows the rules set forth by the calling convention (or else program is buggy and may work or may crash).


There is no hardware difference in preserved vs. scratch registers — any differences are due to convention and register usage models supported by it.


$ra is a parameter supplied by the caller that a function uses to return to the right call site, since a function can be invoked from different call sites.  These day we would describe the contents of parameter $ra as a return address (not to be confused with function return value); in older parlance, this was called linkage.  Thejal instruction implicitly targets the $ra register with the return address of the next instruction after the jal.  You don't necessarily have to use jal to call a function, but you do need to need to pass a valid return address in that register.  (Using the given instructions as intended for call and return helps with hardware branch prediction, when present, though.)

If your function makes a call, this will involve a total of two return addresses — namely this function's own return address, and the called function's for return to this function.  Calling will necessarily repurpose the $ra register for this call.  This repurposing will wipe out the previous value held in that register, which is needed to get back to the caller, so a function that makes a function call has to consider its own return address, and save and restore that for its own benefit and usage.  Callers don't rely on $ra being restored.

$ra restoration often appears along side $s register restoration, making $ra appear somewhat like a call-preserved register; however, it is used directly in the epilogue itself to return to the caller rather than being restored for the caller — its last use is within the function itself, whereas by contrast $s registers are being restored for some callers' benefit.


By contrast, the $s registers are preserved for some caller's benefit.  We don't know which caller has what values in these registers, but we don't have to as long as we preserve the values in those registers — either by not using them, or by save & restore for the ones used.

huangapple
  • 本文由 发表于 2023年5月14日 10:46:04
  • 转载请务必保留本文链接:https://go.coder-hub.com/76245610.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定