What is this MIPS array + loop doing? - arrays

New to MIPS and can understand exactly what is going on with the code, but I do not understand the answer/solution provided. Any help would be greatly appreciated.
Please read the following code and write down the content in array A after funct returns.
.data
A: .word 21,3,2,9,100,22,6,15,33,90
.text
.globl main
main:
la $a0, A
li $a1, 17
li $a2, 10
jal funct
li $v0, 10 # exit
syscall
funct:
li $t0, 0
li $v1, 1000000
funct_L0:
sll $t1, $t0, 2
add $t1, $t1, $a0
lw $t1, 0($t1)
sub $t2, $t1, $a1
bgt $t2, $0, funct_L1
sub $t2, $0, $t2
funct_L1:
bgt $t2, $v1, funct_L2
ori $v0, $t0, 0
ori $v1, $t2, 0
funct_L2:
addi $t0, $t0, 1
blt $t0, $a2, funct_L0
jr $ra
SOLUTION: Finds the smallest difference

It finds the element from the array which is nearest to the number passed in in $a1. In other words, it finds the element x for which the difference abs(x - $a1) is smallest. It returns the index in $v0 and the difference in $v1.

Related

How can I in MIPS(MARS) assembly language check if the result of a multiplication between matrixes is correct?

The fact is that I had to do a program in assembler MIPS consisting of given a 2x2 matrix and a vector of two elements multiply each other. The fact is that I think the code works but I do not know if I'm saving the results well or if it works badly, and I do not know how to prove it either. If someone could look at the code and tell me how it would be very grateful. Thank you very much in advance. I attach the code:
.text
.globl begin
begin:
la $t0, matrix
la $t1, matrix_out
la $t2, array
li $t3, 0
li $t4, 0
loop:
lw $t5, ($t0)
lw $t6, ($t2)
mul $t7, $t6,$t5
add $t0, $t0, 4
add $t2, $t2, 4
add $t8, $t8, $t7
sw $t8, ($t1)
add $t1, $t1, 4
add $t3, $t3, 1
bne $t3, 2, loop
add $t8, $0, $0
add $t2,$t2,-8
add $t3, $zero, $zero
add $t4, $t4, 1
bne $t4, 2, loop
li $v0, 10
syscall
.data
matrix: .word 1,2,3,4
matrix_out: .space 8
array: .word 5,6

MIPS array assign infinity loop

I am trying to fix this problem for hours!!!!!
When I enter 8 integers for the array and then enter 0 to finish reading, when the loop section starts it goes to infinity loop!!
I can't find where's the problem, when I remove the addiu from the $s2 array it works fine but doesn't store the $t1 on the array!
Please HELP!!
.data
array: .space 32
percentage_Array: .space 32
newLine: .asciiz "\n"
.text
main:
la $s1, array
la $s2, percentage_Array
read_numbers:
li $v0, 5
syscall
sw $v0, 0($s1)
addiu $s1, $s1, 4
beqz $v0, continue
j read_numbers
continue:
la $s1, array
loop:
lw $t0, 0($s1)
addiu $s1, $s1, 4
beqz $t0, exit
move $a1, $t0
jal calculate_Ones_and_Bits
move $s6, $v0
move $s7, $v1
#put the total number of ones
add $s0, $s0, $s7
#calculate the percentage
addi $t5, $zero, 100
mult $s7, $t5
mflo $t1
div $t1, $s6
mflo $t1
#-----I THINK HERE IS MY PROBLEM------
#Put the percentages on percentage_Array array
sw $a1, 0($s2)
addiu $s2, $s2, 4
#Check which percentages are greater than 50 and print the numbers
which fulfill the condition
slti $t2, $t1, 50
beq $t2, 1, loop
li $v0, 1
move $a0, $t0
syscall
#lines 66,67,68 are extra just for printing in new line more clearly
li $v0, 4
la $a0, newLine
syscall
j loop
exit:
#lines 73,74,75 are also extra just to print the value of s0, it is
printed here so it
#will be executed after the loop has finished
li $v0, 1
move $a0, $s0
syscall
#tell the OS to exit/finish
li $v0, 10
syscall

