Compiling a C Procedure That Doesn’t Call Another Procedure
Let’s turn the example on page 65 from Section 2.2 into a C procedure:
int leaf_example (int g, int h, int i, int j) { int f; } |
What is the compiled MIPS assembly code?
Th e parameter variables g, h, i, and j correspond to the argument registers $a0, $a1, $a2, and $a3, and f corresponds to $s0. The compiled program starts with the label of the procedure:
leaf_example: |
The next step is to save the registers used by the procedure. The C assignment statement in the procedure body is identical to the example on page 68, which uses two temporary registers. Th us, we need to save three registers: $s0, $t0, and $t1. We “push” the old values onto the stack by creating space for three words (12 bytes) on the stack and then store them:
addi $sp, $sp, –12 # adjust stack to make room for 3 items sw $t1, 8($sp) # save register $t1 for use afterwards sw $t0, 4($sp) # save register $t0 for use afterwards sw $s0, 0($sp) # save register $s0 for use afterwards |
Figure 2.10 shows the stack before, during, and aft er the procedure call.
Th e next three statements correspond to the body of the procedure, which follows the example on page 68:
add $t0, $a0, $a1 # register $t0 contains g + h add $t1, $a2, $a3 # register $t1 contains i + j sub $s0, $t0,$t1 # f = $t0 – $t1, which is (g + h)–(i + j) |
</div.
To return the value of f, we copy it into a return value register:
add $v0,$s0,$zero # returns f ($v0 = $s0 + 0) |
Before returning, we restore the three old values of the registers we saved by “popping” them from the stack:
lw $s0, 0($sp) # restore register $s0 for caller lw $t0, 4($sp) # restore register $t0 for caller lw $t1, 8($sp) # restore register $t1 for caller addi $sp, $sp,12 # adjust stack to delete 3 items |
The procedure ends with a jump register using the return address:
jr $ra # jump back to calling routine |