MIPS code broken - loops

I'm working on some MIPS code for my Computer Organizations class, and well I just can't seem to get the MIPS to work correctly and there's not that many MIPS resources online. I'm running the code on PCSPIM. The code is supposed to add 10 to the contents of array2 and store them in array1 and then print array 1. Reworked the code works properly now.
.text
main:
la $t0, array1
la $t1, array2
la $s0, valuec
li $s2, 6
add $t6, $zero, 1 #i = 1
Loop:
addi $t6, $t6, 1 #i++
lw $t2, ($t0)
lw $t5, ($t1)
lw $s1, ($s0)
addu $t2, $t5, $s1
sw $t2, ($t0)
add $t0, $t0, 4
add $t1, $t1, 4
li $v0, 1
move $a0, $t2
syscall
blt $t6, $s2, Loop
li $v0, 10
syscall
.data
array1: .space 20
array2: .word 1,2,3,5,9
valuec: .word 10
PCSPIM prints 0 5 times and returns Exception 7 [Bad data Address] occured and ignored

This is homework so I'm only going to give you clues for now and add to it as you go. A couple of things:
1/ You need to tell us what it's supposed to do. That's the most important thing.
2/ You store array1 address into t0 then reuse t0 within the first loop.
3/ You appear to be confused about addresses and the contents of those addresses ("la $s0, valuec" and "addu $t0, $t1, $s0").
UPDATE:
Actually I have to sign off for a while, so I'll post my solution so as to not leave you in the lurch.
The confusion I referred to before was the fact that you're loading up two addresses into $t1 and $s0, then adding them together to get another address - this is likely to be well beyond your data area (you should really be adding an address and an offset).
That's basically the problem you have with your code (both the zeros being printed and the crash). Your best bet would be to fix that and refer to my code below only as a last resort to see how I would have done it. Copying code will not help you in the long term and you would be wise to assume your educator is also checking all web sites for plagiarism.
This is the code I've come up with (quickly, so you'll need to test it - it may have bugs). I suggest you read the comments in great detail to understand what it's doing.
I'll be back in a few hours to see how you're doing. Cheers.
.text
main:
# Initialization of array pointers and loop
la $t0, array1 # address of array 1
la $t1, array2 # address of array 2
li $t2, 1 # element number
li $t3, 6 # upper limit of elements
# Process each word in array 2, adding 10 and placing
# into array 1.
Loop:
lw $t3, 0($t1) # get word from array 2
addi $t3, $t3, 10 # add 10 to word
sw $t3, 0($t0) # store word into array 1
addi $t0, $t0, 4 # move to next entry in array 1 and 2
addi $t1, $t1, 4
addi $t2, $t2, 1 # increment element number
blt $t2, $t3, Loop # loop until all elements done
# Initialize printing loop by going back to start of array 1
la $t0, array1 # address of array 1
li $t2, 1 # element number
# Loop through array 1, printing each element.
pLoop:
lw $t2, 0($t0) # get word from array 1
li $v0, 1 # 'print' command code
move $a0, $t2 # needs value in $a0
syscall # print it
addi $t0, $t0, 4 # move to next entry in array 1
addi $t2, $t2, 1 # increment element number
blt $t2, $t3, Loop # loop until all elements done
li $v0, 10 # 'terminate' command code
syscall # exit
# Data arrays for array 1 and 2
.data
array1: .word 0,0,0,0,0
array2: .word 1,2,3,4,5

There's a number of possible issues, but the most obvious/likely is that you aren't returning from main before the start of your data section.
jr ra

Related

MIPS Assembly why are these registers loading the same array values?