Input and output array elements in MIPS

Here is my MIPS code. It is supposed to input 10 integers in array and then output them. I can input integers but after entering 10 integers it doesn't output any array element.
.data
arr: .space 40
.text
.globl main
main:
la $t0, arr #copying array address into $t0
iterateForInput:
blt $t4, 9, forLoopInput
sub $t0, $t0, 40
iterateForOutput:
blt $t4, 9, forLoopOutput
li $v0, 10
syscall
forLoopInput:
li $v0, 5 #input integer
syscall
move $t1, $v0 #moving integer into $t1
sw $t1, ($t0) #storing integer at array address
add $t0, $t0, 4
add $t4, $t4, 1
b iterateForInput
forLoopOutput:
lw $t6, ($t0)
li $v0, 1
move $a0, $t6
syscall
add $t0, $t0, 4
add $t4, $t4, 1
b iterateForOutput

MIPS - Error when printing data into array

So im attempting to put numbers 1-200 in an array. The array is at the bottom of the code. I keep getting errors when i try to print this, can anyone spot the error with me putting in the numbers? The numbers in the array are supposed to go from 1-200, so $t3 increments each time. Any advice would be greatly appreciated.
main:
.text
lw $t0, numbers_size # loads the size of the array into the loop
la $t1, numbers # $t1 gets the number array
li $t2, 0 # loop control variable
li $t3, 1 # value stored inside numbers
li $v0, 4
la $a0, test_2 # print before loop
syscall
number_for:
bge $t2, $t0, end_for
sw $t3, ($t1)
add $t1, $t1, 4
add $t2, $t2, 1
add $t3, $t3, 1
j number_for
end_for:
lw $t0, numbers_size # loads the size of the array into the loop
la $t1, numbers # $t1 gets the number array
li $t2, 0 # loop control variable
j print_numbers
.data
test: .asciiz "Printing numbers:"
test_2: .asciiz "Before loop:"
numbers:
.word 0:200
numbers_size:
.word 200
This may help you:
.text
main:
lw $t0, numbers_size # loads the size of the array into the loop
la $t1, numbers # $t1 gets the number array
li $t2, 0 # loop control variable
li $t3, 1 # value stored inside numbers
li $v0, 4
la $a0, test_2 # print before loop
syscall
j number_for
li $v0, 10
syscall
number_for:
bge $t2, $t0 end_for
sw $t3, ($t1)
addi $t1, $t1, 4
addi $t2, $t2, 1
addi $t3, $t3, 1
b number_for
end_for:
lw $t0, numbers_size # loads the size of the array into the loop
li $t1, 0
li $t2, 0 # loop control variable
buc:
bge $t2, $t0 end
lw $a0, numbers($t1) # Printing integer from array
li $v0,1
syscall
la $a0, space #load a space: " "
li $v0, 4 #print string
syscall
addi $t1, $t1, 4
addi $t2, $t2, 1
b buc
end:
jr $ra
.data
test: .asciiz "Printing numbers:"
test_2: .asciiz "Before loop:\n"
space: .asciiz " "
numbers_size:
.word 200
numbers:
.word 0:200

Adding to an array in a subroutine(MIPS/Assembly)

