When immediately printing a result from an arithmetic operation in mips, is it better to store it directly to $a0?

Viewed 175

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
2 Answers

It depends.

If syscall modifies the value of $a0 and you still need that value after the system call, then you need to preserve it in some way.

However, the syscall simulation in SPIM and MARS will not modify any registers except those explictly listed in the documentation. So, if that's what you're running your code in, you typically won't have to worry about preserving the value of $a0.

Another possibility is that the person who wrote that code had some other code that will be executed later on - and that that code assumes that the value is in $t0.

Or it could be that the extra instruction is completely pointless. It's impossible to say without more context.


As an aside, li $t0, 50 and move $a0, $t0 is much more readable than addi $t0, $zero, 50 and add $a0, $zero, $t0.

The only thing that matters is register contents of $v0 and (for this system call) $a0, when syscall executes.

Yes, it's very common to see inefficient code from beginners. Maybe they copied+modified examples without understanding, or without following the logic that less code / simpler code is almost always better. (Often more efficient, and usually easier for human readers to follow. Including the programmer while you're writing / debugging it. Fewer changes to the architectural state when single-stepping to debug, etc.)

On MARS / SPIM, the system-call ABI doesn't modify $a0, so the data will still be available in a register after. Linux's system call ABI has different system calls with different numbers, but also preserves (almost?) all registers except the return value.

Copying a register before a system call can make sense if you want it in a register other than $a0 for something after the system call, e.g. to keep it in a register while you pass different args to a different syscall, but otherwise it's purely stupid code-bloat. (Copying after would be fine, too.)


Why are you using li for setting $v0 = 1, but manually expanding it to addi for setting $a0 = 50?

It wouldn't make the machine code any more efficient (ori or addiu aren't faster than addi on any real MIPS, AFAIK, although they might be on a simulator/emulator where the overflow-check in addi takes extra code in the emulator.)

But it would make the asm source easier to read, and clearer. (If you understand how assemblers handle the li and move pseudo-instructions, writing out an addiu or addu manually with $zero just gives humans more to read to see that it's just creating a constant or copying a register.)

Related