My assembler code has this error: "invalid program counter value: 0x00000000 Go: execution terminated with errors" - mips

.data
prompt2: .asciiz "please enter the elements one by one:"
prompt3: .asciiz "the array is ordered as follows: "
prompt4: .asciiz "-- Program is finished running --"
str1: .asciiz ","
newLine: .asciiz "\n"
.text
addi $sp,$sp,-24
sw $ra,0($sp)
sw $s4,4($sp)
sw $a2,8($sp)
sw $s3,12($sp)
sw $s0,16($sp)
sw $s2,20($sp)
main:
# read n from console
li $v0 5
syscall
move $a2 $v0 #tagghiir t0 be a2 (n)
# allocate dynamic memory
sll $a0 $v0 2 # sll performs $a0 = $v0 x 2^2
li $v0 9 #9 is the system code for service(sbrk) whoes work is
syscall #to allocate dynamic memory
move $a1 $v0 #t2 saved address of heap #taghiir t2 to a1
#saved for printing
li $v0, 4 # $system call code for print_str
la $a0, prompt2 # $address of string to print
syscall
move $t1 $zero
move $t4,$a1
inputLoop:
bge $t1 $a2 exit1
# read in and store int
li $v0 5
syscall
sw $v0 0($t4)
addi $t1 $t1 1
addi $t4 $t4 4
li $v0, 4 # $system call code for print_str
la $a0, newLine # $address of string to print
syscall
j inputLoop
exit1:
jal sort
li $v0, 4 # $system call code for print_str
la $a0, prompt3 # $address of string to print
syscall
move $t3,$zero
move $t4 ,$a1
outputLoop:
bge $t3 $a2 exit2
#inaro azoon yki copy krdm
lw $t6, 0($t4)
li $v0, 1
move $a0, $t6
syscall
# read in and store int
addi $t3 $t3 1
addi $t4 $t4 4
blt $t4,$a1 ,comma
# bne $t5,$zero,comma
comma:
li $v0, 4 # $system call code for print_str
la $a0, str1 # $address of string to print
syscall
j outputLoop
exit2:
li $v0, 10
syscall #for finishing the program
swap:
move $a3,$a3
move $a1,$s4
# move $t5,$zero # its for our temp variable in c code
move $t4 ,$a1 #t4 is now the base address of heap
sll $t6 , $a3,2 # s1 is the given k
add $t6,$t4,$t6 # heap address + k*4
lw $t3,0($t6) #khoone k e heap
lw $t5,4($t6) #khoone k+1 heap
sw $t5,0($t6)
sw $t3,4($t6)
jr $ra
sort:
# move $s0,$zero #i=t0
move $s4,$a1 #base address of heap
addi $t5,$a2,-1 # meghdare i
move $s2,$zero #its the flag
while:
addi $s2,$s2,1
move $a3,$zero #j #taghiir s1 be a3 (haman j va k
forLoop:
bge $a3,$t5,outOfLoop
sll $t6,$a3,2 #j
add $t1,$t6,$a1 #v+j
lw $t7,0($t1) #t7=heap[j]
lw $t8,4($t1) #t8=heap[j+1]
blt $t7,$t8,outOfIf
move $s4,$a1
move $s3,$a3
jal swap
addi $s2,$s2,-1
outOfIf:
addi $a3,$a3,1 #j++
outOfLoop:
addi $t5,$t5-1 #i--
bgt $s2,$zero,exit_outter #if a>=b break
ble $t5,$zero,exit_outter #if b=< c break
j while
exit_outter:
lw $ra,0($sp)
lw $s4,4($sp)
lw $a2,8($sp)
lw $s3,12($sp)
lw $s0,16($sp)
lw $s2,20($sp)
addi $sp,$sp,24
jr $ra
Where am I going wrong?

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.

Infinite [Bad instruction address] occurred and ignored error occurs. What can be changed to fix this problem?

I am working on a MIPS Fibonacci sequence. However, if I run the program, I input a number and all I get is infinite number of the error: [Bad instruction address] occurred and ignored infinite times. What should I do? And I am only allowed to change the code between the ##########s.
Below is my MIPS code.
.data
newline:
.asciiz "\n"
str0:
.asciiz "Enter a positive integer: "
str1:
.asciiz "ERROR: received a negative integer!\n"
str2:
.asciiz "INFO: fibonacci returned "
.text
# $a0: n (<1024)
################################################################################FIXME
fibonacci:
li $t2, 1
addiu $sp, $sp, -12
sw $ra, 0($sp)
sw $s0, 4($sp)
sw $s1, 8($sp)
addiu $s0, $a0, 0
beq $zero, $s0, ResultOne
beq $t2, $s0, ResultOne
bltz $s0, Negative
addiu $a0, $s0, -1
jal fibonacci
addiu $s1, $v1, 0
addiu $a0, $s0, -2
jal fibonacci
addu $v1, $v1, $s1
j finish
ResultOne:
li $v0, 1
li $v1, 1
j Finish
Negative:
li $v0, 0
j Finish
Finish:
lw $s1, 8($sp)
lw $s0, 4($sp)
lw $ra, 0($ra)
addiu $sp, $sp,12
jr $ra
# FIXME
################################################################################
.globl main
main:
# print_string str0
li $v0, 4
la $a0, str0
syscall
# $t0 = read_int
li $v0, 5
syscall
move $t0, $v0
# $s0 = $ra; fibonacci($t0); $ra = $s0
move $s0, $ra
move $a0, $t0
jal fibonacci
move $ra, $s0
# $t0 = $v0; $t1 = $v1
move $t0, $v0
move $t1, $v1
# if ($t0 == 0) { goto main_failure }
beq $t0, $zero, main_failure
main_success:
# print_string str2
li $v0, 4
la $a0, str2
syscall
# print_int $t1
li $v0, 1
move $a0, $t1
syscall
# print_string newline
li $v0, 4
la $a0, newline
syscall
# goto main_return
b main_return
main_failure:
# print_string str1
li $v0, 4
la $a0, str1
syscall
main_return:
# return
jr $ra

