Procedure Calls and the Stack


Function A

    int A(int a, int * b, int C[])
    {
        if (a == C[2])
            *b = a * 2;
        a = a - *b;
        return a;
    }
A:


        lw $t0, 8($a2)
        bne $a0, $t0, ENDIF
        sll $t1, $a0, 1
        sw $t1, 0($a1)
ENDIF:  sub $a0, $a0, $t1
        add $v0, $a0, $zero


        jr $ra
# $a0 = a, $a1 = b, $a2 = C
# save anything to stack?

# read C[2] into $t0
# if (a != C[2]) goto ENDIF
# $t1 = a * 2;
# store $t1 to address b (*b = $t1)
# a = a - *b;
# store a in $ra for return a

# restore anything from stack?
# return to address in $ra


In A, do we need to store anything on the Stack?

Function A is a leaf function, and we decided to use only $t registers, so we do not need to store anything on the Stack.

 


Calling function A

int caller()
{
    int x, y;
    int Z[20];
    ...
    x = A(x, &y, Z);
    ...
}
caller():


        ...
        move $a0, $s0
        move $a1, $s1
        move $a2, $s2
        jal A
        move $s0, $v0
        ...


        jr $ra
# int caller()
# save anything to stack?

#... (assume x, &y, z are in s0, s1, s2)
# store x, &y, Z into $a0, $a1, $a2


# jump to function named A
# store return value ($v0) in x
# ...

# restore anything from stack?
# return to address in $ra


In caller, do we need to store anything on the Stack?

caller calls a function, so we need to save $ra and $a registers to the Stack. It is also currently using $s0, $s1, $s2, so need to save them as well.

 


int caller()
{
    int x, y;
    int Z[20];
    ...
    x = A(x, y, Z);
    ...
}
caller:   addi $sp, $sp, -28
        sw $s2, 24($sp)
        sw $s1, 20($sp)
        sw $s0, 16($sp)
        sw $a2, 12($sp)
        sw $a1, 8($sp)
        sw $a0, 4($sp)
        sw $ra, 0($sp)

        ...
        move $a0, $s0
        move $a1, $s1
        move $a2, $s2
        jal A
        move $s0, $v0
        ...

        lw $ra, 0($sp)
        lw $a0, 4($sp)
        lw $a1, 8($sp)
        lw $a2, 12($sp)
        lw $s0, 16($sp)
        lw $s1, 20($sp)
        lw $s2, 24($sp)
        addi $sp, $sp, 28
        jr $ra
# adjust stack pointer
# save $ra, $a0-a2, $s0-s2 to stack







#... (assume x, &y, z are in s0, s1, s2)
# store x, &y, Z into $a0, $a1, $a2


# jump to function named A
# store return value ($v0) in x
#...

# restore $ra, $a0-a2, $s0-s2 from stack






# adjust stack pointer
# return to address in $ra


Do we need to store anything else on the Stack?

If we need to refer to &y, where is y? Where is the memory allocated for Z?
Local variables are stored on the Stack, although we can just store x in $s0.

 


int caller()
{
    int x, y;
    int Z[20];
    ...
    x = A(x, y, Z);
    ...
}
caller:   addi $sp, $sp, -104

        sw $s0, 16($sp)
        sw $a2, 12($sp)
        sw $a1, 8($sp)
        sw $a0, 4($sp)
        sw $ra, 0($sp)

        ...
        move $a0, $s0
        addi $a1, $sp, 20
        addi $a2, $sp, 24
        jal A
        move $s0, $v0
        ...

        lw $ra, 0($sp)
        lw $a0, 4($sp)
        lw $a1, 8($sp)
        lw $a2, 12($sp)
        lw $s0, 16($sp)
        addi $sp, $sp, 104
        jr $ra
# save space for y and Z on the stack
#    (4 bytes + 80 bytes)
# save $s0 to stack (x)
# save $ra, $a0-a2 to stack




#... (y, z are at 20($sp), 24($sp))
# store x in $a0
# store &y in $a1
# store Z in $a2
# jump to function named A
# store return value ($v0) in x
#...

# restore $ra, $a0-a2, $s0 from stack




# adjust stack pointer
# return to address in $ra


Alyce Brady, Kalamazoo College