When writing MIPS programs, I've heard that its generally good practice to keep the registers clean i.e. to clear the values of the registers to 0 at the end of the program. So my first question is how/why is this necessary/good practice?
Secondly, If we have a function call with parameters(p1, p2) stored in $4 and $5; at the end of our function definition, is it necessary to clear the values at $4 and $5 or better to leave them as they were at the beginning of the function call?
I've also seen examples of pushing parameters to the stack like this:
addi $29, $29, -8
sw $4, 0($29)
sw $5, 4($29)
; At the end of our program:
addi $29, $29, 8
When and why is this necessary/good practice?
Finally, If we are to use some constants in our program, say 4 and 1, is it better to keep them on the registers or the stack? For Example:
lis $8
.word 4
lis $9
.word 1
And then we might use those values in some way for our program and clear them to 0 afterwards.
Or we could choose to store them on the stack by moving the stack pointer back and forth. Which is a better approach?
First, you usually want to use $zero instead of $0, $v0–$v1 instead of $2–$3, etc... they're easier to understand (and memorize) than plain numbers and assemblers also understand this notation so there's no problem on this side. Also this abstracts your code from the number, so if ever the standard changes (e.g. $zero is no more $0 but $256), your code will still be assembled correctly.
In every CPU architecture there are some conventions on how to use the registers for doing calls and how to behave with the registers within functions. This is called the calling convention. You can see here a brief description for the MIPS calling convention.
I've heard that its generally good practice to keep the registers clean i.e. to clear the values of the registers to 0 at the end of the program. So my first question is how/why is this necessary/good practice?
I've personally never heard of this practice, but I don't quite agree with it. A better practice would be to restore the previous values before the start of the program.
Secondly, If we have a function call with parameters(p1, p2) stored in $4 and $5; at the end of our function definition, is it necessary to clear the values at $4 and $5 or better to leave them as they were at the beginning of the function call?
You should leave them as they were at the beginning of the function call. For the caller, it makes no sense you modify this registers.
Space on the stack is reserved for $a0-$a3 in case the callee needs to save its arguments, but the registers are not stored there by the caller.
I've also seen examples of pushing parameters to the stack like this. When and why is this necessary/good practice?
The stack if by definition a temporary storage. If you want to backup register values (e.g. you want to use $aX or $sX), you put them there. Same than before:
Space on the stack is reserved for $a0-$a3 in case the callee needs to save its arguments
addi $sp, $sp, -8
Moves stack pointer register (by convention it's $29). This reserves 8 bytes in the stack.
sw $a0, 0($sp)
sw $a1, 4($sp)
Saves $a0 to the top of the stack and $a1 as second in stack (keep in mind that stack grows towards lower adresses). This fills the reserved space (8 bytes). This is called the function entry protocol.
; At the end of our program:
; You forgot, and it's important:
lw $a0, 0($sp)
lw $a1, 4($sp)
addi $sp, $sp, 8
You restore saved registers and put stack pointer back to original value. Then the caller will have its stack and parameters untouched. And this is called the function exit protocol.
If we are to use some constants in our program, say 4 and 1, is it better to keep them on the registers or the stack?
Neither. Constants should be used as immediate operands:
li $t0, C ; Load 16-bit constant into $t0
lui $t0, C ; Load upper 16-bit half-word of $t0
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With