Looping and accessing array in mips - mips

I am trying to loop through an array and find the largest value(int) and then print out that value. With this code below i am getting a runtime error that says
"Exception occured at pc=0x00400034
Unaligned adress in inst/data fetch: 0x10010001
attempt to execute non-instruction at 0x80000180"
.globl __start
.data
purchases: .word 5,10,15,20,25,7
.text
__start:
li $t1, 0 # the "i" variable
li $t2, 6 # amount of elements in the array
lw $t0 , purchases+0 #Read the value of the element [0] into $t0
j For_loop
print_int:
li $v0, 1
syscall
li $v0, 10
syscall
For_loop:
blt $t2,$t1,End_loop
lw $t4, purchases($t1)
ble $t0 , $t4, True
add $t1, $t1, 1 #Increment
j For_loop
True:
lw $t0 , purchases($t1)
add $t1, $t1, 1 #Increment
j For_loop #loop
End_loop:
move $a0, $t0
j print_int
li $v0, 10
syscall
All feedback is appreciated!

Related

Why is my MIPS assignment not printing what it should>

I'm sure I've done the math correct for both factoring and amicability, but it doesn't print past the range and I don't know why. Is my math incorrect? Or am I not actually printing the amicability out?
#all the string variables
.data
startrange: .asciiz "Input the start of the range: " #where the range begins
endrange: .asciiz "What is the end of the range: " #where the range ends
pairs: .asciiz "The pairs of amicable numbers are: " #results of amicable #s in range
quit: .asciiz "Unable to check non-positive values\nExiting..." #circumstance for a < 0 or b < 0
swap: .asciiz "End of range < start of range -- swapping values" #if the end of range is less than the start of range, swap the values
range: .asciiz "\nRange of numbers: " #what the range is (startrange -> endrange)
line: .asciiz "-" #dash for range
output1: .asciiz " are amicable numbers" #results if amicable
output2: .asciiz " are not amicable numbers." #results if not amicable
a: .word 0 #input of startrange
be: .word 0 #input of endrange
.text
main:
la $a0, startrange #load address startrange into $a0
li $v0, 4 #gets ready to print string
syscall #prints out startrange
la $s0, a #loads address of startrange input, a, into $s0
li $v0, 5 #gets ready to read string
syscall #reads startrange input, a
addi $s0, $v0, 0
jal negativeInput #calls for negativeInput fxn to check for negative inputs in a or be
la $a0, endrange #load address endrange into $a1
li $v0, 4 #gets ready to print string
syscall #prints out endrange
la $s1, be #loads address of endrange, be, input into $s1
li $v0, 5 #gets ready to read string
syscall #reads endrange input, be
addi $s1, $v0, 0
#if(a < 0 || b < 0) then exit
jal negativeInput #calls for negativeInput fxn to check for negative inputs in a or be
#if(b < a) swap values
jal swapping #jumps to swapping fxn
#print out range of numbers between a and b
jal printRange #jumps to printrange method
jal isFactor #calls for isFactor fxn to check is inputs have factors
jal isAmicable #calls for isAmicable fxn to check is inputs are amicable
negativeInput:
slt $t1, $s0, $zero #if $s0 (a or be) < 0 put in $t1
bne $t1, $zero, negativeTrue #if above is true (a !> 0) jumps to negativeTrue fxn
jr $ra #return to main
negativeTrue:
la $a0, quit #load string quit into $a0
li $v0, 4 #specifies the print string service
syscall #prints out
j exit
swapping:
slt $t1, $s1, $s0 #if $s1 (be) is < $s0 (a) put in $t1
bne $t1, $zero, swapTrue #if above is true (a > b) jumps to swaptrue fxn
jr $ra #returns to main
swapTrue:
la $a0, swap #load string swap into $a0
li $v0, 4 #gets ready to print
syscall #prints out
move $t2, $s0 #moves input a into $t2
move $s0, $s1 #moves input be into $s0
move $s1, $t2 #moves input a into $s1
#addi $t4, $s0, 0 #gets ready to start loop at beginning (a)
printRange:
la $a0, range #loads range statement into $a0
li $v0, 4 #gets ready to print
syscall #prints out
li $v0, 1 #ready to print int
move $a0, $s0 #moving input a into $a0
syscall #printing it out
la $a0, line #moves line statement (-) into $a0
li $v0, 4 #ready to print string
syscall #prints out
li $v0, 1 #ready to print int
move $a0, $s1 #moves input be into $a0
syscall #prints out
exit:
li $v0, 10
syscall
isFactor:
addi $t6, $s0, 0 #i = a to start loop
addi $t4, $zero, 0 #sum_a = 0
blt $t6, $s0, isFactorLoop #while i < a jump to isFactorLoop fxn
isFactor2:
addi $t6, $s1, 0 #i = be to start loop
addi $t4, $zero, 0 #sum_be = 0
blt $t6, $s1, isFactorLoop2 #while i < b jump to isFactorLoop2 fxn
isFactorLoop:
div $s0, $t6 #a/i
mfhi $t5 #a/i == $t5
beq $t5, 0, isFactorLoopTrue #if a/i == 0 jump to isFactorLoopTrue fxn
isFactorLoop2:
div $s1, $t6 #be/i
mfhi $t5 #be/i == $t5
beq $t5, 0, isFactorLoopTrue2 #if be/i == 0 jump to isFactorLoopTrue fxn
isFactorLoopTrue:
add $t4, $t6, $t4 #sum_a += i
move $s3, $t4 #moves sum_a into saved register
j isFactorLoop #repeats loop
isFactorLoopTrue2:
add $t4, $t6, $4 #sum_be += i
move $s4, $t4 #moves sum_be into saved register
j isFactorLoop2 #repeats loop
isAmicable:
addi $t7, $s0, 0 #a/startrange
addi $t8, $s1, 0 #be/endrange
addi $t6, $zero, 0 #i=0
blt $t6, $t8, isAmicableLoop #if i < be jump
beq $t6, $t8, isAmicableLoop #if i == be jump
isAmicableLoop:
addi $t9, $s1, 0 #j = be
bgt $t9, $t7, isAmicableIf #if j > a jump
beq $t9, $t7, isAmicableIf #if j == a jump
isAmicableIf:
#if sum_a == be && sum_be == a they're amicable
beq $s3, $s1, printIsAmicable #if sum_a == be jump
beq $s4, $s0, printIsAmicable #if sum_b == a jump
bne $s3, $s1, printIsNotAmicable #if sum_a != be jump
bne $s4, $s0, printIsNotAmicable #if sum_be != a jump
printIsAmicable:
la $a0, output1 #load address startrange into $a0
li $v0, 4 #gets ready to print string
syscall
printIsNotAmicable:
la $a0, output2 #load address startrange into $a0
li $v0, 4 #gets ready to print string
syscall
I'm sure I did a system call to at least print out the string but thats not working. Even jumped back to main and didn't work. All it prints out to is the range, and doesn't say whether the numbers within that range are amicable.
The problem lies in this function:
printRange:
la $a0, range #loads range statement into $a0
li $v0, 4 #gets ready to print
syscall #prints out
li $v0, 1 #ready to print int
move $a0, $s0 #moving input a into $a0
syscall #printing it out
la $a0, line #moves line statement (-) into $a0
li $v0, 4 #ready to print string
syscall #prints out
li $v0, 1 #ready to print int
move $a0, $s1 #moves input be into $a0
syscall #prints out
exit:
li $v0, 10
syscall
It's important to remember that a label does not alter execution flow simply by existing. The program is printing the range and then "falling through" to your exit routine. This is because labels are merely a hardware abstraction, a convenience so that you don't have to adjust your "line numbers" (read: memory offsets) of your jal, b, and j statements every time you change your code. The assembler converts your source code, which specifies a label, to either a jump to the memory address where the instruction directly beneath that label is stored, or the distance between the current program counter value and that instruction (measured in bytes), as appropriate. The labels no longer exist in your assembled executable program.
Not only that, your isFactorLoop appears to have no way to exit and thus would loop forever.