I'm trying to load in array values in the first and second position but for some reason it's loading in only the value in the first position? Been trying to figure it out for an hour but no luck. This is the code I have. I set $t1 to 0 and $t3 to 4 so I should be loading in the first and second value, yet it only loads in the first value for both $t1 and $t3?
addi $t1, $zero, 0
addi $t3, $zero, 4
FindLessThenLoop:
la $t1, myArray # Load first number
addu $t1, $zero, $t1 # add offset and base together
lw $t1, ($t1) # fetch the data
la $t3, myArray # Load second number
addu $t3, $zero, $t3 # add offset and base together
lw $t3, ($t3) # fetch the data
The code for the first and the second are essentially the same except using a different register, so, we would expect the same results: the value from array position/index 0.
To get the second element, you can do either:
la $t3, myArray # Load second number
addiu $t3, $t3, 4 # add offset and base together
lw $t3, ($t3) # fetch the data
-or-
la $t3, myArray # Load second number
lw $t3, 4($t3) # fetch the data with offset 4
You'll prefer a variation of the first form if you're going to do variable indexing (e.g. a[i]), say in a loop, whereas the second form is for constant indexing (e.g. a[1]).
If you have an integer index, then the following is useful:
# usually done outside of and before a loop:
la $t3, myArray # Load second number
# this part done inside a loop:
sll $t4, $t2, 2 # scale the integer index by 4
addu $t4, $t3, $t4 # add base and offset
lw $t1, ($t4) # fetch the data
Note the following:
there is pre-loop setup of $t3
inside the loop we preserve $t3 so it can be used each iteration
we scale the simple integer index by size of the elements (4x)
An alternative is pointers, which are fairly easy in assembly, but suggest to convert your algorithm to pointers in C first, then take to assembly.
A pointer combines into one variable the notion of base + scaled offset.  A pointer can be incremented to refer to the next element.
Here's a simple illustrative loop that does max value of array, assuming elements are positive:
li $t0, array # t0 is the base array address: &array[0]
li $t1, 0 # t1 is min value variable, initially zero
li $t2, 0 # t2 is the index, aka loop control variable call it "i"
li $t3, 10 # where to stop with "i"
loop1:
beq $t2, $t3, loop1End # if "i" == 10 we're done
sll $t4, $t2, 2 # scale index by 4 due to word-sized elements
add $t4, $t0, $t4 # add base and scaled offset
lw $t4, 0($t4) # fetch element from a[i]
ble $t4, $t1, if1End
move $t1, $t4 # capture the new max, if larger
if1End:
addi $t2, $t2, 1 # next index position
j loop1
loop1End:
... # t1 holds max value from the array

How do I print out the Max and Min of an array in Mips

I am new to mips and I want to print out the max and min of an 8 element array. I saw a question similar to mine but it was done by calling a function readArray and I want to do it without that. Here's what I have so far. I just wanna know whether what I have right now is correct and how to end the loop. Like what do I write to print the correct values
.data
X: .word 1, 2, 3, 4, 5, 6, 7, 8
globl main
.text
main:
la $t0, X
lw $s0, 0($t0) #Sets Max to first value in array
move $s1, $s0 #Sets Min to first value in array
addi $t1, $0, 0 #Sets the counter to 0
li $t1, 0 #Index for the array
loop:
bge $t0, 8 EndLoop
bgt X($t1), $s0, SetMax
blt X($t1), $s1, SetMin
addi $t1, $t1, 4 #Increases the index for the array
addi $t0, $t0, 1 #Increments the counter
SetMax:
move $s0, X($t1)
j loop
SetMin:
move $s0, X($t1)
j loop
EndLoop:
li $v0, 1
addi $s0, $s0, 0
addi $si, $s1, 0
syscall
Am I doing something wrong. Here is the original problem:
Write MIPS code to search through an array X[8] words to find the minimum and maximum values. Store the maximum in register $s0 and the minimum in $s1. Print to screen min and max.
Thanks for the help!
To print an integer you need $v0 to be 1 and $a0 to be equal to the integer you want to print.So point to the register that you have saved the value.
li $v0 1
la $a0 ($s0)
syscall
the same process for $s1 .
To end the program:
li $v0 10
syscall
You may want to make it more visible so print a space or tab between them. Link with some system calls

Trying to create and print elements from an array in MIPS

I'm really struggling with mips it seems, I've read multiple tutorials on how to make arrays and access them, but whenever I try doing the listed methods, my program does nothing.
currently I have this code:
.data
array: .word 1:32 # array of 32 integers
line: .asciiz "\n"
main:
li $t0, 0 # $t0 is the loop induction variable
li $t1, 32 # $t1 is the sentinal value for the loop
la $t2, array # $9 starts as the base address of the array
# and is the address of each element
li $t3, 1 # $12 is the value 18, to be put in desired element
for:
bge $t0, $t1, end_for
sw $t3, ($t2)
li $v0, 4
la $a0, line
syscall
li $v0, 1
move $a0, t3
syscall
add $t2, $t2, 4 # get address of next array element
add $t0, $0, 1 # increment loop induction variable
b valfor
valfor:
addi $t3, $t3, 1
b for
end_for:
li $v0, 10
syscall
When trying to run this, my code immediately finishes. It doesn't list any errors or do anything funny, it just says -- program is finished running (dropped off bottom) --
If someone could point me in the right direction as far as creating, accessing and printing an array of integers I would appreciate it a huge amount.
sites I thought I interpreted accurately to come up with my code:
http://pages.cs.wisc.edu/~cs354-2/onyourown/arrays.html
http://courses.cs.vt.edu/~cs2505/fall2010/Notes/pdf/T23.MIPSArrays.pdf
Have you actually tried to run the code that you put in your question? It contains the line move $a0, t3, which won't assemble in SPIM because of the missing $ sign (t3 should be $t3).
Apart from that I see at least two problems with your code:
You have an infinite loop because of this line:
add $t0, $0, 1 # increment loop induction variable
That just does $t0 = 1. It should be changed to add $t0, $t0, 1.
The other problem is that you've put your code in the data section. The code should be in the text section, i.e. right before main: you should have:
.text
.globl main

