How to compare elements of array in mips assembly? - arrays

I know how to iterate through an array in mips. However I can't seem to figure out how to compare two elements in the same array? Can anybody point me in the right direction here?
if(array[i] > array[i - 3])
I believe it would be a branch if greater than comparing two registers but how would I get the data into the two registers? Thanks!

You cant just iterate an array... You have to add a multiple of 4 (=> index * 4) to the memory address of the array. Then you can load the value at this modified memory addres and compair it to a diffrent moddified addres...
.data
array: .word 1,2,3
#Index's you want to compair
i1: .word 0
i2: .word 1
.text
MAIN:
lw $a0 i1
lw $a1 i2
li $t5 4 #load multiplier
mul $a0 $a0 $t5
mul $a1 $a1 $t5
la $t0 array
la $t1 array
add $t0 $t0 $a0
add $t1 $t1 $a1
lw $t0 ($t0)
lw $t1 ($t1)
beq $t0 $t1 TRUE

Related

MIPS - Help initializing array

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

Getting address out of range in MIPS assembly?

I am trying to reverse an array using only one array. When the index of high is less than or equal to low, I am supposed to keep switching the content of high and low. However, I am getting address out of range and am having trouble finding resources on how to fix it.
I'm supposed to only use one array while reversing the array. What am I doing wrong? Starred is where I am getting the error.
reverseArray:
li $t6, 0 #head = first index of array
la $s0, array
li $t5, 4
mult $s0, $t5
mflo $t7 #tail = last index of array
swap:
lw $t6, 0($s0)
**lw $t4, 0($t7)**
sw $t4, 0($s0)
sw $t6, 0($t7)
add $t7, $t7, -4
add $s0, $s0, 4
sle $t1,$t7,$s0
beq $t1,$0,swap
I assume what you want in $t7 is the address of the last element of the array. Multiplying the base address by 4 is not going to give you that address. What you need to calculate is array + (length-1)*4.
So you need to know the length of the array. The code you've posted doesn't indicate that you know the length of the array, but let's say that you've got the length in register $t6. The calulation you need to perform then is:
addiu $t7,$t6,-1 # $t7 = length-1
sll $t7,$t7,2 # $t7 = (length-1)<<2 == (length-1)*4
addu $t7,$t7,$s0 # $t7 = (length-1)*4 + array
swap:
lw $t6, ($s0)
lw $t4, ($t7)
... etc ...

Assembly Language Array

Any help to find the answer would be greatly appreciated.
.data
array: .word 1,2,3,4,5,6,7,8,9,10
.text
.globl main
main:
la $t0, array
li $t1, 4
mult $t1, $t1
mflo $t1
add $t0, $t0, $t1
sw $t1, 20($t0)
What are the values of the array after executing the instructions? Im confused on this part. Do I just add 20 to each value in the array?
Some hints
.data
array: .word 1,2,3,4,5,6,7,8,9,10 # 10 32 bits values #array
.text
.globl main
main:
la $t0, array # Load address of array into $t0
li $t1, 4 # Load constant 4 into $t1
mult $t1, $t1 # Multiply $t1 x $t1
mflo $t1 # Put result (lower word) into $t1 ( 16 )
add $t0, $t0, $t1 # $t0 = $t0 + $t1 ( array + 16 )
sw $t1, 20($t0) # Store $t1 at address ( $t0 + 20 )
Provided that a word is 4 bytes, i.e. storing at (array + 4) overwrites the 2 in array (2nd value), you should be able to figure out the answer to your question.

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