MIPS: Address out of range - arrays

I'm trying to make a program that given a string inputted by the user(input), sees if it matches any of the strings in the names array. When I'm trying to compare each name in the names array to the inputted string (input), I keep getting the following message:
line 37: Runtime exception at 0x00400064: address out of range 0x1040100c
I'm unsure if my addressing for the items in the array are off or the addresses for the specific characters in those array items. I've been banging my head against the wall for the last few hours trying to figure out why my addresses are off. I've looked through the other answers on Stack Exchange, but there haven't been any that dealt with getting a string from an array and then going through that string and comparing it to another string
.data
input: .space 64
names: .asciiz "steve","john","chelsea","julia","ryan"
ages: .byte 20,25,22,21,23
greeting: .asciiz "Please enter a name: \n"
notfoundmessage: .asciiz "Not found!"
foundmessage: .asciiz "good for you! found"
.text
li $v0,4
la $a0, greeting
syscall #asks for name
li $v0,8
la $a0,input #input address stored at $a0
li $a1,64
syscall
li $t0,0 #current element in array
la $a1,names #stores names array address
loop:
add $a1,$a1,$t0 #adds offset
jal checkName
bne $v0,$zero,found #if one is returned, word has been found
beq $t0,5,notFound #if counter reaches 5, whole array has been searched
addi $t0,$t0,4 #add multiples of 4 to each base address to get next array element
j loop
checkName:
move $t3, $a0
move $t4, $a1
li $t5, 0 #offset
loop2:
add $t3, $t3, $t5
add $t4, $t4, $t5
lb $t6, 0($t3)
lb $t7, 0($t4) **#THIS LINE IS THE PROBLEMATIC ONE**
bne $t6, $t7, mismatch
beq $t6, $zero, doubleCheck
beq $t7, $zero, doubleCheck
addi $t5,$t5,1
j loop2
doubleCheck:
bne $t6,$t7,mismatch
li $v0,1
jr $ra
mismatch:
li $t5,0
li $v0,0
jr $ra
notFound:
li $v0,4
la $a0,notfoundmessage
syscall
li $v0,10
syscall
found:
li $v0,4
la $a0,foundmessage
syscall
li $v0,10
syscall

Related

Can't figure out how to retrieve values from heap in MIPS (MARS)

