Subroutines, MIPS Assembly Language Programming

Tom Kelliher, CS26

Sept. 12, 1996

For a discussion of RISC assembly languages, I'm going to substitute the MIPS processor for the PowerPC. Don't read the PowerPC section of Chapter 2. I do expect you to read the sections on the Motorola 68000.

Resources for the MIPS:

Subroutines

You need to understand section 2.7, Stacks & Queues to understand this material.

We know how to implement loops and the sundry ``decision'' statements, how do we implement function linkages?

At a high level (that of C++ or Pascal), what is going on with a function call?

void f(void)
{
   ...
   g();
   ...
}


void g(void)
{
   ...
   return;
}


void h(void)
{
   ...
   g();
   ...
}
Can we use branch instructions to do this?

A Better Mechanism

Add a link register to the CPU and 2 instructions:

  1. Call_subroutine
  2. Return_from_subroutine
What do they do?
subr_f:     move R0, R1
            Call_subroutine subr_g
            move R1, R0
            Return_from_subroutine

subr_g:     add #1, R1
            Return_from_subroutine

subr_h:     move R3, R1
            Call_subroutine subr_g
            move R1, R3
            Return_from_subroutine
What would happen if f() called g() called h()?

What about recursion?

Stack Frames

A stack can be used to store just return values; a stack frame is a more general mechanism.

Standard method for allocating a function's variables.

Consider a function:

void f(void)
{
   int i, j;
   float x;
   struct S s;

   ...
}
What must the stack frame provide storage for?

Why can't I just keep the variables in registers?

What about arrays?

What about global variables and static locals?

Suppose:

  1. f() (caller) calls g() (callee).
  2. f() uses registers R0-- R7.
  3. g() modifies registers R4-- R8.
When control returns to f(), will its registers have the same values?

Parameter Passing and Return Values

How are parameters transmitted from caller to callee?

What about return values?

An Example

Consider:

void f(void)
{

   int i = 12;
   float x = 34.56, y;

   y = g(i, &x);
}


float g(int a, float* z)
{
   char c;

   *z += 2.0;
   return a + z;
}

Assembly Language Programming for the MIPS

Example SPIM program:

# addn.spim
# Input: A number of inputs, n, and n integers.
# Output: The sum of the n inputs.

            .data                         # Constants.
prmpt1:     .asciiz "How many inputs? "
prmpt2:     .asciiz "Next input: "
sum:        .asciiz "The sum is "
nl:         .asciiz "\n"

            .text                   # Main.
            .globl main

main:       li $v0, 4               # Syscall to print prompt string.
            la $a0, prmpt1
            syscall

            li $v0, 5               # Syscall to read an integer.
            syscall
            move $t0, $v0           # n stored in $t0.

            li $t1, 0               # sum stored in $t1.

while:      blez $t0, endwhile
            li $v0, 4
            la $a0, prmpt2
            syscall

            li $v0, 5
            syscall
            add $t1, $t1, $v0       # Increase sum by new input.

            sub $t0, $t0, 1         # Decrement n.

            b while

endwhile:   li $v0, 4
            la $a0, sum
            syscall

            move $a0, $t1           # Syscall to print an integer.
            li $v0, 1
            syscall

            li $v0, 4
            la $a0, nl
            syscall

            li $v0, 10              # Syscall to exit.
            syscall

An example SPIM run:

abacus:~/Class/Cs26/Examples
% spim
SPIM Version 5.3 of Aug 30, 1993
Copyright 1990-92 by James R. Larus (larus@cs.wisc.edu).
All Rights Reserved.
See the file README a full copyright notice.
(spim) load "addn.spim"
(spim) run
How many inputs? 5
Next input: 1
Next input: 3
Next input: -20
Next input: 45
Next input: -6
The sum is 23
(spim) quit

abacus:~/Class/Cs26/Examples
%



Thomas P. Kelliher
Wed Sep 11 16:28:12 EDT 1996
Tom Kelliher