Why am I getting a "program is finished running (dropped off bottom) error? - mips

I'm not sure why this is giving me a dropped off error here. Anyone know how to fix this?
I'm trying to create a program that can convert between decimal, hexadecimal, and binary in MIPS. I'm supposed to request the input data type and the input data, and then request the output data type, and output the data. Any and all help is appreciated, thanks!
Code:
#Provide data variable and data as an input and output
.Data
Input1: .asciiz "Kindly enter the input X:"
Input2: .asciiz "Please provide the number system Y details:"
Output: .asciiz "\nThe result will be R:"
#starts global main
.Globl main
main:
addi $A0, $zero, 2
addi $A1, $zero, 15
#get the input value dropped by the user
getX:
li $M0, 4
la $N0, Input1
syscall
li $M0, 5
syscall
blt $M0, $zero, getX
move $K0, $M0
#get the value of the number system dropped by the user
getY:
li $M0, 4
la $N0, Input2
syscall
li $M0, 5
syscall
blt $M0, $A0, getY
bgt $M0, $A1, getY
add $K1, $zero, $M0
li $M0, 4
la $N0, Output
syscall
add $N0, $zero, $K0
add $N1, $zero, $K1
jal convert
li $M0, 15
syscall
#perform conversion over the respective input and number system
convert:
addi $sp, $sp, -16
sw $A3, 12($sp)
#Applying counter that is used to check that how many
#times values will be popped up from the stack
sw $A0, 8($sp)
sw $A1, 4($sp)
sw $ra, 0($sp)
add $A0, $zero, $N0
add $A1, $zero, $N1
beqz $A0, end
div $K4, $A0, $A1
rem $K3, $A0, $A1
add $sp, $sp, -4
sw $K3, 0($sp)
add $N0, $zero, $K4
add $N1, $zero, $A1
addi $A3, $A3, 1
jal convert
end:
lw $ra, 0($sp)
lw $A1, 4($sp)
lw $A0, 8($sp)
lw $A3, 12($sp)
beqz $A3, done
lw $N0, 16($sp)
li $M0, 1
syscall
#operation performed
done:
addi $sp, $sp, 20
jr $ra
#return to the main

li $v0, 10
syscall
I don't see you calling this so at the end of your done branch it doesn't end the system. Opcode 10 will do this for you in MIPS.

