MIPS- Reading integers error - arrays

# Programming Project 2
# Noah Heath
# #02685972
.data # Data declaration
# A+B -(C-D x E)
string1: .asciiz "Please enter an integer from range 0 to 32768: "
string2: .asciiz "Next integer: "
string3: .asciiz "Invalid input. Start over. "
userinput: .space 100
var6: .asciiz "The result of A+B -(C-D x E) is: "
.text
main:
la $a0, string1 #load string one and print
li $v0, 4
syscall
la $a1, userinput
li $t1, 5 #set temporary variable to 5
li $t0, 0 #start of counter
input:
beq $t0, $t1, exit
li $v0, 5 # read integer
syscall
blt $v0, $zero, input # if input is less than zero
bgt $v0, 32768, input # if input is greater than 32768
sw $v0, 0($a1)
addiu $a1, $a1, 4
exit:
la $t3, userinput # stores base address of user input array into $t3
lw $t4, ($t3) # load first number
lw $t5, 4($t3) # load second number
lw $t6, 8($t3) # load third number
lw $t7, 12($t3) # load fourth number
lw $t8, 16($t3) # load fifth number
add $s1, $t4, $t5 # adds 1 and 2 into $t0
mult $t7, $t8 # multiplies 2 and 3
mflo $s2 # retrieves from register
sub $s3, $t6, $s2 # subtracts 7 from 6
sub $s4, $s1, $s3 # subtracts 1 from 3
move $a0, $s4 # moves result into a0
li $v0, 1 # instruction to print result
syscall # call operating system to perform operation
li $v0, 10 # exit instruction
syscall
I'm been trying to figure out the reason that my code isn't reading the user integers and storing. I'm sure everything is syntactically correct. Can someone help me understand if I'm using the registers wrong?
QTSpim says Exception occurred at PC = 0x00400060.
Then goes on to say unaligned address in store= 0x1001005b.
It goes on in increments of 4(I'm assuming because of the way the array is indexed.
Final Error message is
Exception 5 [Address error in store] occurred and ignored
Exception 4 [Address error in inst/data fetch] occurred and ignored(repeats 4 times)

There's nothing wrong with the code that asks for user input.
I guess your problem is that you are trying to store what the user entered in a non-aligned address (the line that issues sw $v0, 0($a1) ).
You should add a directive .align 2 before your userinput label, e.g.:
string3: .asciiz "Invalid input. Start over. "
.align 2
userinput: .space 100

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 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.

MIPS - Load integer into array - store address not aligned on word boundary

.data
p1: .asciiz "\nEnter the data for a sorted array: "
p2: .asciiz "\nEnter a value to search for: "
p3: .asciiz " is not found"
p4: .asciiz " is found at "
array: .space 404
.text
main:
la $t0, array # a1 = addr of first int
#Store Array Values
store:
li $v0, 4 # system call code for print_str
la $a0, p1 # address of string to print
syscall # print the first prompt
li $v0, 5 # system call for read_int
syscall # read int to store
move $t1, $v0 # store int
beq $t1, 0, bsearch # once sentinel val hit, go to search
sub $t9, $t0, 4 # set index to the first bit of the last number
j storeVal # store s0 in array
storeVal:
sw $t1, array($t0) # store value in array
addi $t0, $t0, 4 # inc index
j store # continue to add integers
#Binary Search
bsearch:
li $v0, 4 # system call code for print_str
la $a0, p2 # address of string to print
syscall # print the second prompt
li $v0, 5 # system call for read_int
syscall # read int to find
move $a0, $v0 # store int to find
beq $a0, 0, end # once sentinel val hit, go to end prog
la $a2, array # a1 = addr of first int
la $a2, ($t9) # a2 = addr of last int
subu $sp, $sp, 4 # 4 bytes 4 stack
sw $ra, 4($sp) # save return addr
subu $t0, $t9, $s0 # size of array
bnez $t0, searchVal # if not 0, search
move $v0, $a1 # addr of only entry
lw $t0, ($v0) # load entry
beq $a0, $t0, found # if = to int, print found
j notFound # not found
searchVal:
sra $t0, $t0, 3 # comp offset of middle m:
sll $t0, $t0, 2 # t0 = 4(t1/8)
addu $v0, $a1, $t0 # middle m
lw $t0, ($v0) # t0 = m
beq $a0, $t0, found # if = to int, print found
blt $a0, $t0, left # search left
j right # search right
right:
addu $a1, $v0, 4 # search right
jal bsearch
beq $a0, $t0, found # if = to int, print found
j notFound # not found
left:
move $a2, $v0 # search left of m
jal bsearch
beq $a0, $t0, found # if = to int, print found
j notFound # not found
#Print
found:
li $v0, 1 # system call code for print_int
move $a0, $s2 # integer to print (counter
syscall # print it
li $v0, 4 # system call code for print_str
la $a0, p4 # address of string to print
syscall # print the answer part 2
j bsearch # continue to search for more integers
notFound:
li $v0, 1 # system call code for print_int
move $a0, $s2 # integer to print (counter)
syscall # print it
li $v0, 4 # system call code for print_str
la $a0, p3 # address of string to print
syscall # print the answer part 2
j bsearch # continue to search for more integers
#END PROG
end:
li $v0, 10
syscall
I keep getting an error when I attempt to load words into my array, "Error in /../Proj.asm line 58: Runtime exception at 0x00400040: store address not aligned on word boundary 0x200200c2.
57) storeVal:
58) sw $t1, array($t0) # store value in array
59) addi $t0, $t0, 4 # inc index
60) j store # continue to add integers
Line 58 being the sw $t1, array($t0) one. I have tried setting t0 (the line right after .main) the way shown, and setting it to $zero with
addi $t1, $zero, 0
neither of the options will let me set an item into the array, and I cannot find a guide or tutorial to save my life... Also while we're at it, can anyone see if the rest of the code is at least close? Thanks!

