Assembly return address register

Matt Chung

October 12, 2018

About a year has passed since I took computer organization and I’m a bit disappointed of how much of the material faded from my memory. I only realized this while reading about Exception Control Flow (ECF) in the book Computer Systems: A programmer’s perspective, when the authors mentioned:

As with a procedure call, the processor pushes a return address on the stack before branching to the handler

I had to pause for a moment because despite a handful of assembly programs — one of them where I implemented quicksort — I totally forgot how, in assembly, how the return address gets handled. But after reviewing my own assembly program that I wrote earlier this year, I realized that the syscall directs the processor to store the PC value into the ra (return address) register. Then, it’s the callee’s responsiblity to then save that value on the stack and after its routine finishes, call jr (jump return).

Here’s some sample code:

main:
    la $a0, numbers     # Load the address numbers into $a0, the first argument
    li $a1, 0       # Load 0 into $a, the second argument
    lw $t0, length      # Load the length of the array into temporary register $t0
    sub $a2, $t0, 1     # Subtract 1 from the length of the array and store into $a3, the first argument
    jal quicksort
    li $v0, 10
    syscall

quicksort:

quicksort_if:

    bge $a1, $a2, quicksort_end_if  # Check if low < high

quicksort_body:
    addi, $sp, $sp, -24 # Update the stack pointer, allocating enough room for savin the 6 registers
    sw $ra, 0($sp)      # Store return address on the stack
    sw $s0, 4($sp)      # Store $s1 on the stack
    sw $s1, 8($sp)      # Store $s2 on the stack
    sw $s2, 12($sp)     # Store $s3 on the stack
    sw $s3, 16($sp)     # Store $s3 on the stack
    sw $s4, 20($sp)     # Store $s3 on the stack
    move $s0, $a0       # Store $a0 (address of array) into $s0
    move $s1, $a1       # Store $a1 (low) into $s1
    move $s2, $a2       # Store $a2 (high) into $s2
    jal partition       # Call the subprogram partition
    move $s4, $v0       # Store pivot -1 into $a2
    move $a0, $s0       # Store $s0, array, into $a0
    move $a1, $s1       # Store $s1, low, into $a1
    move $a2, $s4       # Store pivot position in $a2
    sub $a2, $a2, 1     # Subtract 1 from $a2 (i.e. pivot - 1)
    jal quicksort       # First call to quicksort (i.e. quickSort(array, low, pivotPosition - 1)
    move $a0, $s0       # Store array into $a0
    move $a1, $s4       # Move pivot into $a1
    add $a1, $a1, 1     # Add 1 to $a1 (i.e. pivot + 1)
    move $a2, $s2       # Move high (i.e. $s2) into $a2
    jal quicksort       # Second call to quicksort (i.e. quickSort(array, pivotPosition + 1, high)
    lw $ra, 0($sp)      # Restore the return address from the stack and back into $ra
    lw $s0, 4($sp)      # Restore $s0 from the stack
    lw $s1, 8($sp)      # Restore $s1 from the stack
    lw $s2, 12($sp)     # Restore $s2 from the stack
    lw $s3, 16($sp)     # Restore $s2 from the stack
    lw $s4, 20($sp)     # Restore $s2 from the stack
    addi $sp, $sp, 24   # Pop the call frame