How do I avoid hard coding array index/indices within a loop in MIPS?

For example,
$a0 is an index/pointer
$a1 is the address of the array base
I want to access each element of the array within a loop, perform an arithmetic operation to that element, then save it to the next. The index should increase +1 on each iteration.
For a simple example, I'm trying to square each previous element in the array. Initial hard coded values are INDEX[0]=0, ARRAY[0]=2. I've marked where I'm confused. I don't know how to make this variable for each loop.
.data
INDEX: .space 4
.align 2
ARRAY: .space 16
.align 2
.text
la $a0, INDEX
la $a1, ARRAY
li $t0, 0
sw $t0, ($a0) # set INDEX[0]=0
li $t0, 2
sw $t0, ($a1) # set ARRAY[0]=2
LOOP:
lw $t0, ($a0)
sll $t0, $t0, 2 # $a0 * 4 to get element offset
lw $t1, $t0($a1) # STUCK HERE (1)
add $t1, $t1, $t1 # square
lw $t0, ($a0)
add $t0, $t0, 1
sw $t1, $t0($a1) # AND HERE (2)
add $a0, $a0, 1
... keep looping if space remaining in $a1
(1) How do I save the element ARRAY[INDEX] to register $t1 without hardcoding the offset?
(2) How do I save the altered register $t1 to a specific element in the array: ARRAY[INDEX] = $t1
Since the indirect addressing will change on each loop, I want to avoid using 4($a1), 8($a1), etc.
Thank you.
You need to add the base address and index together. Something like this ought to work:
sll $t2, $t0, 2 # $a0 * 4 to get element offset
add $t2, $t2, $a1 # Add the array base address to the scaled index
lw $t1, ($t2) # $t1 = ARRAY[index]
add $t1, $t1, $t1 # square
add $t0, $t0, 1
sw $t1, ($t2)
Note that you're not actually squaring numbers - you're doubling them (t1 = t1 + t1). To square a number you'd multiply it by itself.

MIPS assembly - simple query on how to make the numbers inputted into an array

Below is the code I have which does work. It inputs and stores the numbers the user types (can only be a list of 3 or 4 numbers).
However, this is really long and using an array index would be a lot less code and use less registers but I am uunsure how to do this. Would I need to put brackets around the source2 to make it indexed?
# Entering the user's numbers
# Prompt user to enter their numbers
la $a0, number # load the address of number into $a0
li $v0, 4 # 4 is the print_string syscall
syscall
# Declare an array
la $t3, array # load address of array into $t3
li $t4, 0 # index value 0 is the start of the memory address of the array
mul $t5, $t4, 4 # multiply index value by 4 because each element is four bytes
add $t5, $t3, $t5 # add base address of array to index value into $t5
# Get the first number from the user, put into $t1
li $v0, 5 # load syscall read_int into $v0
syscall # make the syscall
move $t1, $v0 # move the number read into $t1
sw $t1, 0($t5) # store number held in $t1 into memory address location $t5
# Get the second number from the user, put into $t2 and store in array
li $v0, 5 # load syscall read_int into $v0
syscall # make the syscall
move $t1, $v0 # move the number read into $t1
add $t5, $t5, 4 # add 4 bytes to go to the next position in the array
sw $t1, 0($t5) # store number into memory address location of $t5
# Get the third number from the user, put into $t3
li $v0, 5 # load syscall read_int into $v0
syscall # make the syscall
move $t1, $v0 # move the number read into $t1
add $t5, $t5, 4 # add 4 bytes to go to the next position in the array
sw $t1, 0($t5) # store number into memory address location of $t5
# Branches to L3 if user chose to enter only three numbers
beq $t0, 3, L3 # if content in $t0 = 3, branch to L3
# Get the fourth number from the user, put into $t4
li $v0, 5 # load syscall read_int into $v0
syscall # make the syscall
move $t1, $v0 # move the number read into $t1
add $t5, $t5, 4 # add 4 bytes to go to the next position in the array
sw $t1, 0($t5) # store number into memory address location of $t5
# Branches to L3 if user chose to enter only four numbers
beq $t0, 4, L3 # if content in $t0 = 4, branch to L3
EDIT: So far i have this....it isnt working though - it isnt accepting integers which the user has entered
loop:
lw $t2, 0($a0) # load array element from memory
addi $t2, $t2, 1 # increment element
sw $t2, 0($a0) # write back to memory
addi $a0, $a0, 4 # increment array pointer by 4 (word = 4 bytes)
addi $t1, $t1, 1 # increment loop counter by 1
blt $t1, $t0, loop # loop, if necessary
Is it not working because I already have numbers in $t0? I ask the user what number of list they want (either 3 or 4 and that is stored in $t0) but then I ask them to enter their list of numbers (which I need to put into an array). If I then put this array also in $t0. Would it overwrite the numbers the user entered first when prompeted to say what list length they wanted?

Resources