I keep getting 0 as an answer for my mips code where I'm supposed to find the gcd of two numbers

.data
n1:.asciiz"Enter the first number:"
n2: .asciiz"Enter the second number:"
.text
.globl main
main:
li $v0,4
la $a0,n1
syscall
li $v0, 5 # get input from user
syscall
move $a0,$s0
li $v0,4
la $a0,n2
syscall
li $v0, 5 # get second input from user
syscall
move $a0,$s1
jal calcGCD # call function calcGCD
add $a0,$v0,$zero
li $v0,1
syscall # print result
li $v0, 10 # exit program
syscall
calcGCD:
#GCD(n1, n2)
# n1 = $a0
# n2 = $a1
addi $sp, $sp, -12
sw $ra, 0($sp) # save function into stack
sw $s0, 4($sp) # save value $s0 into stack
sw $s1, 8($sp) # save value $s1 into stack
add $s0, $a0, $zero # s0 = a0 ( value n1 )
add $s1, $a1, $zero # s1 = a1 ( value n2 )
addi $t1, $zero, 0 # $t1 = 0
beq $s1, $t1, return # if s1 == 0 return
add $a0, $zero, $s1 # make a0 = $s1
div $s0, $s1 # n1/n2
mfhi $a1 # reminder of n1/n2 which is equal to n1%n2
jal calcGCD
exitGCD:
lw $ra, 0 ($sp) # read registers from stack
lw $s0, 4 ($sp)
lw $s1, 8 ($sp)
addi $sp,$sp , 12 # bring back stack pointer
jr $ra
return:
add $v0, $zero, $s0 # return $v0 = $s0 ( n1)
j exitGCD
The main issue with your code is with the part where you store the user input in the registers. In move $a0,$s0, you are moving the value at $s0 into $a0 when the user input is stored in $v0, therefore, it should be move $a0,$v0, and from your function, you seem to have stored the second input in $a1 but in your code, both the inputs are being stored in the same register so the next command should be move $a1,$v0. Here is one version of your code.
.data
n1:.asciiz"Enter the first number:"
n2: .asciiz"Enter the second number:"
.text
.globl main
main:
li $v0,4
la $a0,n1
syscall
li $v0, 5 # get input from user
syscall
move $t0,$v0 #temporarily store the user input in another register because $a0 is having another value stored in it in the next command
li $v0,4
la $a0,n2
syscall
li $v0, 5 # get second input from user
syscall
move $a1,$v0
move $a0,$t0 #transfer the first user input into $a0 to be used in the function
jal calcGCD # call function calcGCD
add $a0,$v0,$zero
li $v0,1
syscall # print result
li $v0, 10 # exit program
syscall
calcGCD:
#GCD(n1, n2)
# n1 = $a0
# n2 = $a1
addi $sp, $sp, -12
sw $ra, 0($sp) # save function into stack
sw $s0, 4($sp) # save value $s0 into stack
sw $s1, 8($sp) # save value $s1 into stack
add $s0, $a0, $zero # s0 = a0 ( value n1 )
add $s1, $a1, $zero # s1 = a1 ( value n2 )
addi $t1, $zero, 0 # $t1 = 0
beq $s1, $t1, return # if s1 == 0 return
add $a0, $zero, $s1 # make a0 = $s1
div $s0, $s1 # n1/n2
mfhi $a1 # reminder of n1/n2 which is equal to n1%n2
jal calcGCD
exitGCD:
lw $ra, 0 ($sp) # read registers from stack
lw $s0, 4 ($sp)
lw $s1, 8 ($sp)
addi $sp,$sp , 12 # bring back stack pointer
jr $ra
return:
add $v0, $zero, $s0 # return $v0 = $s0 ( n1)
j exitGCD

my mips code does not print out correct answer

so I tried this code, took some parts of it from this forum. my answer is not coming okay though. I'm getting weird numbers for min and max. can anyone tell me what did I do wrong?
.text
.globl __start
__start: # execution starts here
la $t0,array # $t0 will point to the elements
lw $t2,($t0) # initialize min = a[0]
lw $t3,($t0) # initialize max = a[0]
addi $t4, $s0, 0
li $t1, 0
loop:
bge $t4, 8, EndLoop
lw $t2, array($t1)
bgt $s2, $s0, SetMax
blt $s2, $s1, SetMin
cont:
addi $s1, $s1, 4
addi $t4, $t4, 1
j loop
SetMax:
move $t3, $s2
j cont
SetMin:
move $t2, $s2
j cont
EndLoop:
li $v0 4
la $a0 ans2
syscall
li $v0 1
la $a0 ($s0)
syscall
li $v0 4
la $a0 Space
syscall
li $v0 4
la $a0 ans1
syscall
li $v0 1
la $a0 ($s1)
syscall
la $a0,endl # syscal to print out
li $v0,4 # a new line
syscall
li $v0,10 # Exit
syscall # Bye!
.data
array: .word 3,4,2,6,12,7,18,26,2,14,19,7,8,12,13
ans1: .asciiz "min = "
ans2: .asciiz "\nmax = "
endl: .asciiz "\n"
Space: .asciiz " "

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?