jal convert
li $M0, 15
syscall
#perform conversion over the respective input and number system
#your problem is here
convert:
addi $sp, $sp, -16
This is actually a pretty common mistake (we've all been guilty of it so no judgment here.) In assembly, a label simply existing does not prevent code from being executed. In order to have this code run the way you want, you need to insert the following.
jal convert
li $M0, 15
syscall
li $v0,10 #linux/mars/spim exit code
syscall #this is how you properly exit main and return to the OS
#thanks to the above, execution will not fall through to here anymore
#perform conversion over the respective input and number system
convert:
addi $sp, $sp, -16

Related

MIPS "fetch address not aligned on word boundary" error on l.s instruction

I've read through some Q&As about this error on here, but I still don't understand what it means. I have a code in which I try to calculate p(n, r) and I keep getting this error: "line 26: Runtime exception at 0x00400044: fetch address not aligned on word boundary 0x00000006". I don't understand how it's not aligned since to my own knowledge, I haven't manipulated the address.
# n and r are assumed to be integers and n > r
.data
textN: .asciiz "enter n: "
textR: .asciiz "enter r: "
.text
main:
li $v0, 4
la $a0, textN
syscall
li $v0, 6
syscall
move $t0, $v0
li $v0, 4
la $a0, textR
syscall
li $v0, 5
syscall
move $t1, $v0
move $a0, $t0
jal Factorial
la $t7, ($v0)
l.s $f0, ($t7) #line 26
sub $a0, $t0, $t1
jal Factorial
la $t7, ($v0)
l.s $f1, ($t7)
div.s $f12, $f0, $f1
li $v0, 2
syscall
jr $ra
Factorial:
beq $a0, 1, Exception
subi $sp, $sp, 8
sw $t0, ($sp)
sw $t1, 4($sp)
move $t0, $a0
move $v0, $a0
Loop:
subi $t0, $t0, 1
beq $t0, $zero, Exit
sub $t1, $a0, $t0
mul $v0, $v0, $t1
Exit:
lw $t0, ($sp)
lw $t1, 4($sp)
addi $sp, $sp, 8
jr $ra
Exception:
addi $v0, $v0, 1
jr $ra
At first, I hadn't included the la instruction and line 26 was l.s $f0, ($v0). I assumed that the current update to line 26 and 27 was what was missing, but the error I'm receiving has remained unchanged.
I think you're a bit confused about what parentheses really mean.
li $t0,8
move $t1,$t0 ;copy the number 8 from $t0 into $t1.
lw $t2,($t0) ;load the four bytes at memory address 0x00000008 into $t2
Essentially, parentheses around a register are the pointer star * in C, and la $t0, myLabel is the same as typename* ptr = &myLabel;. (I used li in the example above because a memory address is a number itself, but that's not usually what you would do if you really were dereferencing a pointer.)
Your function factorial is intended to return an int, so you don't want to dereference that value. Assembly has no type safety at all, and lets you treat any register as a pointer to memory at any time.
The actual source of your error message, however, has to do with a limitation of the MIPS CPU. Your input value for the factorial function was 3, right? I could tell by the error message. Rather than trying to copy the number 6 to $f1 (which wouldn't work for other reasons) you were trying to load the 4 bytes at memory address 0x00000006. This won't work, because MIPS can't use lw or sw to read/write 32-bit values at memory addresses that aren't aligned, i.e. not a multiple of 4. Trying to do so will result in a runtime error. But it's clear that's not what you wanted to do anyway.

Assembly MIPS: Cannot debug floating-point power function

I have been trying to implement a floating-point function in Assembly MIPS 32-bits, and I have not been able to pinpoint the exact fault. It seems to be in the mul.s $fd, $fsrc1, $fsrc2 command, since the contents of the specific floating-point register remain unchanged (I have checked this with syscalls as well, printing the contents in each case) but I seem to be unable to find the fix. Anyone got any ideas? Full code below:
.align 2
.data
number: .float 0.5
.text
.globl main
main:
li $a0, 3
l.s $f12, number
jal power
li $v0, 2
mtc1 $a0, $f0
syscall
li $v0, 17
syscall
power:
#Build stack
subu $sp,$sp,56 # Stack frame is 56 bytes long
sw $a0, 12($sp) # Save Argument 0 ($a0)
swc1 $f12, 8($sp) # Save Argument 1 ($a1) (integer arg)
sw $s0, 56($sp) # Save $s0
sw $s1, 52($sp) # Save $s1
swc1 $f20, 48($sp) # Save $f20
swc1 $f21, 44($sp) # Save $f21
sw $ra, 16($sp) # Save return address
sw $fp, 20($sp) # Save frame pointer
addiu $fp, $sp, 52
#-----------------------------------------------------------------------#
move $s0, $a0 #stores value of n
mov.s $f22, $f12 #stores value of x
li $s1, 0 #initialize counter with 0
powerLoop:
mul.s $f20, $f20, $f20 #y=y*y
addi $s1, $s1, 1 #increase counter
bgtu $s0, $s1, powerLoop #continue loop as long as counter<n
mov.s $f0, $f20 #return the results
#-----------------------------------------------------------------------#
#Pop stack
lw $a0, 12($sp) #Load back $a0
lwc1 $f12, 8($sp) #Load back $f12
lw $s0, 56($sp) # Load $s0
lw $s1, 52($sp) # Load $s1
lwc1 $f20, 48($sp) # Load $f20
lwc1 $f21, 44($sp) # Load $f21
lw $ra, 16($sp) # Restore old value of $ra
lw $fp, 20($sp) # Restore old value of $fp
addiu $sp, $sp, 56 # Pop stack
jr $ra
SOLVED:
Despite some errors in registers, the main error is in the
li $v0, 2
mtc1 $a0, $f0
syscall
FIX:
li $v0, 2
mov.s $f12, $f0
syscall
REASON: $f12 IS ALWAYS, due to convention, the floating-point argument, even for syscalls. It will not print the contents of $a0 but rather $f12!

MIPS Stack Segment can't be Expanded

I'm writing a function that should return the square root of a perfect square recursively as part of a longer assignment.
I was following this mathematical method before I reverted to an even simpler algorithm to see if the error would repeat itself and it did.
The following code:
.data
prompt: .asciiz "num2sqrt: "
.text
.globl main
sqrt:
# save return address & t0
addi $sp, $sp, -8
sw $ra, 0($sp)
sw $t0, 4($sp)
# t0 = n
move $t0, $a0
# a0 = n/2
srl $a0, $t0, 1
jal sqrtRecursor
#restore return address & t0
lw $t0, 4 ($sp)
lw $ra, 0 ($sp)
addi $sp, $sp, 8
jr $ra
sqrtRecursor:
# save return address & t1
addi $sp, $sp, -8
sw $ra, 0($sp)
sw $t1, 4($sp)
# square test
mult $a0, $a0
mflo $t1
beq $t1, $t0, returnAnswer
bne $t1, $t0, newGuess
#restore return address & t1
lw $t1, 4 ($sp)
lw $ra, 0 ($sp)
addi $sp, $sp, 8
jr $ra
returnAnswer:
move $v0, $a0
newGuess:
# t1 = (((x+1)*guess)/x)/2
# x+1
addi $t1, $t0, 1
# *guess
mult $a0, $t1
mflo $t1
# /x
div $t1, $t0
mflo $t1
# /2
srl $t1, $t1, 1
move $a0, $t1
jal sqrtRecursor
main:
#print "Enter num2sqrt: "
la $a0, prompt
li $v0, 4
syscall
#input num2sqrt
li $v0, 5
syscall
move $s1, $v0
move $a0, $s1
jal sqrt
# print result
move $a0, $v0
li $v0, 1
syscall
# end
li $v0, 10
syscall
returns the following error on QTSpim:
Can't expand stack segment by 12 bytes to 524288 bytes. Use -lstack # with # > 524288
which then hangs the app for a minute or so.
I've double checked that I'm saving and returning all my return addresses and used variables, and also attempted implementing the same algorithm in Java separately (which worked), but have yet been unable to figure out what I need to fix and where.
I've been able to implement a power function before this so I'm not a complete novice and am asking after putting in approximately 5 hours of research and debugging on this.
It could be a stack management problem or an if/else implementation error from the intuition I have about my own code.

I tried to write Add function in mips but i got wrong answer

I wrote an add function in MIPS :
.data
str: .asciiz "\n"
.text
.globl main
main:
li $s0, 18
addi $sp, $sp, -4
sw $s0, 0($sp)
li $v0, 1
la $a0, add
syscall
li $v0, 4
la $a0, str
syscall
addi $sp, $sp, 4
jr $ra
add:
lw $t0, 0($sp)
add $v0, $t0, $t0
jr $ra
when i try to simulate it i got wrong answer like 4194388. Did i make something wrong?
It looks like you're attempting to call your add routine using a syscall.
The proper way to call your routine would be jal add

MIPS, Recursion

I trying to write a MIPS program that gets an unsigned integer as argument and returns the sum of all decimal digits in the integer recursively. For example if the argument is 75080 then the sum to be returned is 20 (7+5+0+8+0). Here is my code so far. Any help would be appreciated.
My way of thinking was to divide the number by 10 leaving me with the last integer in the number, add the reminder using mfhi.
.data
prompt: .asciiz "Enter a string of integer: "
output: .asciiz "\nThe total sum is: "
.text
.globl main
main:
la $a0, prompt
li $v0, 4
syscall
li $v0, 5
syscall
move $t2, $v0
la $a0, output
li $v0, 4
syscall
Loop:
div $t2, $t2, 10
mflo, $t1
mfhi, $t3
beqz $t1, Exit
add $t1, $t1, 0
b additive
additive:
add $t0, $t1, $t1
j Loop
Exit:
la $a0, output
li $v0, 4
syscall
la $v0, 10
syscall
What's this supposed to be doing? Adding 0 to the register won't change its value:
add $t1, $t1, 0
After dividing and copying to $t1 and $t3, the quotient is in $t1 and the remainder is in $t3. You're treating it the other way around when you add to the total.
This is actually going to give you $t0 = 2 * $t1: you're adding $t1 to itself and storing the result in $t0.
add $t0, $t1, $t1
You probably actually want:
add $t0, $t0, $t3
You're checking for $t1 == 0 before adding the remainder to the total, so the most significant digit will never get added. You don't really need a subroutine for adding to the total either. You can also use bnez Loop instead of beqz Exit -> b Loop. Lastly, you don't even need $t1, because the quotient is already in $t2.
Get rid of additive and replace Loop with this:
Loop:
div $t2, $t2, 10
mfhi, $t3
add $t0, $t0, $t3
bnez $t2, Loop
Your Exit is weird: you're printing the output string a second time instead of printing the integer.
Change it to this:
Exit:
move $a0, $t0
la $v0, 1
syscall
la $v0, 10
syscall
The approach is quite simple. You need recursive function, I named it SumDigits that will take the last digit and repeat procedure for all digits in the argument. After the recursive call returns you'll add digit to the previous result. The code is commented for easier understanding. The code follows:
.text
#calculates sum of digits recursively
SumDigits:
sub $sp, $sp, 12 #alloocate 12B on stack
sw $ra 0($sp) #save return address
sw $a0, 4($sp) #save argument
beq $a0, $0, exit_sumdigits #when there is no more digits return 0
rem $t0, $a0, 10 #get last digit
sw $t0, 8($sp) #save it on stack
div $a0, $a0, 10 #divide argument by 10
jal SumDigits #repeat procedure
lw $t0, 8($sp) #read digit from stack
add $v0, $v0, $t0 #add digit to previous result
lw $ra, 0($sp) #load return address
addi $sp, $sp, 12 #free stack
jr $ra #return
exit_sumdigits:
li $v0, 0 #there are no more digits, return 0
lw $ra, 0($sp) #load return address
addi $sp, $sp, 12 #free stack
jr $ra #return
main:
li $a0, 75080 #load number in $a0
jal SumDigits #call SumDigits
move $a0, $v0 #set a0 = result of SumDigits
li $v0, 1 #set $v0 for print int system call
syscall
li $v0, 10 #set $v0 for exit system call
syscall
.data