I am new to using dynamic memory in mips. I have to create a program that takes 2 integers from the user, find the positions where the binary forms of those numbers have a 1, print the positions for each number/set (For example: 1000 1001 1100 0000 0000 0010 1000 1110 corresponds to the set: {2, 3, 4, 8, 10, 23, 24, 25, 28, 32}). Then take another integer from the user and see if it is one of the positions in either set. Eventually I will have to find the union and intersection of the two sets but I am not there yet.
So I printed out both sets normally but I also saved them to heap because I figured that would be the only way to be access them later to see if the next number is a member of either set. My problem is that, for the life of me, I can't figure out how to retrieve the sets from heap to use them again.
My code is below. I know it is kind of long so for reference, I store them in dynamic memory in the SetOne and SetTwo functions, and I am trying to retrieve them in the ElementSetOne and ElementSetTwo functions. Sorry if I'm not being descriptive enough, I'm still very new to StackOverflow. Thanks.
.data #Data section
Prompt1: .asciiz "\nEnter first number: "
Prompt2: .asciiz "\nEnter second number: "
Result1: .asciiz "\nMembers of Set 1: "
Result2: .asciiz "\nMembers of Set 2: "
Prompt3: .asciiz "\nEnter an element to find: "
Result3: .asciiz "\nIt is a member of set 1"
Result4: .asciiz "\nIt is not a member of set 1"
Result5: .asciiz "\nIt is a member of set 2"
Result6: .asciiz "\nIt is not a member of set 2"
Result7: .asciiz "\nUnion of the sets: "
Result8: .asciiz "\nIntersection of the sets: "
Prompt4: .asciiz "\nDo you want to compute set functions again? "
.globl main
.text #Code section
main:
li $v0, 4 #system call code for Print String
la $a0, Prompt1 #load address of Prompt1 into $a0
syscall #print the Prompt1 message
li $v0, 5 #system call code for Read Integer
syscall #reads the value of 1st integer into $v0
move $t0, $v0 #move first integer to $t0
li $v0, 4 #system call code for Print String
la $a0, Prompt2 #load address of Prompt2 into $a0
syscall #print the Prompt2 message
li $v0, 5 #system call code for Read Integer
syscall #reads the value of second integer into $v0
move $t1, $v0 #move second integer to $t1
First:
li $v0, 4 #System call code for Print String
la $a0, Result1 #load address of Print into $a0
syscall #print the string
li $v0, 9 #syscall for dynamic memory allocation (sbrk)
li $a0, 80
syscall
move $s0, $v0
li $t4, 0 #sets count to 0
FirstMask:
beq $t0, 0, Second #if first set is done, go to second
andi $t6, $t0, 1 #first number and 1
addi $t4, $t4, 1 #increase count by 1
beq $t6, 1, SetOne #if and with 1, go to SetOne
srl $t0, $t0, 1 #shift number right 1 position
j FirstMask #restart loop
SetOne: #STORE SET 1
sw $t4, 0($s0) #store position in memory
add $s0, $s0, 4 #increment memory
li $v0, 1 #system call code for Print Integer
move $a0, $t4 #move value to be printed to $a0
syscall #print the the count positiom
li $v0, 11 #syscall number for printing character
li $a0, 32 #move ascii code for space in $a0
syscall #print blank space
srl $t0, $t0, 1 #shift input number right 1 position
j FirstMask
Second:
li $v0, 4 #System call code for Print String
la $a0, Result2 #load address of Print into $a0
syscall #print the string
li $v0, 9 #syscall for dynamic memory allocation (sbrk)
li $a0, 80
syscall
move $s1, $v0
li $t4, 0 #reset count to 0
SecondMask:
beq $t1, 0, Element #if number is done go to next step
andi $t6, $t1, 1 #and input with 1
addi $t4, $t4, 1 #increase count by 1
beq $t6, 1, SetTwo #if and with 1, save position number
srl $t1, $t1, 1 #shift right 1 position
j SecondMask
SetTwo: #STORE SET 2
sw $t4, 0($s1) #store position in memory
add $s1, $s1, 4 #increment memory
li $v0, 1 #system call code for Print Integer
move $a0, $t4 #move value to be printed to $a0
syscall #print the count
li $v0, 11 #syscall number for printing character
li $a0, 32 #move ascii code for space into $a0
syscall #print blank space
srl $t1, $t1, 1 #shift right 1 position
j SecondMask
Element:
li $v0, 4 #System call code for Print String
la $a0, Prompt3 #load address of Print into $a0
syscall #print the string
li $v0, 5 #system call code for Read Integer
syscall #reads the value of 1st integer into $v0
move $t2, $v0 #move first integer to $t2
ElementSetOne: #RETRIEVE SET 1
lw $t3, 0($s0) #load first number from memory into $t3
beq $t2, $t3, InSetOne #if element is in memory, go to InSetOne
bgt $s0, 40, NotSetOne #if element isnt in entire array, go to NotSetOne
addi $s0, $s0, 4 #increment memory by 4
j ElementSetOne
InSetOne:
li $v0, 4 #System call code for Print String
la $a0, Result4 #load address of Print into $a0
syscall #print the string
j ElementSetTwo
NotSetOne:
li $v0, 4 #System call code for Print String
la $a0, Result5 #load address of Print into $a0
syscall #print the string
j ElementSetTwo
ElementSetTwo: #RETREIVE SET 2
lw $t3, 0($s1) #load first number from memory into $t3
beq $t2, $t3, InSetTwo #if element is in memory, go to InSetOne
bgt $s1, 40, NotSetTwo #if element isnt in entire array, go to NotSetOne
addi $s1, $s1, 4 #increment memory by 4
j ElementSetTwo
InSetTwo:
li $v0, 4 #System call code for Print String
la $a0, Result5 #load address of Print into $a0
syscall #print the string
j Exit
NotSetTwo:
li $v0, 4 #System call code for Print String
la $a0, Result6 #load address of Print into $a0
syscall #print the string
j Exit
Exit:
li $v0, 10 #terminate program
syscall #return control to the system
Update: I am taking programming in C next semester so I don't know very much about the language. Essentially, my problem is that I stored a set of numbers into heap. And I can't figure out how to retrieve them now.
I know they were successfully stored because when I look in the heap section while running the program in MARS, I can see them being stored one by one. I'm just trying to retrieve all the numbers for each set now, but what I have just returns 0. So I'm thinking I must be using the wrong address or I'm missing a step somewhere.
I think this is all the code that is relevant:
li $v0, 9 #syscall for dynamic memory allocation (sbrk)
li $a0, 80
syscall
move $s0, $v0
#Theres a loop here to find the values of $t4
SetOne: #STORE SET 1
sw $t4, 0($s0) #store values in $s0
add $s0, $s0, 4 #increment memory
li $v0, 9 #syscall for dynamic memory allocation (sbrk)
li $a0, 80
syscall
move $s1, $v0
#Theres another loop here to find different values of $t4
SetTwo: #STORE SET 2
sw $t4, 0($s1) #store position in memory
add $s1, $s1, 4 #increment memory
#Then later on I want to retrieve these values so i can use them in other loops
ElementSetOne:
lw $t3, 0($s0) #load first number from memory into $t3
beq $t2, $t3, InSetOne #if element is in memory, go to InSetOne
bgt $s0, 40, NotSetOne #if element isnt in entire array, go to NotSetOne
addi $s0, $s0, 4 #increment memory by 4
j ElementSetOne. #loop
ElementSetTwo: #RETREIVE SET 2
lw $t3, 0($s1) #load first number from memory into $t3
beq $t2, $t3, InSetTwo #if element is in memory, go to InSetOne
bgt $s1, 40, NotSetTwo #if element isnt in entire array, go to NotSetOne
addi $s1, $s1, 4 #increment memory by 4
j ElementSetTwo #loop

