Finding number of character occurrences in string (mips 32) - string

I'm writing a code that takes a string and a character from user as input, Then finds number of occurrences of the character in the string.
Here is my attempt:
.data
string: .space 100 # allc space for string
.text
main:
la $a0, string # input string
li $a1, 100 # maximum size of string
li $v0, 8 # represents reading string
syscall # call system
la $s0, 0($a0) # $s0 contains address of first element of the string
li $v0, 12 # 12 represents reading character
syscall # call system
move $s2, $v0 # $s2= character
li $s1, 100 # $s1= maximum size of string
li $t4, 0 # count (number of occurrances)
li $t0, 0 # i(index)
loop:
bge $t0, $s1, print # i>= string length, exit
add $t1, $s0, $t0 # &A[i]
lb $t2, 0($t1) # A[i]
bne $t2, $s2, skip # skip increasing the counter if item does not equal
add $t4, $t4, 1 # otherwise increment the counter
skip:
add $t0, $t0, 1 # increment index
j loop # go back to loop
print: # print the result
addi $v0, $t4, 0 # $v0= $v4= number of occurrences
li $v0,1 # 1 represents printing integer
syscall # call system
# Terminate the program
li $v0, 10 # 10 represents exit
syscall # call system
But my code is not working properly. It prints a very large number instead of number of occurrences. I even checked it for string with the same size as the space allocated. But it still gives wrong result. Is this problem related to length of string or something else? Please help me debug it.

Try this code :
.data
string: .space 100 # allc space for string
.text
main:
la $a0, string # input string
li $a1, 100 # maximum size of string
li $v0, 8 # represents reading string
syscall # call system
li $v0, 12 # 12 represents reading character
syscall # call system
move $s2, $v0 # $s2= character
li $s1, 100 # $s1= maximum size of string
li $t4, 0 # count (number of occurrances)
li $t0, 0 # i(index)
bge $t0, $s1, print # i>= string length, exit
loop:
lb $s0,($a0) # the first character of string into $s0
bne $s0, $s2, skip # skip increasing the counter if item does not equal
add $t4, $t4, 1 # otherwise increment the counter
skip:
addiu $a0, $a0, 1 # increment index
beq $s0,0,print # go to print label if $s0=0 so $s0 ='\0'
j loop # go back to loop
print: # print the result
#addi $v0, $t4, 0 # $v0= $v4= number of occurrences
li $v0,1 # 1 represents printing integer
move $a0,$t4 # $a0=$t4 = number of occurances of character
syscall # call system
# Terminate the program
li $v0, 10 # 10 represents exit
syscall # call system

Related

Mips error printing length of string

This seems like it should work but clearly doesn't. When I try to count the length of the string it returns some crazy long number. When I one step the program it works fine but prints out the wrong number. Can somebody point me back on track so that I can work on the next function? I just need to figure out what is throwing off the count
############################################
# Program Name: strings.s
# Programmer: David Bierbrauer
# Date: 9/07/2017
############################################
# Functional Description:
#
#
############################################
# Cross References:
#
#
############################################
.data # Data declaration section
stringa: .asciiz "Enter the first string: "
stringb: .asciiz "\nEnter the second string: "
.text
main: # Start of code section
#li $v0, 4 #get first string input
la $a0, stringa
jal read
jal length
jal print
#get second string input
la $a0, stringb
jal read
jal length
jal print
j end
length:
li $t0, -1 #loop count 0
j lengthloop
lengthloop: #exit address $s1
lb $t1, 0($a0) #load next char into $t1
beqz $t1, endlength
addi $a0, $a0, 1 #increment string pointer
addi $t0, $t0, 1 #increment count
j lengthloop
endlength:
jr $ra
equality:
lb $t2, 0($a0)
lb $t3, 0($a1)
bne $t2,$t3 notequal
append:
print:
li $v0, 1
la
syscall
jr $ra
read:
li $v0, 4
syscall #print prompt
li $v0,9
li $a0,80
syscall
move $a0,$v0
li $v0,8
li $a1,80
syscall
jr $ra
end:
li $v0, 10
syscall
The code you've posted doesn't even assemble, because there's a stray la in the print routine.
Aside from that, your length routine returns the length in $t0, while your print routine assumes that the value is in $a0. That's why you get the wrong output.
Your print looks odd. spim yells at me - bad syntax of la pseudoinstruction. I guess, you mean
print:
li $v0, 1
la $a0, 0($t0)
syscall
jr $ra

Finding out number of vowels in given string in MIPS

