In this sequence of videos I translate the following code. There are
two intended goals of this demonstration:
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
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