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
Related
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
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
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.
I am trying to implement puts in MIPS. I made it work with $a0. It printed the string starting at the address of that register. However, I am now trying to implement puts for an arbitrary amount of strings, meaning that I can't use the registers anymore. I am confused as to how to use the stack efficiently. From my main procedure, I stack an arbitrary amount of strings. I then want to jal to puts, which will print all the strings. I also pass on top of the stack the number of strings to print.
Here is my code for puts :
# puts - prints ASCII to the screen
# prints from $a0, $a1, $a2, $a3 (buffers)
# stops when chracter is NULL
# ASSUME THAT WHEN PUTS IS CALLED, AT LEAST ONE STRING IS PASSED
#
# CALLING CONVENTION
#
# I decided not to use any of the registers $a0-$a4.
# Instead, the caller stacks all the strings it wants to print in the stack.
# On top of it, it adds the number of strings it wants to print.
# puts will loop, printing each string, until it has printed all of them.
#
# Since the caller is using "s" registers, puts must save them to the stack.
# Thus, these will be put on top of the stack.
# puts will have to access the strings below the stacked registers.
#
# ============ STACK DIAGRAM ==============
#
# \ Number of Strings \ TOP
# \ String 1 \ +200
# \ String 2 \ +400
# \ String 3 \ +600
# \ String 4 \ +800
# \ String 5 \ +/000
# \ String 6 \ +...
# \ ... \
#
# on entry:
# $ra -- return address
# 0($sp) -- number of strings to print
# x($sp) -- strings to print
#
# on exit:
# $v0 -- number of character printed
#
.text
puts:
addi $sp, $sp, -20 # make room for 6 registers
sw $ra, 16($sp) # save $ra on the stack
sw $s0, 12($sp) # save $s0 on the stack
sw, $s1, 8($sp) # save $s1 on the stack
sw, $s2, 4($sp) # save $s2 on the stack
sw, $s3, 0($sp) # save $s3 on the stack
lw $s0, 224($sp) # copy address of first string inside $s0
lw $s1, 24($sp) # copy number of strings to print inside $s1
move $s2, $zero # counter for the number of strings printed
move $s3, $zero # counter for the number of characters sent to putchar
putsString:
** lbu $t3, ($s0) # load ccurrent char into #t3
beq $t3, $zero, exitString # exit puts if the current character is the NULL character
move $a0, $t3 # put the character to print inside $a0, accessible by putchar
jal putchar # print char using putchar
addi $s3, $s3, 1 # character count += 1
addi $s0, $s0, 4 # increment string address by 1 word (4 bytes)
j putsString # Loop to print next character
exitString:
addi $s2, $s2, 1 # increment number of strings printed
beq $s1, $s2, exitPuts # if # of strings to print = # of strings printed, then exit puts; else, increment # of strings printed
addi $s0, $s0, 200 # $s0 now points to next string to print
j putsString
exitPuts:
move $v0, $s4 # return number of character printed
lw $s3, 0($sp) # restore stack
lw $s2, 4($sp) # -
lw $s1, 8($sp) # -
lw $s0, 12($sp) # -
lw $ra, 16($sp) # -
addi $sp, $sp, 20 # pop from stack
jr $ra # return
The line with a ** is the faulty one for now. I get Runtime exception at 0x00400124: address out of range 0x00000000.
Here is how I save the strings to the stack (I read 2 (2 is hardcoded) strings for now with gets).
init:
beq $s0,2,continue
move $a0, $s2 # load buffer address into $a0
la $t1, limit # - load limit into $a1
lb $a1, ($t1) # - ...
jal gets # call gets - it will modify buffer
move $t0, $v0 # $t0 = string count returned by gets
moveBufferToStack:
lbu $t1, ($s2) # get first character inside buffer
beqz $t1, endMoveBuffer
sw $t1, ($sp) # copy buffer(i) into array(i)
addi $sp, $sp, 4 # array pointer points a position forward
addi $s2, $s2, 4 # same for array pointer
j moveBufferToStack
endMoveBuffer:
addi $sp, $sp, 200 # step to next array cell
addi $s0, $s0, 1 # increment number of strings read
j init # loop until we have 9 elements
continue:
jal puts
j done
Just focusing on the problem line, I see this:
lw $s0, 224($sp) # copy address of first string inside $s0
...
putsString:
lbu $t3, ($s0) # load ccurrent char into #t3
So you've loaded $s0 with the contents of the memory starting 224 bytes past $sp. If I'm understanding correctly, that's the first four bytes of a string. Meaning, if the string is "Madam, I'm Adam", that $s0 contains 'a' 'd' 'a' 'M' (if I've got my endianness right).
So when you do lbu $t3, ($s0), you're not loading the current character into $t3. You're loading the byte pointed to by $s0, which is going to be a random spot in memory. If your string is blank, $s0 might contain 0x00000000 - and thus would generate the error you're getting.
I think what you want to do, instead of lw, is addi $s0, $sp, 224. Then, $s0 will point to the address at $sp + 224.
I am attempting to reverse a string of ints when given size and string. Here is what I have so far. I know my problem is in the loop section, mainly in figuring out how to get a pointer to point at the back of the string and move what is contained to where it should go
Any help would be appreciated:
.data
Size: .word 9 # Size is 9
Vals: .word 1, 2, 3, 4, 5, 6, 7, 8, 9 # Vals[9]={1,2,..}
.text
main:
la $t1, Size # get the address of variable Size
la $t2, Vals # get the address of variable Vals
lw $t3, 0($t1) # fetch the value of Size to register $t3
sra $t4, $t3, 1 # right shift arithematic, now $t4 contains Size/2
sll $t3, $t3, 2 # left shift logic, now $t3 contains Size*4
loop:
lb $t5, 0($t2)
sb $t0, 36($t2)
sb $t0, ($t5)
addi $t0, $t0, 4
addi $t5, $t5, -4
bne $t5, $t4, end
j loop
end:
la $t0, Vals # get the address of Vals to $t0
la $t1, Size # get the address of Size to $t1
lw $t3, 0($t1) # get Size to $t3
sll $t3, $t3, 2 # left shift logic, now $t3 contains Size*4
add $t1, $t0, $t3 # $t1=Vals+Size*4 => array bound
li $v0, 1 # service 1 is print integer
lab4:
lw $a0, 0($t0) # load desired value into argument register $a0
syscall # print the value in $a0
addi $t0, $t0, 4 # increase array index
bne $t0, $t1, lab4 # check if reach array bound
There are some issues in that loop:
You are reading bytes instead of words (use lw/sw instead of lb/sb
You are mixing contents with addresses (usage of register $t5)
You are adding/subtracting 4 to the contents read instead of the pointers to the array
The way you are trying to reverse the array seems wrong as adding 36 (=9x4) would point to a location after the end of the array
What you should do is use 2 pointers: one which starts pointing to the beginning of the array and another that starts pointing to the end of the array, then read both items and interchange its contents. Now move the the next element in each pointer (one pointer moves ahead and the other move behind), and repeat the process until all the items are processed (that is, when both pointers crosses).
E.g (snip):
addu $t7, $t2, $t3 # $t5 contains address of end of string
loop:
addi $t7, $t7, -4 # moves pointer backwards
lw $t5, 0($t2)
lw $t0, 0($t7)
sw $t5, ($t7) # interchange
sw $t0, ($t2) # contents
addi $t2, $t2, 4 # moves pointer forward
ble $t2, $t7, loop