MIPS Assembler trouble - Arrays - arrays

I have an assembly code containing an array, and I simply cannot understand what actually the result in the $s2 register shows. If someone could help and explain or simplify it for me that would be great.
Here's the code:
.data arr: .word 3 2 -6 1 4 10 530 115 2231 1422
arrSize: .word 10
.text
.global main
main:
la $s0, arr
la $t0, arrSize
lw $s1, 0($t0)
add $s2, $zero, $zero
loop:
lw $t1, 0($s0)
andi $t2, $t1, 1
bne $t2, $zero, skip
addi $s2, $s2, 1
skip:
addi $s0, $s0, 4
addi $s1, $s1, -1
bne $s1, $zero, loop
end:
add $v0, $zero, $s2

I've added some pseudo-code comments to the code:
.data arr: .word 3 2 -6 1 4 10 530 115 2231 1422
arrSize: .word 10
.text
.global main
main:
la $s0, arr ;; s0 = arr // init s0 = pointer to start of arr
la $t0, arrSize ;; t0 = &arr_size // get no of elements in arr
lw $s1, 0($t0) ;; s1 = arr_size = 10
add $s2, $zero, $zero ;; s2 = 0 // init count of even elements = 0
loop: ;; do { // for all elements in arr do
lw $t1, 0($s0) ;; t1 = *s0 // get element from arr
andi $t2, $t1, 1 ;; t2 = t1 & 1 // test element for odd/even-ness
bne $t2, $zero, skip ;; if (t2 != 0) // if not odd (i.e. even) then
addi $s2, $s2, 1 ;; s2++ // increment count in s2
skip:
addi $s0, $s0, 4 ;; s0++ // increment pointer to next element in arr
addi $s1, $s1, -1 ;; s1-- // decrement count of elements to process
bne $s1, $zero, loop ;; } while (s1 != 0) // end of do loop
end:
add $v0, $zero, $s2 ;; v0 = s2 // return result in v0
It seems that this just iterates through the elements of arr, testing each element to see if it is even, and incrementing a count of even elements found. The final result (in v0 and s2) will be 6, since there are 6 even elements in the array.

Related

MIPS 1D Integer Array, inserting at index

I'm new to MIPS and having some trouble with my program.
Right now my code works at inserting an integer value into the array at a specified index. But currently, when the integer is inserted it replaces the value that was previously there. How do I instead shift all elements after said index so the array's length increases by 1 and no values are lost?
Note that I'm using a special integer -22 to indicate the end of my array.
Any help would be greatly appreciated! Thank you!
Below is my code:
.data
beginarray: .word 1, 2, 3, 4, -22
array: .space 4000
str_command: .asciiz
str1: .asciiz "\nEnter an Integer: "
str2: .asciiz "\nAt what index: "
.text
.globl main
main:
# get length
la $a0, beginarray
jal length
addi $s0, $v0, 0 # $s0 = returned length
# copy beginarray into array
la $a0, beginarray
la $a1, array
jal copyarray
jal insert
# print array
la $a0, array
jal printarray
li $v0,10
syscall
# takes pointer to array as input
length: addi $t0, $zero, -22 # $t0 = -22
addi $v0, $zero, 0 # $v0 = 0 (length)
add $t1, $a0, $zero # $t1 = pointer to first int
calclength: lw $t2, 0($t1) # $t1 = value of current int
beq $t2, $t0, returnlength # if $t1 = -22
addi $v0, $v0, 1 # increment length
addi $t1, $t1, 4 # move pointer to next int
j calclength # loop
returnlength: jr $ra
# takes two pointers as input (pointer to first array and pointer to second array)
# copies contents of first array into second array
copyarray: addi $t0, $a0, 0 # $t0 = pointer to array1
# addi $t1, $a1, 0 # $t1 = pointer to array2
addi $t4, $zero, -22 # $t4 = -22
calccopy: lw $t2, 0($t0) # $t2 = value of array1
#lw $t3, 0($t1) # $t3 = value of array2
sw $t2, 0($a1) # store int in array
beq $t2, $t4, returncopy # if $t2 = -22
addi $t0, $t0, 4 # move a1 pointer to next int
addi $a1, $a1, 4 # move a2 pointer to next int
j calccopy
returncopy: jr $ra
# print array
printarray: add $t1, $a0, $zero # $t1 = pointer to first int
addi $t0, $zero, 0 # set counter to zero
printloop: beq $t0, $s0, done
# load word from addrs and goes to the next addrs
lw $t2, 0($t1)
addi $t1, $t1, 4
# syscall to print value
li $v0, 1
move $a0, $t2
syscall
# syscall for printing space
li $a0, 32
li $v0, 11
syscall
#increment counter
addi $t0, $t0, 1
j printloop
done: jr $ra
insert:
li $v0, 4 # system call code for print_str
la $a0, str1
syscall
li $v0 5 # system call code for read_int
syscall
move $t3, $v0 # $t3 = integer entered
li $v0, 4 # system call code for print_str
la $a0, str2
syscall
li $v0 5 # system call code for read_int
syscall
move $t1, $v0 # $t1 = index entered
li $t0, 0 # $t0 = counter
la $t2, array # $t2 = base address of array
for: bge $t0, $t1, end_for
add $t2, $t2, 4 # get address of next array element
add $t0, $t0, 1 # increment loop induction variable
b for
end_for:sw $t3, ($t2)
jr $ra