MIPS Problem in printing the array and get the third element multiply to 4

I'm new to MIPS and I'm stuck in the printing array and the function also kinda mess up
This is my code, it works for the get input I guess but after that, they display the array and have error.
This is the question:
Prompts the user to input an integer number between 1 and 10 using the console
Write a function to initialize an array of 5 elements with the value entered by the user. This function must include the following
A loop
A branch
Write a function to multiply the third element of the array initialized above by the number 4.
Write a function to print all the elements of the array to the console. The third element must be 4 times the other elements. This function must include the following
A loop
A branch
Your code must have three separate functions (in addition to the main section) and function calls
Function to initialize the array
Function to multiply the third element of the array by the user input number
Function to print the arrays to screen.
.data
array: .space 20
prompt: .asciiz "Input 5 integers\n"
.align 3
.text
main:
li $v0, 4
la $a0, prompt
syscall
loop:
beq $t0, 20, exit
li $v0, 5
syscall
sw $v0, array($t0)
add $t0, $t0, 4 #increase index
j loop
exit:
jr $ra
print_loop:
la $t1, array # get array address
li $t2, 0 # set loop counter
beq $t2, 5, exit_print_loop
lw $a0, ($t1) # print value at the array pointer
li $v0, 1
syscall
addi $t2, $t2, 1 # advance loop counter
addi $t1, $t1, 4 # advance array pointer
j print_loop # repeat the loop
exit_print_loop:
li $v0, 10
This is my code that I made and it works perfectly for my test. Thank you!
.data
array: .space 20 #create an array for 5 integer
prompt1: .asciiz "Input 5 integers from 1 to 10 \n"
prompt2: .asciiz "\nThe array is: \n"
prompt3: .asciiz "Third element times 4 is: "
newLine: .asciiz "\n"
.align 3
.text
main:
#prompt the user input
li $v0, 4
la $a0, prompt1
syscall
jal loop
#Calculate and print out the result
li $v0, 4
la $a0, prompt3
syscall
jal cal
#Print out the array
li $v0, 4
la $a0, prompt2
syscall
addi $t1, $zero, 0 #clear t1
jal display
li $v0, 10
syscall
loop:
beq $t0, 20, exit
li $v0, 5
syscall
sw $v0, array($t0)
add $t0, $t0, 4 #increase index
j loop
exit:
jr $ra
cal:
la $s5, array
lw $t5, 8($s5)
mul $t3, $t5, 4
li $v0, 1
move $a0, $t3
syscall
jr $ra
display:
beq $t1, 20, exit_display
lw $t6, array($t1)
addi $t1, $t1, 4
#print current number
li $v0, 1
move $a0, $t6
syscall
#print the new line
li $v0, 4
la $a0, newLine
syscall
j display
exit_display:
li $v0, 10
syscall

MIPS instruction `load word` not loading word into the register

