谁负责保存MIPS中的寄存器?

4
在MIPS中调用子例程时,由于被称为保存寄存器($s0-$s7)在函数/子程序调用期间需要保留,如果它们将要被修改,则会保存在子例程的堆栈帧中。谁负责保存它们?是我作为汇编程序员负责通过编写指令将这些被保存的寄存器存储到堆栈中来保存这些被称为保存的寄存器吗?还是汇编器在调用子例程时会自动管理保存被称为保存的寄存器,以便它们跨调用被保留?我刚开始学习MIPS调用约定,所以这完全是新的对我来说。
2个回答

4
您的函数不一定必须保存/恢复它们,只需确保在函数返回时它们仍然具有原始值即可。最简单的方法是根本不触及那些寄存器。
Caller和callee saved registers 是令人困惑的术语,错误地暗示每次函数调用都必须将所有寄存器保存在某个地方。
更好的术语是call-preserved(调用时保留)和call-clobbered(调用时破坏)。在这两种情况下,您从同样的角度查看寄存器,并且不意味着任何人实际上在浪费指令进行任何保存。如果您不需要jal之后的寄存器中的值,请让寄存器被破坏。
您可以像使用$t0..$t9这样的 call-clobbered 寄存器做任何您想做的事情,并且可以返回它们持有的任何垃圾。
如果您在循环内部进行函数调用,则可能需要保存一些 call-preserved 寄存器($s0..$s7)并将其中一个用作循环计数器。然后在函数的末尾恢复它。您不希望在循环内部自己存储/重载它;如果您调用的函数不接触该寄存器,那么这将是一种巨大的浪费。

1
你需要负责,汇编器的工作是将你所写的代码转换成机器码。

所以,既然我负责一切,如果我想以同样的方式处理$t0-$t9或$s0-$s7寄存器,那么它们本质上并没有什么不同吗?例如,我可以将$t0-$t9和$s0-$s7寄存器保存到堆栈帧中,从而使$t0-$t9表现得像被调用者保存的寄存器,尽管它们通常是“调用者保存/临时”寄存器? - Mrcitrusboots
1
确实可以。通常情况下,坚持惯例是值得的,这样你编写的代码将与库/编译代码兼容,并且对于加入项目的人来说更加熟悉。 - Colin
2
@Mrcitrusboots 没错,“约定”只是一种约定,你可以在你的代码中尊重和支持它,也可以不这样做,在 CPU 内部没有任何硬件保护这些约定。(而且 $s0$t0 都是通用寄存器,没有任何额外的特性(不像 $0$sp 在某些特殊情况下在硬件内部会有所不同),但大多数 32 个 MIPS 寄存器都是“相等”的)。 - Ped7g
@Colin,为什么偏向于使用$s0-$s7寄存器?这样做是因为它更优化吗? - Nishant

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接