(C to MIPS)I dont know why I cant printf all of the output like C code do

I had tried my best to turn the C code to mips code.
I cant find why I cant printf all of the output like C code do.
I think problem is about $ra, but I cant fix it.
I need help.
thanks for the nice guy like you.
I need output like this
1 2 3
1 2 4
1 2 5
1 3 4
1 3 5
1 4 5 *
2 3 4
2 3 5
2 4 5
3 4 5
but MIPS code will exit at *.
C
#include <stdio.h>
static int cl[3];
static int n=5;
static int k=3;
void dfs(int cur, int s ){
int i;
if (cur==k) {
for (i=0; i<k; i++){
printf("%d ",cl[i]);
}
printf("\n");
}
else{
int p=n-k+cur+1;
for (i=s; i<=p; i++){
cl[cur]=i;
dfs(cur+1,i+1);
}
}
}
int main(){
dfs(0,1);
}
ASM
.data
cl: .word 0,0,0 #cl[3]
n: .word 5 #n=5
k: .word 3 #k=3
space: .asciiz " "
enter: .asciiz "\n"
.text
main: li $s0, 0 #cur = 0
li $s1, 1 #s = 1
jal dfs
j exit
dfs: addi $sp, $sp, -12
sw $ra, 0($sp)
li $t3, 0 #i=0
lw $t0, k #k=3
if: bne $s0, $t0, else #if(cur==k)
la $t0, cl #get address of cl[i]
loop:
lw $a0, ($t0) #printf
li $v0, 1
syscall
la $a0, space # load address of spacer for syscall
li $v0, 4 # specify Print String service
syscall
addi $t3, $t3, 1 # i++
addi $t0, $t0, 4 # cl[i++]
lw $t1, k
blt $t3, $t1,loop #i<k
la $a0, enter # load address of enter for syscall
li $v0, 4 # specify Print String service
syscall
j done
else: lw $s2, n # n
lw $t0, k # k
sub $s2, $s2, $t0 #n-=k
add $s2, $s2, $s0 #+=cur
addi $s2, $s2, 1 # +=1
move $t0, $s1 #i=s
loop2: la $t1, cl #load address from cl
sll $t2, $s0, 2 #t2=cur*4
add $t1, $t1, $t2 #t1=*cl+cur*4
sw $t0, ($t1) #cl[cur]=i
addi $s0, $s0, 1 #cur++
addi $s1, $t0, 1 #s=i+1
sw $t0, 4($sp)
sw $s2, 8($sp)
jal dfs
addi $s0, $s0, -1
addi $s1, $s1, -1
addi $t0, $t0, 1
ble $t0, $s2, loop2 #i<=s2
done:
addi $sp, $sp, 12
lw $ra, 0($sp)
lw $t0, 4($sp)
lw $s2, 8($sp)
jr $ra #return void
exit:
You are incrementing the stack pointer — popping it — too early in the function epilogue. To reverse the prologue we change the sign of the immediate in adding to the stack pointer and move it to the end and otherwise change sw's to lw's.
done:
addi $sp, $sp, 12 <--- this is too early
lw $ra, 0($sp)
lw $t0, 4($sp)
lw $s2, 8($sp)
<--- it belongs here
jr $ra #return void

Array indexing in a for-loop in MIPS assembly

