On function entry, ra
holds the return address where our caller wants us to jump when we’re done.
The function preamble saves it to the stack because the function body uses jal
to make function calls. jal
overwrites ra
so we need to save/restore our own return address around that.
f: addi $sp, $sp, -12 ; adjust stack pointer to accommodate stack frame (subtract 12 bytes) sw $ra, 8($sp) ; save a copy of our return address ...
When the function is complete we can restore the things we saved, then use the standard jr $ra
to return, setting PC = $ra.
... lw $ra, 8($sp) ; restore saved return address addi $sp, $sp, 12 ; restore stack pointer (dispose of stack frame) jr $ra ; jump to return address
(Some phrasing and code formatting copied from @PaulR’s answer which seems to explain it incorrectly, so I felt all its text needed a rewrite outside of the code blocks.)