I am writing a program that given an array, it prints out array value and swap two elements of choice by users. This is the code:
# Declare main as a global function
.globl main
# Declare the data
.data
list:
.align 4 # Forces a word to line up at boundary/4
.word 5, 17, 43, 22, 120, 3 # A six-element array
endList:
space:.asciiz " "
newLine: .asciiz "\n"
msg1:.asciiz "Array is: "
msg2:.asciiz "Enter fisrt index to swap: "
msg3:.asciiz "Enter second index to swap: "
msg4:.asciiz "Array after swapping is: "
#.text assembler directive to place the code
.text
# Start the program at main
main:
la $s1, list # Load beginning address of array
into register $s1
la $s2, endList # Load end address of array into register $s2
la $a0, msg1 # Load address of message string into $a0
li $v0, 4 # Load print string system call code into $v0
syscall # System call to print
jal printLoop
jal swap
# Exit
li $v0, 10
syscall
printLoop:
beq $s1, $s2, printDone # Check when array end, go to done
lw $a0, ($s1) # Load word at address of $s1 into $a0
li $v0, 1 # Load print integer system call code
into $v0
syscall # System call to print number
la $a0, space # Load address of space stringinto $a0
li $v0, 4 # Load print string system call code into $v0
syscall # System call to print a space
addi $s1, $s1, 4 # Advance array pointer to the next element
j printLoop # Loop back to next element
printDone:
j $ra
swap:
la $a0, newLine # Print a new line
li $v0, 4
syscall
la $a0, msg2 # Print a message to ask for first index to swap
li $v0, 4
syscall
li $v0, 5 # Get user input, save into $s3
syscall
addi $s3, $v0, 0
la $a0, msg3 # Print a message to ask for second index to swap
li $v0, 4
syscall
li $v0, 5 # Get user input, save into $s4
syscall
addi $s4, $v0, 0
sll $t0, $s3, 2 # Multiply first index by 4 to get its offset
add $t0, $s1, $t0 # Get the address of the first index
sll $t1, $s4, 2 # Multiply second index by 4 to get its offset
add $t1, $s1, $t1 # Get the address of the second index
lw $t2, ($t0) # Load first number at address contained in $t0 into $t2
lw $t3, ($t1) # Load second number at address contained in $t1 into $t3
sw $t2, ($t1) # Store first number into address of second number
sw $t3, ($t0) # Store second number into address of first number
move $a0, $t0
li $v0, 4
syscall
move $a0, $t1
li $v0, 4
syscall
j $ra
When I step through the code using QtSpim, these lines seem to be giving problems:
lw $t2, ($t0)
lw $t3, ($t1)
The values in $t2 and $t3 should be integer values given by the array. For example, if user specifies index 1 and 2, values in $t2 and $t3 should be 5 and 17. Instead it showed weird numbers: 1634890305 and 1936269433 (decimal) in my version.
What is going wrong? I would appreciate any help!
Printloop changes $s1, so when swap uses it, it points at the list end.

Array in Mips Assembly with looping

I am having an issue with my code. I am creating a program that will read in a string, save it into an array and then output the number of times each letter is used in the string. For right now I am having an issue with just the output of the string back to the screen. The string is outputted but the loop never exits, the $t2 value is maybe never set to a value?
.data
intro: .asciiz "Andrew Lofgren, Letter Checker Program"
question: .asciiz "\nPlease enter a string for evaluation: "
alphabet: .ascii "ABCDEFGHIJKLMONOPQRSTUVWXYZ"
results: .space 104
string: .space 1024
.text
main:
jal setup
jal analyze
#jal results
li $v0, 10
syscall
setup:
li $v0, 4 # outputing name and program information
la $a0, intro
syscall
li $v0, 4 # asksing for string input
la $a0, question
syscall
li $v0, 8
la $a0, string
li $a1, 1024
syscall
jr $ra # return
analyze:
la $t0, string # taking string and saving into a tmp
move $t2, $t0 # backup of orignal address
find:
beq $t1, 0, print
addi $t0, $t0, 1
j find
print:
blt $t0, $t2, end #PROBLEM HERE
li $v0, 11
lb $a0, 0($t0)
syscall
addi $t0, $t0, 1
j print
end:
jr $ra
$t0 will never be less than $t2, because $t0 continually increases while $t2 remains the same. To solve this, you need a third register, say $t7, which stores the final index of your string. To calculate the last index, simply add the base address of the string to length which you have defined as 1024. Once $t0 is no longer less than 1024 + string, there are no chars left in the string, and thus we branch to end:. This is done and explained further in the code segment below.
print:
li $t7 , 1024 # Load total byte length of the string
add $t7 , $t7 , $t2 # add it to the base address to get the end
slt $t6 , $t0 , $t7 # check to see if cur index < end
beq $t6 , $0 , end # if we hit the end, branch to end
...
For more information on MIPS instructions, visit this page.