How to make a vector that controls the size of two arrays

In MIPS, I have this code and I don't know how to make it so that there are to arrays whose sizes are Controled by a vector. Like-- "Please enter the size of the vector." and you choose five and so the arrays sizes are five. "Enter in the numbers for Array 1". You enter 10 10 10 10 10. Then it asks you to enter in the size for array 2. lastly it shows the the sum and averages for both array 1 and array 2. Heres what I have so far.
.data
prompt: .asciiz "Enter 10 Elements: \n"
avg: .asciiz "Average of these numbers is: "
sum: .float 0
count: .float 10
.text
main:
#size of the vector using prompt
la $a0 prompt
li $v0 4
syscall
li $t1, 40 # t1 has count
li $t2, 0 # t2 is iterator
l.s $f12, sum # t3 has sum
while: bge $t2, $t1, end
li $v0, 6
syscall
add.s $f12, $f12, $f0
addi $t2, $t2, 4
b while
end:
la $a0 avg
li $v0, 4
syscall
lwc1 $f10, count
div.s $f12, $f12, $f10
li $v0, 2
syscall
li $v0, 10
syscall
li $v0, 2
lwc1, $f12 sum
It took me a little while to refresh my memory of MIPS. I wrote up a somewhat small program that asks the user for the size of the vector. Using that size it then dynamically allocates two integer arrays and prompts the user to fill said arrays. Once the arrays have been filled, via user input, the program then prints the first array followed by its sum, then the second array followed by its sum.
I noticed that your code uses floating point numbers. Since I don't know if this is a homework assignment or school project, I thought I'd let you figure out how to convert the below code to use floating point numbers. Also, I purposely left out the code to calculate the average for the same reason (but I did leave comments where the code could possibly be added). Modifying the program to use floating point numbers and adding an average calculation shouldn't be to hard. Let me know if you need further assistance in the comments section of this answer.
Sorry about the spacing of some of the comments in the code, copying from the program I used didn't go so well.
Vector Program
# ====== DATA SEGMENT ====== #
.data
prompt: .asciiz "Enter Size of the Vector:\n"
enter: .asciiz "Enter the "
first: .asciiz " numbers in the first array:\n"
second: .asciiz " numbers in the second array:\n"
sum: .asciiz "Sum of these numbers is: "
avg: .asciiz "Average of these numbers is: "
open: .asciiz "[ "
close: .asciiz " ]\n"
comma: .asciiz ", "
lf: .asciiz "\n"
a1: .word 0 # first array
a2: .word 0 # second array
# syscall variables
printi: .word 1 # print_int
printf: .word 2 # print_float
prints: .word 4 # print_string
readi: .word 5 # read_int
readf: .word 6 # read_float
sbrk: .word 9
exit: .word 10
# ====== TEXT SEGMENT ====== #
.text
main:
# initialize and describe registers
li $s0, 0 # vector size
li $s1, 0 # first array's sum
li $s2, 0 # second array's sum
li $s6, 0 # temporary sum store
li $s7, 0 # temporary array address store
li $t9, 0 # loop iterator
# prompt for vector size
la $a0, prompt
lw $v0, prints
syscall
# get vector size integer into $s0
lw $v0, readi
syscall
add $s0, $zero, $v0 # store vector size in $s0
# dynamically allocate first array
mul $t1, $s0, 4 # put size * 4 in $t1
add $a0, $zero, $t1 # put mul result in $a0
lw $v0, sbrk # allocate size * 4 bytes in memory
syscall
sw $v0, a1 # put address returned by sbrk in a1
# dynamically allocate second array
lw $v0, sbrk # allocate another size * 4 bytes in memory
syscall
sw $v0, a2 # put address returned by sbrk in a2
# prompt for first array elements
jal print_enter
la $a0, first
lw $v0, prints
syscall
# fill the first array and calculate sum
lw $s7, a1
jal array_fill
add $s1, $zero, $s6 # put first sum in $s1
# prompt for second array elements
jal print_enter
la $a0, second
lw $v0, prints
syscall
# fill the second array and calculate sum
lw $s7, a2
jal array_fill
add $s2, $zero, $s6 # put second sum in $s2
# print the first array
lw $s7, a1
jal print_array
# print the sum of the first array
la $s6, ($s1)
jal print_sum
# TODO: Add array1 average calculation and output
# print the second array
lw $s7, a2
jal print_array
# print the sum of the second array
la $s6, ($s2)
jal print_sum
# TODO: Add array2 average calculation and output
b end
print_enter:
# print "Enter the "
la $a0, enter
lw $v0, prints
syscall
# print the number of elements to enter
add $a0, $zero, $s0
lw $v0, printi
syscall
jr $ra
array_fill:
la $s6, ($zero) # set tmp sum to 0
la $t9, ($zero) # set iterator to 0
array_fill_for: bge $t9, $s0, end_array_fill
# get integer from user
lw $v0, readi
syscall
sw $v0, ($s7) # store integer at current array index
add $s6, $s6, $v0 # keep a running sum in $s6
add $s7, $s7, 4 # get address of next array element
add $t9, $t9, 1 # increment iterator
b array_fill_for
end_array_fill:
jr $ra
print_array:
# print opening bracket of array
la $a0, open
lw $v0, prints
syscall
la $t9, ($zero) # set iterator to 0
add $t0, $s0, -1 # loop over size-1 elements
print_array_for: bge $t9, $t0, end_print_array
# print array element at current index
lw $a0, ($s7)
lw $v0, printi
syscall
# print a seperating comma
la $a0, comma
lw $v0, prints
syscall
add $s7, $s7, 4 # get address of next array element
add $t9, $t9, 1 # increment iterator
b print_array_for
end_print_array:
# print last index of array without comma
lw $a0, ($s7)
lw $v0, printi
syscall
# print closing bracket of array
la $a0, close
lw $v0, prints
syscall
jr $ra
print_sum:
# print the sum greeting
la $a0, sum
lw $v0, prints
syscall
# print the sum that's in $s6
la $a0, ($s6)
lw $v0, printi
syscall
# print a line feed
la $a0, lf
lw $v0, prints
syscall
jr $ra
end:
lw $v0, exit
syscall
Test Input/Output
Enter Size of the Vector:
4
Enter the 4 numbers in the first array:
1
2
3
4
Enter the 4 numbers in the second array:
5
6
7
8
[ 1, 2, 3, 4 ]
Sum of these numbers is: 10
[ 5, 6, 7, 8 ]
Sum of these numbers is: 26
-- program is finished running --
Some Links I Found Helpful
MIPS Instruction
Reference
MIPS Dynamic Memory Allocation using
sbrk

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.

Resources