I have to write a program to count the number of vowels in a string in MIPS. My current code is giving me a memory out of bounds error in QtSPim.
I'm at the beginner level in MIPS, so any help would be appreciated.
Code so far:
.data
str: .space 20
my_chars: .space 20
vow1: .byte 'a'
vow2: .byte 'e'
vow3: .byte 'i'
vow4: .byte 'o'
vow5: .byte 'u'
.text
main:
li $s0,0 #initilaze loop var1
li $t0,20 #initialize loop var2
li $s1,0 #initialize counter
la $t1, my_chars # base address of array
li $a1,20 #max input to be read
li $a0,8
syscall
loop:
beq $s0, $t0, exit
la $t2, str #string into t2
lb $v0, 0($t2) #access first index
lb $t9, vow1
beq $v0, $t9, then #comparing to a
then:
addi $s1, $s1, 1
lb $t8, vow2
beq $v0, $t8, then1 #comparing to e
then1:
addi $s1, $s1, 1
lb $t7, vow3
beq $v0, $t7, then2 #comparing to i
then2:
addi $s1, $s1, 1
lb $t6, vow4
beq $v0, $t6, then3 #comparing to o
then3:
addi $s1, $s1, 1
lb $t5, vow5
beq $v0, $t5, then4 #comparing to u
then4:
addi $s1, $s1, 1
addi $t1, $t1,1 #increment base address
addi $s0, $s0,1 #increment loop variable
j L1
syscall
Because your posted code had missing labels, etc. I couldn't run it to look for the runtime error.
From visual inspection, the read from user input code had a few issues. li $a0,8 should be li $v0,8 [the syscall number to read a string]. $a0 should contain the address of the buffer to read into. In your code, this was 8 and [probably] not a valid address. So, you'd probably want something like la $a0,my_chars or la $a0,str. One of them should be the input buffer and the other seems unnecessary.
As I was trying to add labels [based on educated guesswork], I realized that your program could/would be much simpler if the vowels were in an array, so I refactored the code.
I also changed the loop termination to look for EOS (0x00) instead of decrementing a count, which may have been another potential source of an out-of-bounds issue. This also reduces the number of registers needed (i.e. reduces complexity)
I added the missing boilerplate/syscalls [please pardon the gratuitous style cleanup]:
.data
vowel: .asciiz "aeiou"
msg_prompt: .asciiz "Enter string: "
msg_out: .asciiz "Number of vowels is: "
msg_nl: .asciiz "\n"
str: .space 80
.text
.globl main
main:
# print user prompt
li $v0,4
la $a0,msg_prompt
syscall
# get string to scan
li $v0,8
la $a0,str
li $a1,80
syscall
li $s2,0 # initialize vowel count
la $s0,str # point to string
# registers:
# s0 -- pointer to string character
# s1 -- pointer to vowel character
# s2 -- count of vowels
#
# t0 -- current string character
# t1 -- current vowel character
string_loop:
lb $t0,0($s0) # get string char
addiu $s0,$s0,1 # point to next string char
beqz $t0,string_done # at end of string? if yes, fly
la $s1,vowel # point to vowels
vowel_loop:
lb $t1,0($s1) # get the vowel we wish to test for
beqz $t1,string_loop # any more vowels? if not, fly
addiu $s1,$s1,1 # point to next vowel
bne $t0,$t1,vowel_loop # is string char a vowel? -- if no, loop
addi $s2,$s2,1 # yes, increment vowel count
j string_loop # do next string char
string_done:
# print count message
li $v0,4
la $a0,msg_out
syscall
# print vowel count
li $v0,1
move $a0,$s2
syscall
# print a newline
li $v0,4
la $a0,msg_nl
syscall
# exit program
li $v0,10
syscall

Reverse string in MIPS

I am trying to write a program that gets a user string input and reverse that string in MIPS.
However, I must be doing something horribly wrong as it doesn't just display the user input in reverse but, it also reverses the prompt to the user. It seems that the user input is not identified with a null(zero?) character in the end.
.data
prompt: .asciiz "Please enter your name. You're only permitted 20 characters. \n"
userInput: .space 20 #user is permitted to enter 20 characters
.globl main
.text
main:
# user prompt
li $v0, 4
la $a0, prompt
syscall
# getting the name of the user
li $v0, 8
la $a0, userInput
li $a1, 20
syscall
add $t0, $a0, $0 # loading t0 with address of array
strLength:
lbu $t2, 0($t0)
beq $t2, $zero, Exit # if reach the end of array, Exit
addiu $t0, $t0, 1 # add 1 to count the length
j strLength
Exit:
add $t1, $t0, $0 # t1 = string length
li $t2, 0 # counter i = 0
li $v0, 11
reverseString:
slt $t3, $t2, $t1 # if i < stringlength
beq $t3, $0, Exit2 # if t3 reaches he end of the array
addi $t0, $t0, -1 # decrement the array
lbu $a0, 0($t0) # load the array from the end
syscall
j reverseString
Exit2:
li $v0, 10
syscall
Problem number 1:
add $t1, $t0, $0 #t1 = string length
What you're assigning to $t1 here isn't the length of the string; it's the address of the first byte past the end of the string.
Problem number 2 is that you never increment $t2 (or decrement $t1) within the reverseString loop.
I suggest that you make use of the debugging features in SPIM/MARS (like the ability to set breakpoints and single-step through the code), as that would've made finding these problems yourself fairly simple.

