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 handlerSection 8.1 Exceptions
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