Go ahead an familiarize yourself with the C code for each function before watching the videos, since they assume familiarity with the code. The first function counts the number of times a character is found in a string; the second counts the number of times one string is found (in its entirety) in another string.
Here are complete (testable) versions of the C code and the MIPS code for both functions.
// This function iterates through the character string "str" (which is of // length "str_len" and counts how many instances there are of the // character "c". int count_letters(char str[], int str_len, char c) { int count = 0; for (int i = 0 ; i < str_len ; ++ i) { if (str[i] == c) { count ++; } } return count; }Here is the resulting MIPS code:
count_letters: li $v0, 0 # count li $t0, 0 # i cl_loop: bge $t0, $a1, cl_exit add $t1, $a0, $t0 # &A[i] lb $t2, 0($t1) # A[i] bne $t2, $a2, cl_skip add $v0, $v0, 1 cl_skip: add $t0, $t0, 1 j cl_loop cl_exit: jr $ra
// This function iterates through the character string "str" (which is of // length "str_len" and counts how many instances there are of the // string "sub_str" (which is of length "substr_len"). int count_substring(char str[], int str_len, char sub_str[], int substr_len) { int count = 0; for (int i = 0 ; i < (str_len - substr_len) ; ++ i) { int match = TRUE; for (int j = 0 ; j < substr_len ; ++ j) { if (str[i+j] != sub_str[j]) { match = FALSE; break; } } if (match) { count ++; } } return count; }Note: in my haste, I hadn't test "count_substring" before recording this video. I had a bug in my C code. The outer loop condition
i < (str_len - substr_len)
should be i <= (str_len -
substr_len)
(note the less than or equal in the second). I
discovered this in the debugging of this MIPS function as I show in
the debugging videos.
Here is the resulting MIPS code:
count_substring: li $v0, 0 # count li $t0, 0 # i sub $t1, $a1, $a3 # str_len - substr_len cs_loop: bge $t0, $t1, cs_exit li $t2, 1 # match = TRUE li $t3, 0 # j cs_iloop: bge $t3, $a3, cs_done_inner add $t4, $a0, $t0 # &str[i] add $t4, $t4, $t3 # &str[i+j] lb $t4, 0($t4) # str[i+j] add $t5, $a2, $t3 # &sub_str[j] lb $t5, 0($t5) # sub_str[j] beq $t4, $t5, cs_skip li $t2, 0 # match = FALSE j cs_done_inner # break cs_skip: add $t3, $t3, 1 # j ++ j cs_iloop cs_done_inner: beq $t2, $0, cs_skip2 add $v0, $v0, 1 # count ++ cs_skip2: add $t0, $t0, 1 # i ++ j cs_loop cs_exit: jr $ra # return countIn this second example, during the recording, I forgot to write the
cs_skip
label in front of the add $t3, $t3, 1 #
j++
instruction. This bug would be detected when the code is
loaded into xspim, because the assembler would fail to compile the
branch to cs_skip
because it couldn't find a label to
which to connect the branch (a syntax error of sorts). I found it
when I was typing in the code.