Searching for a word in a sentence in MIPS

I hope you're all having a great day. I was hoping i could get some assistance with my project code. Basically a sentence "FADED IN FADED OUT." is type in when prompted and then a search word "FADED" is typed in and the code is executed to see if the word "FADED" is in the sentence and if it is it will say "x Match(es) Found" and if not "No Match(es) Found". Well when I compile and run it gives me a "line 65: Runtime exception at 0x00400098: address out of range 0x00000000" error and there are multiple lines that have this error. Would anyone be able to assist me with this? I have been trying to do it the past 3 days and finally broke for some help... If you have any questions please let me know!
.data
str: .space 100 # Pre Allocate space for the input sentence
input: .space 30 # Pre Allocate space for the input sentence
ins: .asciiz "Please enter a sentence: " # string to print sentence
seek: .asciiz "Please enter a word: " # string to print sentence
nomatch: .asciiz "No Match(es) Found"
found: .asciiz " Match(es) Found"
newline: .asciiz "\n" # string to print newline
.text
li $v0, 4 # syscall to print string
la $a0, ins # move str into a0
syscall # syscall
li $a1, 100 # allocate space for the string
la $a0, str # load address of the input string
li, $v0, 8 # read string input from user
syscall # issue a system call
move $t9, $a0 # move string to t5
li $v0, 4 # syscall to print string
la $a0, seek # move str into a0
syscall # syscall
la $a0, input # load address of the input string
li $a2, 30 # allocate space for the string
li, $v0, 8 # read string input from user
syscall # issue a system call
move $t8, $a0 # move string to t8
la $s5, input # create space for the input word we are looking for in s5
wloop: # loop to allocate space for the word we are looking for to a register
lb $t0, 0($t8) # load first character into t0
beqz $t0, sentence # branch to sentence loop if null character
sb $t0, 0($s5) # store the current character into current address of s5
addi $t8, $t8, 1 # add one to t8 to move to next character
addi $s5, $s5, 1 # add one to s5 to move to the next allocated space
j wloop # jump back to wloop
la $s4, str # create space for the input sentence
sentence: # loop to allocate space for the word we are looking for into a register
lb $t0, 0($t9) # load first character into t0
beqz $t0, resetsen # branch to check loop if null character
sb $t9, 0($s4) # store the current character into current address of s4
addi $t9, $t9, 1 # add one to t9 to move to next character
addi $s4, $s4, 1 # add one to s5 to move to the next allocated space
j sentence # jump back to sentence
resetsen:
li $s4, 0 # reset sentence back to 0 (first character)
resetword:
li $s5, 0 # reset word we are looking for back to 0 (first character)
check:
lb $t1, 0($s4) # load current character of sentence to t1
beq $t1, 46, quit # branch to QUIT if period found
bne $t1, 70, nextword # if t1 != t0 branch to nextword
beq $t1, 70, checkword # branch to found if t1 = f
nextword: # loop to get to the next word
lb $t1, 0($s4) # load current character to t1
beq $t1, 46, quit # branch to quit if period found
bne $t1, 32, increment # if current character is not a spaace branch to increment
beq $t1, 32, plusone # if current character is a space branch to plusone
increment: # increment procedure
addi $s4, $s4, 1 # add one to s4 to move to next character
j nextword # jump to nextword
plusone: # plusone procedure
addi $s4, $s4, 1 # add one to s4 to move to next character
j resetword # jump to check
checkword:
addi $s4, $s4, 1 # add one to s4 to move to next character
addi $s5, $s5, 1 # add one to s5 to move to next character
lb $t1, 0($s4) # load current character of sentence to t1
lb $t0, 0($s5) # load current character of sentence to t0
bne $t1, $t0, increment # if t0 != t1 branch to increment (looking for a)
addi $s4, $s4, 1 # add one to s4 to move to next character
addi $s5, $s5, 1 # add one to s5 to move to next character
lb $t1, 0($s4) # load current character of sentence to t1
lb $t0, 0($s5) # load current character of sentence to t0
bne $t1, $t0, increment # if t0 != t1 branch to increment (looking for d)
addi $s4, $s4, 1 # add one to s4 to move to next character
addi $s5, $s5, 1 # add one to s5 to move to next character
lb $t1, 0($s4) # load current character of sentence to t1
lb $t0, 0($s5) # load current character of sentence to t0
bne $t1, $t0, increment # if t0 != t1 branch to increment (looking for e)
addi $s4, $s4, 1 # add one to s4 to move to next character
addi $s5, $s5, 1 # add one to s5 to move to next character
lb $t1, 0($s4) # load current character of sentence to t1
lb $t0, 0($s5) # load current character of sentence to t0
bne $t1, $t0, increment # if t0 != t1 branch to increment (looking for d)
addi $t2, $t2, 1 # add one to t2 which counts occurences
j resetword
quit:
beqz $t2, exit # if t2 = 0 branch to exit
li $v0, 1 # syscall to print integer
move $a0, $t2 # move str into a0
syscall # syscall
li $v0, 4 # syscall to print string
la $a0, found # move found into a0
syscall # syscall
j endprogram
exit:
li $v0, 4 # syscall to print string
la $a0, nomatch # move nomatch into a0
syscall # syscall
endprogram:
li $v0, 10
syscall

