MIPS Prime number factors - mips

I am trying to write a program in MIPS, where you enter a number and it tells you whether it is prime or not, and if it is prime it also gives all the prime numbers up to it. Ex: n = 11, and it will print: "11 is prime, and so are 2, 3, 5, 7, 11". I am not sure how to create the loop to check if numbers before the input are prime and to print or skip over them.
.data
string1: .asciiz "Please enter an integer: "
string2: .asciiz "Input is a prime number"
string3: .asciiz "Input is not a prime number"
string4: .asciiz " "
string5: .asciiz "Prime numbers up to the input are: "
.text
main:
# Print string 1
la $a0, string1
li $v0, 4
syscall
# Take input from user
li $v0, 5
syscall
# Store input in temp register
move $t8, $v0
# Initial value for processing
li $t9, 2
# Corner cases
blt $t8, 1, NotPrime
beq $t8, 1, NotPrime
beq $t8, 2, Prime
loopPrime:
beq $t9, $t8, Prime # Branch to prime when input equals initial value
div $t8, $t9 # Divide input by numbers in range
mfhi $t1 # Move division remainder to t1
beq $t1, $0, NotPrime # If remainder equals 0, the input is not prime number
addi $t9, $t9, 1 # Increment initial value by 1
b loopPrime
Prime:
li $v0, 4
la $a0, string2
syscall
li $v0, 4
la $a0, string4
syscall
li $v0, 4
la $a0, string5
syscall
# Initial value2 for processing
li $t7, 2
b loopfactor2
b Exit
loopfactor1:
addi $t7, $t7,1
b loopfactor2
loopfactor2:
beq $t9, $t7, Print
div $t7, $t9
mfhi $t1
beq $t1, $0, Skip
addi $t9, $t9, 1
blt $t7, $t8 loopfactor1
b Exit
Print:
li $v0, 4
move $a0, $t7
syscall
Skip:
addi $t7, $t7,1
b loopfactor2
NotPrime:
li $v0, 4
la $a0, string3
syscall
b Exit
Exit:
li $v0, 10
syscall

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.

MIPS program: check if number is prime

.data
userInput: .asciiz "give an integer to check if prime: "
prime: .asciiz "Prime"
notPrime: .asciiz "No prime"
.text
main:
li $v0, 4
la $a0, userInput
syscall
li $v0, 5
syscall
move $t0, $v0
addi $t1, $t1, 1
addi $t2, $t2, 2
ble $t0, $t1, no
beq $t0, $t2, yes
div $t0, $t2
mflo $s0
mfhi $s1
bgt $s1, $zero, yes
yes:
li $v0, 4
la $a0, prime
syscall
j exit
no:
li $v0, 4
la $a0, notPrime
syscall
j exit
exit:
li $v0, 10
syscall
For some reason, the program always jumps to the "yes" even when there's a remainder (mfhi) and I can't seem to find the problem on why it does it. When I give input 4 it should jump to the "no" label since the remainder is 0 so it isn't greater than the constant 0.
What are you trying to accomplish with this part of your code:
bgt $s1, $zero, yes
yes:
Play the computer and decide where to go if the gt is true vs. if the gt is false.

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

MIPS multiplication using addition

sorry, I try to multiply two integers but it doesn't work. I can't find where the problem is.Maybe because of register' names but I don't know how to correct it. I correct many times but it is not successful. Could anyone give me some points?
.data
prompt1: .asciiz "Please enter the first signed (decimal) integer: "
prompt2: .asciiz "Please enter the second signed (decimal) integer: "
result_msg: .asciiz "The result of these two 16-bit integers\' multiplication is: "
.text
.globl main
main:
li $v0, 4 #print prompt
la $a0, prompt1
syscall
li $v0, 5 #read multiplicand
syscall
move $s0, $v0
li $v0, 4 #print prompt
la $a0, prompt2
syscall
li $v0, 5 #read multiplier
syscall
move $s1, $v0
Mult: ori $t0,$zero,1 #mask
move $s3, $0 #initialize the result register
move $t1, $0
loop: beq $s1, $zero, end #if the multiplier is 0 then finished
and $t1, $t0, $s1 #mask
beq $t1, 1, mult_add
beq $t1, 0, shift
mult_add: addu $s3, $s3, $s0 #add to get product
shift:
sll $s0, $s0, 1 #shift multiplicand left
srl $s1, $s1, 1 #shift multiplier right
j loop
end:
jr $ra
result: #input the print_string
li $v0, 4
la $a0, result_msg
syscall
exit:
li $v0, 1 #input result
move $a0, $s3
syscall
li $v0, 10 #exit
syscall
Inspecting your code I see that you jump to label end when you are done multiplying.
The instruction at that label issues a jr $ra which "returns from a function", but I guess you just want to print the result and exit.
Therefore I'd suggest you remove that instruction so as to print the result and exit and maybe remove label result as it is not used anywhere in your code.