I'm trying to add values to an array inside a subroutine. I can get the first valid value(positive number and divisible by 3) into the array, but the next valid entries don't work. I can enter a valid number and then enter an invalid number and the program works fine, but two valid numbers makes Spim stop working. I've spent a few hours trying to figure it out but no luck. The jumping from one subroutine is a requirement for the assignment, I have a working program but lacks all the unnecessary(in my opinion) subroutines.
.data
array1: .word 80
EnterARVal: .asciiz "Please enter a number:\t"
space: .asciiz " "
errormessage: .asciiz "*****Error: "
notpos: .asciiz " is not a positive number.\n"
notdiv3: .asciiz " is not divisible by 3.\n"
numadded: .asciiz " added to array.\n"
EnterElem: .asciiz "Enter number "
ARReverse: .asciiz "The contents of the array in reverse orders is:\n"
InvalidAR: .asciiz "Invalid number of array elements, please try again.\n"
.text
main:
la $s0, array1 #array1 pointer
li $t0, 1
begin:
jal readNum #go to readNum subroutine
add $a0, $0, $v0 #stores readNum input to $a0
jal verifySize #jumps to verifySize subroutine
add $t1, $v1, $0 #stores 0 or 1 value to $t1
beq $t1, $0, begin #starts over if t1 is 0 or false
beq $t1, $t0, numok #goes to numok if t1 is 1 or true
numok: add $a0, $0, $a0
add $a1, $0, $s0
jal createArray
j exit
readNum: li $v0, 4
la $a0, EnterARVal
syscall
li $v0, 5
syscall
add $v0, $v0, $0
j $ra
verifySize: add $t1, $0, $a0
li $t2, 20
li $t3, 1
li $t4, 0
li $t5, 1
slt $t6, $t1, $t3
beq $t6, $t3, toolow
sgt $t7, $t1, $t2
beq $t7, $t3, toohigh
beq $t7, $t4, oknum
oknum:
add $v1, $t5, $0
j $ra
toolow:
li $v0, 4
la $a0, InvalidAR
syscall
add $v1, $t4, $0
j $ra
toohigh:
li $v0, 4
la $a0, InvalidAR
syscall
add $v1, $t4, $0
j $ra
createArray: add $s1, $a0, $0
add $s0, $a1, $0
li $t0, 0 #counter
li $t2, 1
add $a0, $s1, $0
li $v0, 1
syscall
makingarray: beq $t0, $s1, arraydone
jal readNum #go to readNum subroutine
add $a0, $v0, $0 #stores number from readNum to $a0
jal checkNumPositive #jump to checkNumPositive subroutine
add $t1, $v0, $0
beq $t1, $0, positivenum #if number is positive go to positivenum
beq $t1, $t2, notpositive
positivenum:
jal divisibleBy3
add $t4, $v0, $0
beq $t4, $0, notdivisibleby3
sw $a0, 0($s0)
li $v0, 1
syscall
li $v0, 4
la $a0, numadded
syscall
add $s0, $s0, 4
add $t0, $t0, 1
j makingarray
arraydone:
add $v0, $s0, $0
j $ra
notpositive:
li $v0, 4
la $a0, notpos
syscall
j makingarray
notdivisibleby3:
li $v0, 4
la $a0, notdiv3
syscall
j makingarray
#reverseArray:
divisibleBy3: add $t0, $a0, $0
li $t1, 3
div $t0, $t1
mfhi $t2
mflo $t3
seq $t4, $t2, $0
add $v0, $t4, $0
j $ra
checkNumPositive: li $t0, 0
slt $t1, $a0, $0 #set t1 to 1 if number is less than 0
add $v0, $t1, $t0
j $ra
exit: li $v0, 10
syscall
Any tips with how I can fix createArray is appreciated, thanks.
Your primary problem is you used .word 80 which only reserves a single word with value 80. You probably meant .space 80 to reserve space for up to 20 words (which seems to be the limit enforced in your code).
Further problem is you are not following conventions about which registers need to be preserved.
For example, you use $t0 as counter in createArray and that's not preserved across subroutines, not by convention and de facto not by your code (both divisibleBy3 and checkNumPositive destroy it).
Similar problem with not properly preserving $ra in nested subroutine calls, as such the return address for createArray is overwritten by the subroutines invoked from there.
I assume the intent of the assignment was to teach you about these nuances.

Resources