Push Each Character of a String Into a Stack MIPS

So I'm working on a project in MIPS to check if a string input by the user is a palindrome or not. The part I'm stuck on is reading the string and pushing each character of the string into the stack one by one (the PushLoop part of the code). When I debug it, the program seems to think I haven't entered anything at all. Here's what I have so far:
.text
main:
li $v0, 4 # Prints str1
la $a0, str1
syscall
jal Init # Sets $s0 equal to $sp to compare if the stack is empty later
li $v0, 8 # Read String
la $a0, buffer # Loads memory buffer (100)
li $a1, 100 # Defines length of buffer
syscall
la $t0, buffer # Moves base register to $t0
PushLoop:
lb $a2, ($t0) # Loads current character into $a2
beqz $a2, fin # if $a2 is equal to zero, the loop is terminated
jal Push # Pushes what is stored in $a0 to the stack
add $t0, $t0, -8 # Subtracts from buffer
j PushLoop
fin:
la $t0, buffer # Resets the memory buffer (I think)
PopLoop:
jal IsEmpty # Checks if the stack is empty
lb $a2, ($t0) # Loads current character into $a2
beq $v0, 1, isPal # If stack is empty, jump to isPal
jal Pop # Pops what is stored in the stack to $t1
add $t0, $t0, -8 # Subtracts from buffer
bne $a2, $t1, notPal
j PopLoop
notPal:
li $v0, 4 # Prints str3
la $a0, str3
syscall
li $v0, 0 # loads 0 into $v0
j end
isPal:
li $v0, 4 # Prints str2
la $a0, str2
syscall
li $v0, 1 # loads 1 into $v0
j end
#EXIT
end:
li $v0, 10 # ends the program
syscall
Push:
addi $sp, $sp, -8 # Move stack pointer
sb $a2, ($sp) # Store contents of $a2 at ($sp)
jr $ra
Pop:
lw $t1, ($sp) # Pop char from stack and store in $t1
addi $sp, $sp, 8 # Move stack pointer
jr $ra
Init:
add $s0, $sp, $zero # Sets $s0 equal to $sp
jr $ra
IsEmpty:
beq $sp, $s0, Yes # If $s0 is equal to the initial value of $sp, then stack is empty
li $v0, 0 # Loads 0 into $v0
jr $ra
Yes:
li $v0, 1 # Loads 1 into $v0
jr $ra
.data # Data declaration section
str1: .asciiz "Please enter a String: "
str2: .asciiz "Is a palindrome!"
str3: .asciiz "Is NOT a palindrome"
buffer: .space 100
I'm sure there are more things wrong with the code, but I'm just trying to squash one bug at a time. Thanks so much for helping me out!
You're not using syscall 8 properly:
li $v0, 8 # Read String
la $t0, buffer # Loads memory buffer (100)
syscall
If you read the description of syscall 8, it says "Arguments $a0 = buffer, $a1 = length". So those three lines of code should be changed into something like:
li $v0, 8 # Read String
la $a0, buffer
li $a1, 100
syscall
Then you can do la $t0, buffer after the syscall if you still want to use $t0 as the base register for the memory reads in PushLoop.

Resources