Why is my array comparison not printing in MIPS?

Here is my code that calculates the sum of two arrays and then prints them in a message to the the console. I would now like to compare my two array sums and return the correct message prompt depending on which array is larger. I feel like I'm very close because I tried to follow the logic from the first printed statements but how can I compare register $s7 & $s8 and then declare one the larger array through my message prompt I have set up? I'm using this emulator: https://cpulator.01xz.net/?sys=mipsr5-spim
.data
x: .word 1,2,3,4,5,6,7,8,9,10
iterator: .word 0
size: .word 9
prompt: .asciiz "The total sum of the array is equal to: "
.text
main:
la $s0, prompt
la $t0, x
lw $t1, iterator
lw $t2, size
begin_loop:
bgt $t1, $t2, exit_loop
sll $t3, $t1, 2
addu $t3, $t3, $t0
lw $t6, 0($t3)
addu $s7, $s7, $t6
addi $t1, $t1, 1
j begin_loop
exit_loop:
li $v0, 4
la $a0, prompt
syscall
li $v0, 1
la $a0, ($s7)
syscall
.data
x2: .word 5,6,7,8,9,10,11,12,13,14
iterator2: .word 0
size2: .word 9
prompt2: .asciiz "The total sum of array 2 is equal to: "
prompt3: .asciiz "The larger array is array 1"
prompt4: .asciiz "The larger array is array 2"
.text
main2:
la $s0, prompt2
la $t0, x2
lw $t1, iterator2
lw $t2, size2
begin_loop2:
bgt $t1, $t2, exit_loop2
sll $t3, $t1, 2
addu $t3, $t3, $t0
lw $t6, 0($t3)
addu $s8, $s8, $t6
addi $t1, $t1, 1
j begin_loop2
exit_loop2:
li $v0, 4
la $a0, prompt2
syscall
li $v0, 1
la $a0, ($s8)
syscall
slt $t1,$s7,$s8 # checks if $s0 > $s1
beq $t1,1,prompt3 # if $s7 > $s8, goes to prompt3
beq $t1,$zero,prompt4 # if $s8 < $s7, goes to prompt4
li $v0, 4
la $a0, prompt3
syscall
li $v0, 4
la $a0, prompt4
syscall

