Most modern CPU architectures provide specific instructions to support jumping to and returning from subprograms.
MAL provides two basic instructions for ordinary subprogram calls:
jr $racomplements the jal instruction, so this is the most typical use.
The basic structure of a subprogram call looks something like this:
.text main: jal subprog # End of main jr $ra # Beginning of subprogram subprog: # End of subprogram jr $ra
As discussed in Section 5.3, “The MIPS Register Files”, MAL programmers adhere to a convention for use of registers. Table 5.3, “MIPS Registers” shows the conventional use for all registers in the CPU and the floating point coprocessor.
With respect to subprograms, the following conventions must be followed:
Suppose we have a subprogram that computes the area of a rectangle. The Java method might be called as follows:
int yard_size, length, width; // Some other code // Compute area of yard yard_size = area(length, width); // More code
If this code were compiled to MAL, the compiler output might look like this:
.data yard_size: .word 0 length: .word 0 width: .word 0 .text # Some other code # Compute area of yard lw $a0, length # Pass length argument lw $a1, width # Pass width argument jal area sw $v0, yard_size # Store return value # more code
If passing floating point values, we use the floating point registers as arguments and return values. Register $f12 should be used for the first argument, $f13 for the second (or $f14 if the first argument was a double). Register $f0 should be used for the return value.
.data yard_size: .double 0.0 length: .double 0.0 width: .double 0.0 .text # Some other code # Compute area of yard l.d $f12, length # Pass length argument l.d $f14, width # Pass width argument jal area s.d $f0, yard_size # Store return value # more code
Note that some registers must be preserved by subprograms. For example, a program can assume that $s0 or $f20 will have the same value after a subprogram call (including a syscall) that it had before. Hence, if a subprogram alters the value of either $s0 or $f20, the original value must be restored before the subprogram returns. We cannot assume the same about temporary registers such as $t0. They may have different values after a jal or syscall than they had before it.