CS232 MIPS Coding Example 2

In this sequence of videos I translate the following code. There are two intended goals of this demonstration:
  1. demonstrating how to write a (non-trivial) function that allocates a stack frame, including managing the movement of variables to an from the stack, and
  2. demonstrating the difference in usage between caller-saved and callee saved registers and when each should be used.
The demonstration has two parts: first, I do a translation using only caller-saved registers; second, I do a demonstration using callee-saved registers. Before watching the videos, familiarize yourself with the C code, since they assume familiarity with the code. Here are complete (testable) versions of the C code and the MIPS code for both functions.

Part 1: caller-saved


Part 2: callee-saved


Here is the C code I translate:
// This function iterates through two character strings "s1" and "s2" 
// performing a character-by-character comparison to see which is earlier
// in alphabetical order.
//
// Note: in order to reduce the amount of code to be translated, we've 
// left out the code that checks for the end of string, so this code
// doesn't work for strings that are equal or where one string is a
// prefix of the other.
int
case_insensitive_strcmp(const char *s1, const char *s2) {
  int i = 0;
  while (1) {
    int c1 = tolower(s1[i]);
    int c2 = tolower(s2[i]);
    if (c1 == c2) {
      ++ i;
      continue;
    }
    return c1 - c2;
  }
}
Here is the resulting MIPS code:
## here is a version using entirely caller-saved variables	
ci_strcmp1:
	sub	$sp, $sp, 20
	sw	$ra, 0($sp)
	sw	$a0, 4($sp)
	sw	$a1, 8($sp)

	li	$t0, 0		# i
ci_loop1:
	lw	$t1, 4($sp)	# s1
	add	$t1, $t1, $t0	# &s1[i]
	lb	$a0, 0($t1)	# s1[i]
	sw	$t0, 12($sp)	# save i
	jal	tolower		# c1 in $v0
	sw	$v0, 16($sp)	# save c1
	lw	$t1, 8($sp)	# s2
	lw	$t0, 12($sp)	# i
	add	$t1, $t1, $t0	# &s2[i]
	lb	$a0, 0($t1)	# s2[i]
	jal	tolower		# c2 in $v0
	lw	$t1, 16($sp)	# c1
	bne	$t1, $v0, ci_done1
	lw	$t0, 12($sp)	# i
	add	$t0, $t0, 1	# ++ i
	j	ci_loop1

ci_done1:
	sub	$v0, $t1, $v0	# c1 - c2
	lw	$ra, 0($sp)
	add	$sp, $sp, 20
	jr	$ra
	
## here is a version using callee-saved variables	
ci_strcmp2:
	sub	$sp, $sp, 20
	sw	$ra, 0($sp)
	sw	$s0, 4($sp)
	sw	$s1, 8($sp)
	sw	$s2, 12($sp)
	sw	$s3, 16($sp)
	move	$s1, $a0	# s1
	move	$s2, $a1	# s2
	
	li	$s0, 0		# i
ci_loop2:
	add	$t1, $s1, $s0	# &s1[i]
	lb	$a0, 0($t1)	# s1[i]
	jal	tolower		# c1 in $v0
	move	$s3, $v0	# c1
	add	$t1, $s2, $s0	# &s2[i]
	lb	$a0, 0($t1)	# s2[i]
	jal	tolower		# c2 in $v0
	bne	$s3, $v0, ci_done2
	add	$s0, $s0, 1	# ++ i
	j	ci_loop2

ci_done2:
	sub	$v0, $s3, $v0	# c1 - c2
	lw	$ra, 0($sp)
	lw	$s0, 4($sp)
	lw	$s1, 8($sp)
	lw	$s2, 12($sp)
	lw	$s3, 16($sp)
	add	$sp, $sp, 20
	jr	$ra

email