MIPS Print multiples of 2 and 3 in the range 0 to n

I have just started MIPS and I am trying to print all numbers that are multiples of 2 and 3 between a range of 0 to n. I have coded a program that can print the numbers from 0 to n already.
I know that I should try use the "and $t0, $v0, 2" and the "and $t0, $v0, 3" to check if it is a multiple but I get mixed up in the MIPS code as it is very confusing for a beginner. Help would be greatly appreciated!
main:
la $a0, prompt
li $v0, 4
syscall
li $v0, 5
syscall
li $t0, 1
move $t2,$v0;
loop:
bgt $t0, $t2 end
move $a0, $t0
li $v0, 1
syscall
li $a0, '\n'
li $v0, 11
syscall
add $t0, $t0 1
b loop
end:
jr $ra
.data
prompt:
.asciiz "Enter a number: "
This is one approach for this problem
#for (int i =0;i<=n; i++)
#if (i%2 ==0) && (i%3==0)
#print i;
.data
prompt: .asciiz "enter value for n: "
newline: .asciiz "\n"
.text
.globl main
main:
li $t5 0 #initialising i = 0
#for printing prompt
li $v0 4
la $a0 prompt
syscall
#user input reading
li $v0 5
syscall
move $t1 $v0
#displaying on console
move $a0 $t0
li $v0 1
syscall
move $v0 $t0
loop:
beq $t5 $t1 end #checking if i=n
#checking multiples of 2
div $t2 $t5 2
mfhi $t2 #remainder
beq $t2 0 equal #if remainder 0, jump to equal
addi $t5 $t5 1 #increment i by 1
j loop
equal:
#beq $t2 $t3 answer
#checking multiples of 3
div $t3 $t5 3
mfhi $t3 #remainder
beq $t3 0 equal2 #if remainder 0, jump to equal2
addi $t5 $t5 1 #if remainder != 0, incrementing i and jumping to loop
j loop
equal2:
beq $t2 $t3 answer #if both remainder equal to zero, jump to answer
answer:
move $a0 $t5 #moving the value of i for which i is a multiple of 2 and 3
li $v0 1 #printing the answer
syscall
#giving space of a line
li $v0,4
la $a0, newline
syscall
addi $t5 $t5 1 #incrementing i
j loop
#terminating
end:
li $v0, 10
syscall

