Assembly RA (return address)

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

Section 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