I need to implement this code in the MARS emulator:
int x[10] = { /* initial values */ } ;
int i;
for(i=0; i<10; i++){
print i;
}
for (i=0; i<10; i++){
x[i] = 2*i+1;
print x[i];
}
Heres what I have:
.data
i: .word 0
x: .word 1,2,3,4,5,6,7,8,9,10
.align 2
.text
.globl main
main:
lw $t0, i
lw $t1, x
li $t4, 4
jal L0
li $t0, 0
jal L1
li $v0, 10 # terminate
syscall
L0:
li $v0, 1
la $a0, ($t0)
syscall
addi $t0, $t0, 1
bge $t0,10, RETURN #goto L1 if NOT n<0
b L0
L1:
li $v0, 1
la $a0, ($t1)
syscall
mul $t2, $t0, $t4
lw $t1, x + ($t2) #########this line#########
addi $t0, $t0, 1
bge $t0,10, RETURN
b L1
RETURN:
jr $ra
I commented next to the line that I believe to be the source of my problem. That is essentially the line that is referencing x[i]. I multiplied i by 4 and added that value to x, in attempt to reference the appropriate word in the array. I don't know how to properly implement this concept.
Thanks for the help.
You need to do something like this:
L1:
la $a1,x # $a1 = &x
L2: # do {
addu $a0,$t0,$t0 # $a0 = i*2
addiu $a0,$a0,1 # $a0 = i*2 + 1
sw $a0,($a1) # x[i] = i*2 + 1
addiu $a1,$a1,4 # a1 = &x[i+1]
li $v0,1 # print_int
syscall # print_int(i*2 + 1)
addiu $t0,$t0,1 # i++
bne $t0,10,L2 # } while (i != 10)
jr $ra
And stuff like la $a0, ($t0) looks really weird. Please use the much clearer move $a0, $t0 instead.

Finding MAX values of two Arrays using MIPS

I'm supposed to find the max values in two different arrays. Here is an example in C
int largest( int* array, int arrayLength) {
int largest = array[0];
int index = 1;
while( index < arrayLength) {
if( array[index] > largest {
largest = array[index];
}
index++;
}
return( largest);
}
I'm supposed to do the same by implementing a function in MIPS assembly and test the function in main on two different arrays. I've included my code below, but I'm new and not sure if it even works as I don't have access to QTSPIM on this computer. If you have any suggestions, fixes, or any help at all it is much appreciated. Thanks
.data
arrayOne: .word -10, 9, 5, 60, 12, -33, 10
arrayTwo: .word 20, 44, -9, 8, 72, 25, -36
.text
main:
la $s0, arrayOne #load the array
move $a0, $s0 #move array to register the function can use
jal Largest #call the function
la $s0, arrayTwo #load the other array
move $a0, $s0
jal Largest
li $v0, 10 #exit program
syscall
Largest:
addi $sp, $sp, -4 #save return address
sw $ra, 0($sp)
move $t0, $a0 #load array into temp register
lw $v0, 0($t0) #set maximum to array[0]
li $t2, 1 #set index = 1
Loop:
slt $t3, $t2, $t1 #???
beq $t3, $zero, ExitLoop
sll $t3, $t2, 2 #find offest of next element
add $t3, $t0, $t3 #store address in $t3
lw $t4, 0($t3) #load next value into $t4
sgt $t5, $t4, $v0 #compare previous max with new value
beq $t5, $zero, notGreater #jump if not greater
move $v0, $t4 #if greater, set return value to new max
notGreater:
addi $t2, $t2, 1 #increment index
j Loop
ExitLoop:
lw $ra, 0($sp) #unload the stack
addi $sp, $sp, 4
jr $ra #return to main

How do I access each word in Assembly?

Given:
.data
arr: .word 2,5,1,3,4
len: .word 5
sum: .word 0
How would I access each word in "arr" such as 2, 3 and 4?
Eventually, what I would like to do is find a sum of all of the values in "arr", but I'm having difficulty iterating through "arr".
Thank you for your time!
Additional Info:
I'm using eduMIPS64
First load the address of the array into a register, then you can access the items with a constant offset. (Your assembler might support constructs such as lw $t0, arr+12 as convenience shorthand for this. See your manual.) For iteration, either increment the address register, or add another register containing the offset. Be sure to account for item sizes. Folling example is for 32 bit mips, adjust as necessary for 64 bit:
.data
arr: .word 2,5,1,3,4
len: .word 5
sum: .word 0
.text
.globl main
main:
la $t0, arr
lw $t1, 12($t0) # load arr[3] using byte offset
li $t1, 3 # index
sll $t1, $t1, 2 # multiply by item size
addu $t1, $t1, $t0 # add base address
lw $t1, ($t1) # load arr[3]
# iteration type 1
# for(i=len, ptr=arr; i != 0; i -= 1, ptr += 1)
# ... use *ptr ...
la $t0, arr
lw $t1, len # load length
loop1:
lw $t2, ($t0) # load item
# process item here
addi $t0, $t0, 4 # add item size to pointer
addi $t1, $t1, -1 # decrement counter
bne $t1, $0, loop1 # if counter != 0, repeat
# iteration type 2
# for(i=0, i != len; i += 1)
# ... use arr[i] ...
la $t0, arr
lw $t1, len # load length
li $t2, 0 # index
loop2:
sll $t3, $t2, 2 # multiply by item size
addu $t3, $t3, $t0 # add base address
lw $t3, ($t3) # load item
# process item here
addi $t2, $t2, 1 # increment index
bne $t2, $t1, loop2 # if index != len, repeat
(note these sample loops do not handle zero length array, add check if necessary)

Resources