function to perform swapping in an array

The basic flow of the program is as follows:
1. Print the original content of array.
2. Ask the user for two indices X and Y.
3. Swap the two elements if Array[X] > Array[Y].
4. Print the modified array only if swapping occurs.
.data
array: .word 8, 2, 1, 6, 9, 7, 3, 5, 0, 4
newl: .asciiz "\n"
.text
la $a0, array
li $a1, 10
jal printArray
#Ask the user for two indices
li $v0, 5 #System call code for read_int
syscall
addi $t0, $v0, 0 # first user input in $t0
li $v0, 5 #System call code for read_int
syscall
addi $t1, $v0, 0 # second user input in $t1
swap : li $a1, 0 #inx1
li $a2, 0 #inx2
sll $t0, $a1, 2 # $t0 = inx1* 4
add $t0, $t0, $a0 # $t0 is the address of A[$a1]
sll $t3, $a2, 2 # $t3 = inx2* 4
add $t3, $t3, $a0 # $t3 is the address of A[$a2]
lw $t1, 0($t0) # $t1 = A[$a1]
lw $t2, 0($t3) # $t2 = A[$a2]
ble $t1, $t2, noPrint# if A[$a1] <=A[$a2] goto noPrint
sw $t1, 0($t3) # do the swap
sw $t2, 0($t0) # do the swap
syscall
jal printArray
printArray:
addi $t1, $a0, 0 #$t1 is the pointer to the item
sll $t2, $a1, 2 #$t2 is the offset beyond the last item
add $t2, $a0, $t2 #$t2 is pointing beyond the last item
loop: beq $t1, $t2, end
lw $t3, 0($t1) #$t3 is the current item
li $v0, 1 # system call code for print_int
addi $a0, $t3, 0 # integer to print
syscall # print it
addi $t1, $t1, 4
j loop # Another iteration
end:
li $v0, 4 # system call code for print_string
la $a0, newl #
syscall # print newline
jr $ra # return from this function
noPrint:
li $v0, 10 # system call code for exit
syscall # terminate program
I'm having problems with swap function. It doesn't print anything on console window(using QtSpim). Can you please recommend any suggestion?

Count number of lowercase letters

So I have created this program to count the number of lowercase letters in a string. The problem I am having is that when I reach the end of the string and the nl character is reached, the line beq $t0, $t1, end is not being executed; it just continues indefinitely. I'm not sure what I'm doing incorrectly.
.data
msg1: .word 0:24
.text
.globl main
main:
addu $s0, $0, $ra
li $v0, 8
la $a0, msg1
la $a1, 100
syscall
loop:
lb $t0, 4($a0)
li $t1, 0x0a
beq $t0, $t1, end
continue:
li $t1, 'a'
blt $t0, $t1, count
li $t1, 'z'
bgt $t0, $t1, count
count:
addi $t4, $t4, 1
j loop
end:
li $v0, 1
addu $a0, $t2, $0
syscall
jr $ra
You compare 4($a0) with 0x0a on each iteration of the loop, but you never change $a0 in the loop, so you are not advancing through your string and never look at the \n at the end of the string.
There also are a few other bugs in your code.
Use this at the start of your loop:
loop:
lb $t0, 0($a0)
addiu $a0, $a0, 1
...