MIPS汇编语言 - 临时寄存器 vs 保存的寄存器

43

到目前为止,我一直在使用寄存器 $s0-$s9 以及和 $t0-$t9 寄存器的使用方式相同。我被告知并阅读了无数论坛帖子和段落,介绍了它们之间的区别,但没有编码示例。我被告知应该在使用过程中看到它所涉及的差异,但我已经创建了无数涉及过程的场景,试图找到保存寄存器与临时寄存器之间的区别,但我失败了。

我想看到一个相对简单的示例,在其中 $t0-9 寄存器不会像 $s0-9 寄存器一样工作,并因此产生不同的值?

```html

迄今为止,我一直使用 $s0-$s9 寄存器,并将其与 $t0-$t9 寄存器使用相同的方式。虽然我听说过它们之间的区别,也看过无数的论坛帖子和谷歌段落,但都没有附带编程示例。有人告诉我要在过程中看到差别,但我已经尝试创建了许多涉及过程的场景,却没能发现保存寄存器和临时寄存器之间的差异。

请提供一个相对简单的示例,其中 $t0-9 寄存器与 $s0-9 寄存器的工作方式不同,并因此产生不同的值

```
1个回答

84
临时变量和保存的变量在工作原理上没有区别。区别在于它们的使用方式,或者更确切地说,应该如何使用它们。
MIPS调用约定规定了各种寄存器的使用方式——$v寄存器用于函数返回值,$a寄存器用于函数参数,$t变量是临时调用者保存寄存器,而$s寄存器是被调用者保存寄存器。 被调用者保存调用者保存之间的区别如下:在调用函数时,约定保证$s寄存器在返回后保持不变,而对于$t寄存器,约定并不保证这一点。当然,这意味着如果您希望在例程中使用$s寄存器,则必须保存并恢复其值。例如,如果函数A使用寄存器$t0$s0,然后调用函数B,则如果要在函数B返回后继续使用寄存器$t0,则必须保存寄存器$t0。函数B必须先保存$s0才能开始使用它。
一个例子:
main:

    li $s0 7
    li $t0 7

    jal myFunction

    #$s0 guaranteed to equal 7
    #$t0 value not guaranteed

我推荐这个链接,它提供了一些不错的深入信息。

当然,所有这些只是惯例,只有在你和其他程序都遵守惯例并保存和恢复$s寄存器以使其不会被函数调用覆盖时才有效。


2
为了回应发帖者对“相对简单的例子”的请求,其中$t与$s表现不同,您可以添加myFunction的定义:addi $t0, $0, 255``jr $ra - RobertB
1
@RobertB 我认为那会过于混乱。用户也可以在myFunction中自由更改$s0的值,只是他们“应该”在之后将其放回去。 - Konrad Lindenbach
1
你所说的“Function B必须在开始使用$s0之前保存它”,具体是什么意思呢?你所说的保存是指什么?$s0已经是一个被保存的值了。而且主函数调用时已经“保存”了$s0。 - user4351838
2
我喜欢术语“调用保留”与“调用破坏”的区分。这样可以避免暗示任何人必须保存/恢复寄存器,如果他们不关心值或不打算修改它们的话。通常情况下,您会在下一个函数调用后不需要的值上使用调用破坏寄存器,因此可以让这些值消失,并在函数调用后将寄存器/值视为死亡。此外,这些术语不仅通过一个字母的差异进行区分,而且从当前函数使用它们的角度考虑了两种类型的寄存器。 - Peter Cordes
1
为了确保一切正常,无论是否遵守约定,被调用者都可以先在堆栈中保存所有将要修改的寄存器,然后在返回之前恢复它们。这样,调用者就不必保存任何寄存器,因为受影响的寄存器由被调用者保存。@mejariamol - Helder Daniel
显示剩余2条评论

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