Adding to an array in a subroutine(MIPS/Assembly)

I'm trying to add values to an array inside a subroutine. I can get the first valid value(positive number and divisible by 3) into the array, but the next valid entries don't work. I can enter a valid number and then enter an invalid number and the program works fine, but two valid numbers makes Spim stop working. I've spent a few hours trying to figure it out but no luck. The jumping from one subroutine is a requirement for the assignment, I have a working program but lacks all the unnecessary(in my opinion) subroutines.
.data
array1: .word 80
EnterARVal: .asciiz "Please enter a number:\t"
space: .asciiz " "
errormessage: .asciiz "*****Error: "
notpos: .asciiz " is not a positive number.\n"
notdiv3: .asciiz " is not divisible by 3.\n"
numadded: .asciiz " added to array.\n"
EnterElem: .asciiz "Enter number "
ARReverse: .asciiz "The contents of the array in reverse orders is:\n"
InvalidAR: .asciiz "Invalid number of array elements, please try again.\n"
.text
main:
la $s0, array1 #array1 pointer
li $t0, 1
begin:
jal readNum #go to readNum subroutine
add $a0, $0, $v0 #stores readNum input to $a0
jal verifySize #jumps to verifySize subroutine
add $t1, $v1, $0 #stores 0 or 1 value to $t1
beq $t1, $0, begin #starts over if t1 is 0 or false
beq $t1, $t0, numok #goes to numok if t1 is 1 or true
numok: add $a0, $0, $a0
add $a1, $0, $s0
jal createArray
j exit
readNum: li $v0, 4
la $a0, EnterARVal
syscall
li $v0, 5
syscall
add $v0, $v0, $0
j $ra
verifySize: add $t1, $0, $a0
li $t2, 20
li $t3, 1
li $t4, 0
li $t5, 1
slt $t6, $t1, $t3
beq $t6, $t3, toolow
sgt $t7, $t1, $t2
beq $t7, $t3, toohigh
beq $t7, $t4, oknum
oknum:
add $v1, $t5, $0
j $ra
toolow:
li $v0, 4
la $a0, InvalidAR
syscall
add $v1, $t4, $0
j $ra
toohigh:
li $v0, 4
la $a0, InvalidAR
syscall
add $v1, $t4, $0
j $ra
createArray: add $s1, $a0, $0
add $s0, $a1, $0
li $t0, 0 #counter
li $t2, 1
add $a0, $s1, $0
li $v0, 1
syscall
makingarray: beq $t0, $s1, arraydone
jal readNum #go to readNum subroutine
add $a0, $v0, $0 #stores number from readNum to $a0
jal checkNumPositive #jump to checkNumPositive subroutine
add $t1, $v0, $0
beq $t1, $0, positivenum #if number is positive go to positivenum
beq $t1, $t2, notpositive
positivenum:
jal divisibleBy3
add $t4, $v0, $0
beq $t4, $0, notdivisibleby3
sw $a0, 0($s0)
li $v0, 1
syscall
li $v0, 4
la $a0, numadded
syscall
add $s0, $s0, 4
add $t0, $t0, 1
j makingarray
arraydone:
add $v0, $s0, $0
j $ra
notpositive:
li $v0, 4
la $a0, notpos
syscall
j makingarray
notdivisibleby3:
li $v0, 4
la $a0, notdiv3
syscall
j makingarray
#reverseArray:
divisibleBy3: add $t0, $a0, $0
li $t1, 3
div $t0, $t1
mfhi $t2
mflo $t3
seq $t4, $t2, $0
add $v0, $t4, $0
j $ra
checkNumPositive: li $t0, 0
slt $t1, $a0, $0 #set t1 to 1 if number is less than 0
add $v0, $t1, $t0
j $ra
exit: li $v0, 10
syscall
Any tips with how I can fix createArray is appreciated, thanks.
Your primary problem is you used .word 80 which only reserves a single word with value 80. You probably meant .space 80 to reserve space for up to 20 words (which seems to be the limit enforced in your code).
Further problem is you are not following conventions about which registers need to be preserved.
For example, you use $t0 as counter in createArray and that's not preserved across subroutines, not by convention and de facto not by your code (both divisibleBy3 and checkNumPositive destroy it).
Similar problem with not properly preserving $ra in nested subroutine calls, as such the return address for createArray is overwritten by the subroutines invoked from there.
I assume the intent of the assignment was to teach you about these nuances.

Resources