1/22/09

MIPS Compare Strings

This is another MIPS example (program) which:
- ask user to enter two strings (max 20 characters) and saves them into memory.
- call (jal) a function (strcmp) which compares the two string and returns 0 (zero) if the two strings are the same or 1 (one) if not.
- prints a message depending on what strcmp returned.

.data
msg1:.asciiz "Please insert text (max 20 characters): "
msg2:.asciiz "\nNOT SAME"
msg3:.asciiz "\nSAME"
str1: .space 20
str2: .space 20
.text
.globl main
main:
addi $v0,4
la $a0,msg1
syscall
li $v0,8
la $a0,str1
addi $a1,$zero,20
syscall #got string 1
li $v0,4
la $a0,msg1
syscall
li $v0,8
la $a0,str2
addi $a1,$zero,20
syscall #got string 2

la $a0,str1 #pass address of str1
la $a1,str2 #pass address of str2
jal strcmp #call strcmp

beq $v0,$zero,ok #check result
li $v0,4
la $a0,msg2
syscall
j exit
ok:
li $v0,4
la $a0,msg3
syscall
exit:
li $v0,10
syscall

strcmp:
add $t0,$zero,$zero
add $t1,$zero,$a0
add $t2,$zero,$a1
loop:
lb $t3($t1) #load a byte from each string
lb $t4($t2)
beqz $t3,checkt2 #str1 end
beqz $t4,missmatch
slt $t5,$t3,$t4 #compare two bytes
bnez $t5,missmatch
addi $t1,$t1,1 #t1 points to the next byte of str1
addi $t2,$t2,1
j loop

missmatch:
addi $v0,$zero,1
j endfunction
checkt2:
bnez $t4,missmatch
add $v0,$zero,$zero

endfunction:
jr $ra

Example of the output:

Please insert text (max 20 characters): akoma ena blog
Please insert text (max 20 characters): computers blog
NOT SAME

Please insert text (max 20 characters): computers blog
Please insert text (max 20 characters): computers blog
SAME

Thank you very much for visiting and reading. I hope this example was helpful to you.
Any comments are appreciated.

7 comments:

Anonymous said...

When I try to run this using my Mars MIPS simulator the program doesn’t assemble.
This is the error message it displays.
Error in CompareStrings.s line 16 position 1: "addi": Too few or incorrectly formatted operands. Expected: addi $1,$2,-100

Andreas Papadopoulos said...

change it to li $v0,4

Dee Nice said...

Or you can simply addi $v0,$v0,4

Tavu said...

A better function (wich returns like in c/c++):
It's called with $a0-adress of the first string $a1-|- of the second string
Return $v0 ->
0 - equal string
1 - a > b
-1 - a < b

strcmp:
add $t0,$zero,$zero #t0=0
add $t1,$zero,$a0 #t1=first string address
add $t2,$zero,$a1 #t2=second string address
loop:
lb $t3,0($t1) #load a byte from string 1
lb $t4,0($t2) #load a byte from string 2
beqz $t3,checklower #str1 is finished - if str2 is not also finished str1 < str2
beqz $t4,higher #str2 is finished -> str2 > str1
blt $t3,$t4,lower #if str1 < str2 -> str1 is lower
bgt $t3,$t4,higher #if str1 > str2 -> str1 is higher
addi $t1,$t1,1 #t1 points to the next byte of str1
addi $t2,$t2,1
j loop

checklower:
beqz $t4,equal
j lower
equal:
li $v0,0
jr $ra

lower:
li $v0,-1
jr $ra

higher:
li $v0,1
jr $ra

Anonymous said...

I think this code has a bug. If string1 is "b" and string2 is "a" then the result in $v0 is 0. That's not right.

LightnessHope said...

That bug can be resolved if you change this:

slt $t5,$t3,$t4

to this:

sne $t5,$t3,$t4

Because in the first one (slt), its writing a 1 if string 1 byte is lower than string 2 byte and a zero in other case; meanwhile in the second (sne) its writing a 1 if string 1 byte is different to string 2 byte and zero in other case.

So if you write "b" in string 1 and "a" in string 2 with sne, it should give you "NOT SAME" thing.

Greetings from Spain! :)

Anonymous said...

more comments would be nice, as an example, why do you use $a1 and set it to 20, but other than that, seems pretty good