If you're going to print the result of arithmetic operations immediately, why do you still store the result in a different register and copy it to $a0
instead of directly using $a0
when you perform operations? Is it a better practice? Or is it something arbitrary?
The common process I see from others is this:
addi $t0, $zero, 50
li $v0, 1
add $a0, $zero, $t0
syscall
Will it potentially cause problems if I do it this way?
addi $a0, $zero, 50
li $v0, 1
syscall
答案 0 :(得分:1)
要视情况而定。
如果syscall
修改了$a0
的值,而在系统调用之后您仍然需要该值,则需要以某种方式保存它。
但是,SPIM和MARS中的syscall
模拟不会修改任何寄存器,除非文档中明确列出了那些寄存器。因此,如果您要在其中运行代码,通常就不必担心保留$a0
的值。
另一种可能性是,编写该代码的人还有其他一些代码将在以后执行-并且该代码假定该值位于$t0
中。
也可能是多余的指令完全没有意义。没有更多的上下文是不可能说的。
顺便说一句,li $t0, 50
和move $a0, $t0
比addi $t0, $zero, 50
和add $a0, $zero, $t0
更具可读性。
答案 1 :(得分:0)
唯一重要的是$v0
执行时$a0
和(对于此系统调用)syscall
的寄存器内容。
是的,从初学者那里看到效率低下的代码非常普遍。也许他们复制了+修改过的示例而没有理解,或者没有遵循更少的代码/更简单的代码几乎总是更好的逻辑。 (通常效率更高,并且通常对于人类读者更容易理解。在编写/调试程序时包括程序员。单步调试时对架构状态的更改较少,等等)
在MARS / SPIM上,系统调用ABI不会修改$a0
,因此之后的数据仍然可以在寄存器中使用。 Linux的系统调用ABI的系统调用具有不同的编号,但是还保留(几乎?)除返回值以外的所有寄存器。
如果您希望在$a0
以外的其他寄存器中复制某个寄存器,则可以在系统调用之前进行复制,例如在系统调用之后进行复制。在将不同的args传递给不同的syscall时将其保存在寄存器中,但是否则,这纯粹是愚蠢的代码膨胀。 (复制也可以。)
为什么要使用li
来设置$v0 = 1
,却要手动将其扩展到addi
来设置$a0 = 50
?
这不会使机器代码效率更高({ori
或addiu
在任何真实的MIPS,AFIAK上都不会比addi
快,尽管它们可能在模拟器上) / emulator,其中addi
中的溢出检查会在模拟器中添加额外的代码。)
但是它将使asm源代码更易于阅读和清晰。 (如果您了解汇编程序如何处理li
和move
伪指令,则用addiu
手动写出addu
或$zero
只会使人类有更多的阅读空间看到它只是在创建一个常量或复制一个寄存器。)