MIPS - Help initializing array - arrays

I am trying to initialize memory array to values 1, 2, 3.. 10. Though I am having a bit of trouble. Here is my work so far:
.data
myarray: .space 10
.text
la $t3, myarray # Load the address of myarray
addi $t2, $zero, 1 # Initialize the first data value in register.
addi $t0, $zero, 10 # Initialize loop counter $t0 to the value 10
top:
sw $t2, 0($t3) # Copy data from register $t2 to address [ 0 +
# contents of register $t3]
addi $t0, $t0, -1 # Decrement the loop counter
bne $t0, $zero, top
Any help would be much appreciated.

There are several problems with your code.
If you use sw (store word), you assume a "word" array. Its size should be 4*10. If you wand a byte array, use sb .
You do not increment the array pointer in $t3
Same problem for the array values in $t2
.data
myarray: .space 10
.text
la $t3, myarray # Load the address of myarray
addi $t2, $zero, 1 # Initialize the first data value in register.
addi $t0, $zero, 10 # Initialize loop counter $t0 to the value 10
top:
sb $t2, 0($t3) # Copy data from register $t2 to address [ 0 +
# contents of register $t3]
addi $t0, $t0,-1 # Decrement the loop counter
addi $t3, $t3, 1 # next array element
addi $t2, $t2, 1 # value of next array element
bne $t0, $zero, top
As suggested by #PeterCordes, this can be optimized by merging the loop counter and the array values register to suppressed one instruction in the loop. The corresponding loop in C will be
for(i=1, ptr=array; i!=11; ptr++,i++) *ptr=i;
And the corresponding code
.data
myarray: .space 10
.text
la $t3, myarray # Load the address of myarray
addi $t2, $zero, 1 # Initialize the first data value in register.
addi $t0, $zero, 11 # Break the loop when array value reaches 11
top:
sb $t2, 0($t3) # Copy data from register $t2 to address [ 0 +
# contents of register $t3]
addi $t2, $t2, 1 # Increment array value/loop counter
addi $t3, $t3, 1 # next array element
bne $t0, $t2, top

Related

I need 10 integer of array and display the sum and here is my code I dont know where the error is

Write a MIPS program that defines a one-dimensional array of 10 integers in the static area of the data segment, asks the user to input all 10 array elements, computes, and displays their sum.
.data
arr: .word 1,2,3,4,5,6,7,8,9,10
msg: .asciiz "Result: "
.text
.globl main
main:
addi $t0, $zero, 0 # clear i
addi $t1, $zero, 0 # clear sum
ori $t2, $zero, 10 # Initializing t2 to its constant value 10
la $t3, arr # load address of array into t4
loop:
slt $t4, $t0, $t2 # compare, $t4 = i < sum ? 1 : 0
beq $t4, $zero, end # if i is not < 10, exit the loop
lw $t4, 0($t3) # load current array element into t4
add $t1, $t1, $t4 # add it to sum
add $t0, $t0, 1 # increment i
add $t3, $t3, 4 # increment current array element pointer
j loop
end:
addi $v0, $zero, 4 # Now we print out result: string
la $a0, msg
syscall
addi $v0, $zero, 1 # followed by the actual sum (which is in t1)
add $a0, $t1, $zero
syscall
jr $ra
.end main

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

Function to find the MAX and its position on an array

I have to find the max element and its position on an array(the position starts with 1)( if the array doesn't contain any elements I have to return position=0 and max=smallest negative number). I think that my code is ok (apart from setting the max to the lowest number possible, that I have doubt about) but I have no idea what I need to start my code with, like save the last thing stored in the registers. Also I can't compile it (probably because of the pseudo-instructions).
I have tried writing my program in c and then compiling to MIPS but it still wouldn't work.
MaxAndArg:
li $v0, -2,147,483,648 # $v0(MAX) is the smallest negative number
li $v1, 0 # $v1(POSITION) starts from zero
li $t3, 0 # $t3(i in a normal language) will be used to loop
li $t4, 0 # $t4 will be used to show the position in the array
L2:
beq $t3, $a1, EXIT # if (i = array size) goto EXIT
sll $t4, $t4, 2 # $t4 = $t4 * 4
add $a0, $t4, $a0 # $a0 = $a0 + $t4 (next element in the array)
blt $v0, a0, L1 # if (max < a[j]) goto L1
addi $t3, $t3, 1 # i++
addi $t4, $t4, 1 # array_position++
j L2
L1:
addi $v0, $a0, 0 # $v0 = $a0
addi $v1, $t3, 1 # $v1 = i + 1 (probably works)
addi $t3, $t3, 1 # i++
addi $t4, $t4, 1 # array_position++
j L2
EXIT:
jr $ra #return

Array sorting in MIPS

So I am working on an assignment to sort an array in MIPS. The data to sort is given in a separate .asm file as follows:
.data
.word 3
.word 40
.word 30
.word 70
.text
I decided to use bubble sort. I am fairly certain that my algorithm is sound, and it appears to sort the data correctly. The fun thing about this project is that the values we sort will be played as MIDI notes as a means of testing the program (so, naturally, the notes should play in ascending order). This is working pretty well when I test my code, however, I'm hearing a few strange beats at the end of the MIDI notes. I stepped through my code and discovered that, at the end, $t1 (the value I use to compare to my loop iterator for completeness) holds a value of 7, when I expected it to hold a value of three. I assign $t1 as 0($t2), $t2 is 0x10010000 which I assume is still the base address of my array. The base address of the array should hold 3, shouldn't it?
I'm a little confused about why $t1 is 7 at all... any advice? I have included all of my code below.
#ec2.asm
.include "ec2_data.asm" #must be in the same directory as ec2.asm
#ec2_data.asm: puts some values in the "data segment"
#the first value is the number of values to sort (n)
#the remaining n word values are the data to sort
#the values will be stored in memory as word values starting
# address 0x10010000
j main
#$t2 is hasChanged
#$t3 is itemCount
#$t4 is i, our iterator in the for loop
#$t5 is array[i] (temp)
#$t6 is array[i+1] (temp)
while_label:
beq $t2, $zero, done_sorting #checks to see if the previous iteration switched any values. If not, we are done.
addi $t2, $zero, 0 #initialize hasChanged to 0
addi $t3, $t3, -1 #decrement itemCount by -1
addi, $t0, $t0, 4 #add 4 to the array offset
addi, $t4, $zero, 0 #set our for loop iterator to 0
for_label:
lw $t5, 0($t0) #set a temp value equal to array[i]
lw $t6, 4($t0) #set a temp value equal to array[i+1]
beq $t4, $t3, while_label #for loop: if i = itemcount, we have incremented all the way through our for loop
bge $t6, $t5, skip_swap #if array[i+1] is greater than or equal to array[i], we don't need to swap these values
#swap
sw $t6, 0($t0) #set array[i] equal to array[i+1]
sw $t5, 4($t0) #set array[i+1] equal to the temp value
addi $t2, $t2, 1 #set hasChanged to 1 to indicate that a swap has been made
skip_swap:
addi, $t4, $t4, 1 #increment i by 1 (for loop iterator)
j for_label #keep the for loop going!
main:
#read values
addi $t0, $zero, 0x10010000 #sets $t0 to be the base address of the array
addi $t2, $zero, 1
lw $t3, 0($t0) #stores n in $t3
j while_label
done_sorting:
# adapted from MIDI example
#duration 25 ms
#instrument (whichever)
#volume 64
addi $v0, $zero, 33 # midi out synchronous
addi $t2, $zero, 0x10010000 # address of original array (which should by now be sorted)
addi $a1, $zero, 250 # duration (ms)
addi $a2, $zero, 1 # instrument
addi $a3, $zero, 64 # volume
addi $t0, $zero, 0 # counter
lw $t1, 0($t2) # end of the loop (should be n)
addi $t1, $t1, 4 # adds four to the array offset in $t1
lw $a0, 0($t2) # stores the first sorted value ( 4($t1) ) in $a0
midi_loop:
beq $t0, $t1, done
addi $t2, $t2, 4
lw $a0, 0($t2)
syscall
addi $t0, $t0, 1
j midi_loop
done:
#addi $v0, $zero, 10 # syscall for exit
#syscall # clean exit
Your sorting algorithm is quite broken. You haven't noticed that because it happens to get the right answer with your test data. It will produce the wrong answer with other test data (e.g. I believe your algorithm will sort 70, 40, 30 to 40, 30, 70).
But your question was about why $t1 ends up with value 7. The answer is simple. You wrote this:
addi $t2, $zero, 0x10010000 # address of original array (which should by now be sorted)
addi $a1, $zero, 250 # duration (ms)
addi $a2, $zero, 1 # instrument
addi $a3, $zero, 64 # volume
addi $t0, $zero, 0 # counter
lw $t1, 0($t2) # end of the loop (should be n)
addi $t1, $t1, 4 # adds four to the array offset in $t1
We can see that you set $t2 to 0 + 0x10010000 = 0x10010000. Then you load the word at 0($t2) (= 0x10010000) into $t1. The word at 0x10010000 is 3, so at that point $t1 is 3. Then you add 4 to $t1, storing the result in $t1. At that point $t1 is 7. You never modify $t1 after that.
SO I really shouldn't have asked this question without giving my code another once-over. The errors were extremely simple. This appears to work.
#ec2.asm
.include "ec2_data.asm" #must be in the same directory as ec2.asm
#ec2_data.asm: puts some values in the "data segment"
#the first value is the number of values to sort (n)
#the remaining n word values are the data to sort
#the values will be stored in memory as word values starting
# address 0x10010000
j main
#$t2 is hasChanged
#$t3 is itemCount
#$t4 is i, our iterator in the for loop
#$t5 is array[i] (temp)
#$t6 is array[i+1] (temp)
while_label:
beq $t2, $zero, done_sorting #checks to see if the previous iteration switched any values. If not, we are done.
addi $t2, $zero, 0 #initialize hasChanged to 0
addi $t3, $t3, -1 #decrement itemCount by -1 WHY
addi, $t0, $zero, 0x10010000 #add 4 to the array offset
addi, $t4, $zero, 0 #set our for loop iterator to 0
for_label:
addi, $t0, $t0, 4
lw $t5, 0($t0) #set a temp value equal to array[i]
lw $t6, 4($t0) #set a temp value equal to array[i+1]
beq $t4, $t3, while_label #for loop: if i = itemcount, we have incremented all the way through our for loop
bge $t6, $t5, skip_swap #if array[i+1] is greater than or equal to array[i], we don't need to swap these values
#swap
sw $t6, 0($t0) #set array[i] equal to array[i+1]
sw $t5, 4($t0) #set array[i+1] equal to the temp value
addi $t2, $t2, 1 #set hasChanged to 1 to indicate that a swap has been made
skip_swap:
addi, $t4, $t4, 1 #increment i by 1 (for loop iterator)
j for_label #keep the for loop going!
main:
#read values
addi $t0, $zero, 0x10010000 #sets $t0 to be the base address of the array
addi $t2, $zero, 1
lw $t3, 0($t0) #stores n in $t3
j while_label
done_sorting:
# adapted from MIDI example
#duration 25 ms
#instrument (whichever)
#volume 64
addi $v0, $zero, 33 # midi out synchronous
addi $t2, $zero, 0x10010000 # address of original array (which should by now be sorted)
addi $a1, $zero, 250 # duration (ms)
addi $a2, $zero, 1 # instrument
addi $a3, $zero, 64 # volume
addi $t0, $zero, 0 # counter
lw $t1, 0($t2) # end of the loop (should be n)
lw $a0, 0($t2) # stores the first sorted value ( 4($t1) ) in $a0
midi_loop:
beq $t0, $t1, done
addi $t2, $t2, 4
lw $a0, 0($t2)
syscall
addi $t0, $t0, 1
j midi_loop
done:

MIPS code broken

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

Resources