Mips Recursive Assignment - recursion

I hope everyone is okay in these covid-19 times. I am working on an assignment and I'm hoping someone could point out where I'm going wrong. I'm taking in a number in a MIPS program that will be put in a recursive function that returns the following:
Guidelines are:
The recursive function accepts a single positive integer as an input argument and is defined as:
recurse(n) = 1 if n=0
recurse(n) = n * Recurse(n-1) + 1 if n >0
My recursing is going alright, but I feel like I'm getting lost in the returns when the function unwinds. I'm also pretty sure that a lot of what I'm doing might look very messy as I'm a novice with MIPS. Here is my version:
Here is my code:
PRINT_STRNG = 4
PRINT_INT = 1
PRINT_CHAR = 11
READ_CHAR = 12
READ_STRNG = 8
READ_INT = 5
TERMINATE = 10
NEWLINE = 10
.data
prompt1: .asciiz "\nPlease enter a decimal integer between 1 and 12 (or 0 to stop): "
terminating: .asciiz "\nTerminating!"
recursing: .asciiz "recursing "
returning: .asciiz "returning "
newLine: .asciiz "\n"
.text
main:
jal clearRegs
li $t0, 4
jal promptNumber
move $a1, $v0
beq $a1, $zero, exit
move $t2, $a1 # $t2 has n
mul $t1, $a1, $t0 # $t1 has the spaces
jal factPlusOne
j main
promptNumber:
# Prompt the user for first decimal
li $v0, PRINT_STRNG
la $a0, prompt1
syscall
# Get the user's first decimal
li $v0, READ_INT
syscall
# Print new line after
li $v0, PRINT_STRNG
la $a0, newLine
syscall
jr $ra
printRecursingSpaces:
# $ra now points to below print spaces
# Prints the spaces before the recursing messages
blez $t1, printRecursing
li $a0, 32
li $v0, 11 # syscall number for printing character
syscall
addi $t1, $t1, -1
j printRecursingSpaces
printReturningSpaces:
# Prints the spaces before the returning messages
blez $t1, printReturning
li $a0, 32
li $v0, 11 # syscall number for printing character
syscall
addi $t1, $t1, -1
j printReturningSpaces
factPlusOne:
# Tests to enter recursion or end recursion
move $s0, $ra
jal printRecursingSpaces
bgtz $a1, recurse
li $t3, 1
jr $s0
recurse:
addi $sp, $sp, -8
sw $ra, 4($sp)
sw $a1, 0($sp)
addi $a1, $a1, -1
mul $t1, $a1, $t0
jal factPlusOne
lw $v1, 0($sp)
mul $t4, $t3, $v1
addi $t4, $t4, 1 # $t3 has n * Recurse(n-1) + 1
mul $t1, $t4, $t0
jal printReturningSpaces
lw $ra, 4($sp)
addi $sp, $sp, 8
jr $ra
printRecursing:
# Prints the recursing message
li $v0, PRINT_STRNG
la $a0, recursing
syscall
# Print the n
li $v0, PRINT_INT
addi $a0, $a1, 0
syscall
# Prints a new line
li $v0, PRINT_STRNG
la $a0, newLine
syscall
jr $ra
printReturning:
# Prints the returning message
li $v0, PRINT_STRNG
la $a0, returning
syscall
# Print the n
li $v0, PRINT_INT
addi $a0, $t4, 0
syscall
# Prints a new line
li $v0, PRINT_STRNG
la $a0, newLine
syscall
jr $ra
clearRegs:
sub $v0, $v0, $v0
sub $v1, $v1, $v1
sub $a0, $a0, $a0
sub $a1, $a1, $a1
sub $t0, $t0, $t0
sub $t1, $t1, $t1
sub $t2, $t2, $t2
sub $t3, $t3, $t3
sub $t4, $t4, $t4
sub $s0, $s0, $s0
jr $ra
exit:
# Show terminating message and exit program
li $v0, PRINT_STRNG
la $a0, terminating
syscall
li $v0, TERMINATE
syscall
Gonna be hacking at it for the next few hours. I appreciate any assistance and hope everyone is having a good Sunday. Thank you!

I did end up fixing this, I just had to grasp the concept that anywhere you need to save the value of $ra, make a stack variable. Working code below:
PRINT_STRNG = 4
PRINT_INT = 1
PRINT_CHAR = 11
READ_STRNG = 8
READ_INT = 5
TERMINATE = 10
NEWLINE = 10
.data
prompt1: .asciiz "\nPlease enter a decimal integer between 1 and 6 (or 0 to stop): "
terminating: .asciiz "\nTerminating!"
recursing: .asciiz "recursing "
returning: .asciiz "returning "
newLine: .asciiz "\n"
theNumber: .word 0
.text
main:
li $t0, 4
jal promptNumber
lw $a1, theNumber
bgt $a1, 6, main # If >6 is entered
beq $a1, $zero, exit # If 0 is entered
blez $a1, main # If <0 is entered
mul $t1, $a1, $t0 # $t1 has the spaces
jal factPlusOne
jal printReturningSpaces # for the last result
j main
promptNumber:
# Prompt the user for first decimal
li $v0, PRINT_STRNG
la $a0, prompt1
syscall
# Get the user's first decimal
li $v0, READ_INT
syscall
sw $v0, theNumber
# Print new line after
li $v0, PRINT_STRNG
la $a0, newLine
syscall
jr $ra
printRecursingSpaces:
# Prints the spaces before the recursing messages
blez $t1, printRecursing
li $a0, 32
li $v0, 11 # syscall number for printing character
syscall
addi $t1, $t1, -1
j printRecursingSpaces
printReturningSpaces:
# Prints the spaces before the returning messages
blez $t1, printReturning
li $a0, 32
li $v0, 11 # syscall number for printing character
syscall
addi $t1, $t1, -1
j printReturningSpaces
factPlusOne:
# Tests to enter recursion or end recursion, saves $ra
addi $sp, $sp, -4
sw $ra, 0($sp)
jal printRecursingSpaces
lw $ra, 0($sp)
addi $sp, $sp, 4
bgtz $a1, recurse
li $t3, 1
jr $ra
recurse:
# wind up recursion
addi $sp, $sp, -8
sw $ra, 4($sp)
sw $a1, 0($sp)
addi $a1, $a1, -1
mul $t1, $a1, $t0
jal factPlusOne
# unwind recursion
lw $v1, 0($sp)
jal printReturningSpaces
mul $t1, $v1, $t0
mul $t3, $t3, $v1
addi $t3, $t3, 1
lw $ra, 4($sp)
addi $sp, $sp, 8
jr $ra
printRecursing:
# Prints the recursing message
li $v0, PRINT_STRNG
la $a0, recursing
syscall
# Print the n
li $v0, PRINT_INT
addi $a0, $a1, 0
syscall
# Prints a new line
li $v0, PRINT_STRNG
la $a0, newLine
syscall
jr $ra
printReturning:
# Prints the returning message
li $v0, PRINT_STRNG
la $a0, returning
syscall
# Print the n
li $v0, PRINT_INT
addi $a0, $t3, 0
syscall
# Prints a new line
li $v0, PRINT_STRNG
la $a0, newLine
syscall
jr $ra
exit:
# Show terminating message and exit program
li $v0, PRINT_STRNG
la $a0, terminating
syscall
li $v0, TERMINATE
syscall

Related

Sum calculator in MIPS

I am fairly new to MIPS and am trying to write a code which calculates the sum of an integer which was entered by the user. I am using recursion in my code but am not sure if theres an easier way to do this. My code runs fairly well for the most part however it keeps adding 1 to the final sum. For example, sum of 10 is 55 but it gives me 56.
.data
#messages
sumMessage: .asciiz "\Enter a number to find its Sum: "
sumMessage1: .asciiz "\nSum is: "
sumInput: .word 0
sumAns: .word 0
.text
.globl main
main:
#read promtMessage
li $v0, 4
la $a0, sumMessage
syscall
#take input
li $v0,5
syscall
sw $v0, sumInput#storing input
#call sumCalc function
lw $a0, sumInput
jal sumCalc
sw $v0, sumAns#returns value from function
#display sum
li $v0, 4
la $a0, sumMessage1
syscall
li $v0, 1
lw $a0, sumAns
syscall
#end main
li $v0, 10
syscall
#sumCalc Function
.globl sumCalc
sumCalc:
subu $sp, $sp, 8
sw $ra, ($sp)#storing value of returning address in the stack
sw $s0, 4($sp)#4 bites apart from the value stored above in the stack
#base case
li $v0, 1
beq $a0, 0, exit
#find factorial n-1
move $s0, $a0
sub $a0, $a0, 1
jal sumCalc
add $v0, $s0, $v0
exit:
lw $ra, ($sp)
lw $s0,, 4($sp)
addu $sp, $sp, 8
jr $ra
Any help would be appreciated!
Using recursion here makes the processing cumbersome and of little interest because we can calculate the sum directly. The sum of an integer is given to us using the following mathematical formula: n * (n + 1) / 2 or else n * (n + 1) then a right shift which is comparable to a division by 2.
.data
#messages
sumMessage: .asciiz "\Enter a number to find its Sum: "
sumMessage1: .asciiz "\nSum is: "
sumInput: .word 0
sumAns: .word 0
.text
.globl main
main:
#read promtMessage
li $v0, 4
la $a0, sumMessage
syscall
#take input
li $v0,5
syscall
sw $v0, sumInput#storing input
#call sumCalc function
lw $a0, sumInput
jal sumCalc
sw $s2, sumAns#returns value from function
#display sum
li $v0, 4
la $a0, sumMessage1
syscall
li $v0, 1
lw $a0, sumAns
syscall
#end main
li $v0, 10
syscall
#sumCalc Function
.globl sumCalc
sumCalc:
subu $sp, $sp, 8
sw $ra, ($sp)#storing value of returning address in the stack
sw $s0, 4($sp)#4 bites apart from the value stored above in the stack
li $s2,1 # storing the final result
move $s3,$v0
addi $s3,$s3,1 # $s3 = $v0+1
mul $s2,$v0,$s3 # $s2 = $v0 * ($v0 +1)
div $s2,$s2,2 # $s2 = $s2/2
exit:
lw $ra, ($sp)
lw $s0,4($sp)
addu $sp, $sp, 8
jr $ra

Fibonacci recursion function in Mips

I am trying to pratice how recursion works in Mips. So I tried to write a fibonacci function fib.
At first I had addi $a0, $a0, n to write a general solution, but I thought that if I want to check my results in Qtspim , maybe i need to add a real number as an argument. I do not want a full answer , if the thought behind the code is wrong, but some help in order to run it in Qtspim, and find my mistakes (logic mistakes) on my own
This is my code:
.globl main
.text
main:
addi $a0, $a0, 4
fib:
addi $sp, $sp, -8
sw $ra, 4($sp)
sw $a0, 0($sp)
slti $t0, $a0, 1
beq $t0, 1, L2 #if n<1
beq $a0, 1, L2 # if n=1
beq $t0, 0, L1 # if n>1
#what to do when n<=1
L2:
addi $v0, $v0, 1
jr $ra
#what to do when n>1
L1:
addi $a0, $a0, -1
jal fib
lw $a0, 0($sp)
lw $ra, 4($sp)
addi $sp, $sp, 8
lw $t1, 0($v0)
add $v0, $t1, $v0
jr $ra
li $v0,10
syscall
I get an error message as such:
Bad address in data/stack read: 0x00000000
.text
main:
addi $a0, $a0, 4
#### you've place fib inline inside main,
#### you should have all of main here, and "call" fib using jal instruction
#### and the syscall for exit goes up here as well
fib:
addi $sp, $sp, -8 # you will want one more word of stack space
sw $ra, 4($sp)
sw $a0, 0($sp)
slti $t0, $a0, 1 # i would have use 2 here instead of 1
beq $t0, 1, L2 #if n<1 # this is ok, but better to use bne $t0, $0, L2
beq $a0, 1, L2 # if n=1 # and then this would not be needed
beq $t0, 0, L1 # if n>1 # this doesn't need to be conditional, if the program reaches here then L1 is the thing to do next.
#what to do when n<=1
L2:
addi $v0, $v0, 1 # here you want to return just 1 not v0+1
jr $ra
#what to do when n>1
L1:
addi $a0, $a0, -1
jal fib # fib(n-1), good
lw $a0, 0($sp) # this reloads $a0 the original n
lw $ra, 4($sp)
addi $sp, $sp, 8
lw $t1, 0($v0) # after a call to fib $v0 holds fib(n)
# an integer value but you're treating it like a pointer and dereferencing it
add $v0, $t1, $v0 # here doing fib(n-1) + n
# you want fib(n-1) + fib(n-2) instead
# so you're missing a fib(n-2)
jr $ra
li $v0,10 # this is part of main, so move it to where main is
syscall # realize that code located here is unreachable (aka dead)
# anything after an unconditional branch (here the jr $ra just above)
# and without a label is very suspicious as unreachable
update , some improved (i hope ) code
.globl main
.text
main:
addi $a0, $a0, 4
jal fib
li $v0, 10
syscall
fib:
addi $sp, $sp, -8
sw $ra, 4($sp)
sw $a0, 0($sp)
slti $t0, $a0, 2
beq $t0, 1, L2
#what to do when n<=1
L2:
addi $v0, $v0, 1
jr $ra
#what to do when n>1
L1:
addi $a0, $a0, -1 # a0 -> n-1
jal fib # fib(n-1)
lw $a0, 0($sp) #load word from memory adress 0($sp) to register $a0
lw $ra, 4($sp) #load word from memory adress 4($sp) to register $ra
addi $sp, $sp, 8
add $t1, $zero, $v1 # in register $t1 store current $v1
add $v0, $t2, $v0 # v0_ n+1 =v0 _n + v0_n-1
add $t2, $t1, $zero # in $t2 save the previous value of v1
.data
prompt: .ascii "Fibonacci Program\n"
.asciiz "Enter N value: "
results: .asciiz "\nFibonacci of N = "
n: .word 0
answer: .word 0
.text
.globl main
.ent main
main:
# Read n value from user
li $v0, 4 # print prompt string
la $a0, prompt
syscall
li $v0, 5 # read N (as integer)
syscall
sw $v0, n
# Call Fibonacci function.
lw $a0, n
jal fib
sw $v0, answer
# Display result
li $v0, 4 # print prompt string
la $a0, results
syscall
li $v0, 1 # print integer
lw $a0, answer
syscall
# Done, terminate program.
li $v0, 10 # terminate
syscall # system call
.end main
# Fibonacci function
# Recursive definition:
# = 0 if n = 0
# = 1 if n = 1
# = fib(n-1) + fib(n-2) if n > 2
# Arguments
# $a0 - n
# Returns
# $v0 set to fib(n)
.globl fib
.ent fib
fib:
subu $sp, $sp, 8
sw $ra, ($sp)
sw $s0, 4($sp)
move $v0, $a0 # check for base cases
ble $a0, 1, fibDone
move $s0, $a0 # get fib(n-1)
sub $a0, $a0, 1
jal fib
move $a0, $s0
sub $a0, $a0, 2 # set n-2
move $s0, $v0 # save fib(n-1)
jal fib # get fib(n-2)
add $v0, $s0, $v0 # fib(n-1)+fib(n-2)
fibDone:
lw $ra, ($sp)
lw $s0, 4($sp)
addu $sp, $sp, 8
jr $ra
.end fib

Double Recursion in Assembly works until secondary recursion becomes larger than the base case

I am trying to code a Assembly program that will ask for an integer and perform a recursive function: if n>5 f(n) = n*f(n-1)-f(n-3)+n-23 else n<=5 f(n)=15-2n I managed to get the first instance of recursion of the n*f(n-1)but when it goes for the second recursion of f(n-3) it performs the second portion improperly.
During the calculations, if I input 8 as the integer, the result should be 20 which I get but, when I input anything greater than 8 because then the second recursion hits an integer larger than 5 (the base case) I get an incorrect answer. Basically any input larger than 8 doesn't work
For example the correct answers are:
f(9) = 162
f(10) = 1602
f(11) = 17590
The answers I get
f(9)= 27
f(10)=22
f(11)=23
Here is my code:
```#data declarations: declare variable names used in program, storage allocated in RAM
.data
prompt1: .asciiz "\nEnter an Integer:\n" #Ending Index
message1: .asciiz "\nThe Solution is:\n"
answer: .word 0
#program code is contained below under .text
.text
.globl main #define a global function main
# the program begins execution at main()
main:
la $a0, prompt1 #load address of prompt1
li $v0, 4 #prepare print string
syscall
li $v0, 5 #prepare receive int
syscall
move $a0, $v0
addi $sp, $sp, -4
sw $ra, 0($sp)
jal Function
sw $v0, answer #move returned answer to a new memory
lw $ra, 0($sp)
addi $sp, $sp, 4
la $a0, message1 #load address of message1
li $v0, 4 #prepare print string
syscall
lw $a0, answer
li $v0, 1
syscall
jr $ra
############################################################################
# Procedure/Function Function1
# Description: recursive math function
# parameters: $a0 = value of n,
# return value: $v0 = answer
# registers to be used: $s3 and $s4 will be used.
############################################################################
Function:
addi $sp, $sp, -12 #adjust stack pointer
sw $ra, 8($sp) #save return address
sw $a0, 4($sp) #save n
sw $s0, 0($sp) #save immediate value (used for storing function(n-1))
li $t2, 15
slti $t0, $a0, 6
beq $t0, $zero, GreaterThanFive
LessThanFive:
add $t1, $a0, $zero
add $t1, $t1, $a0
sub $t2, $t2, $t1
move $v0, $t2
j Conclusion
GreaterThanFive:
addi $a0, $a0, -1
jal Function
move $s0, $v0
lw $a0, 4($sp)
addi $a0, $a0, -3
jal Function
lw $a0, 4($sp)
mul $t3, $a0, $s0
sub $t4, $t3, $v0
add $t5, $t4, $a0
addi $t6, $t5, -23
move $v0, $t6
Conclusion:
lw $s1,0($sp) # restore intermediate value
lw $a0,4($sp)
lw $ra,8($sp)
addi $sp,$sp,12 # restore stack
jr $ra #return to caller```

Error in MIPS assembler regarding fetch address not being aligned

having some trouble with an assignment, not looking for solution code, just some answers to why I keep encountering this error.
The program asks the user for 10 digits and then displays the resulting sum (using the stack and recursion).
I know from debugging that the read: portion works fine, but I get the error "Runtime exception at 0x0040005c: fetch address not aligned on word boundary 0x00000001". The error refers to the line in summation: lw $t0, 0($a0)
Not sure what is wrong since I only ever increment by 4 bytes. I've checked other similar questions but couldn't find any clarification. Any help would be greatly appreciated.
.data
A1: .space 40
input: .asciiz "please enter a number: "
Str: .asciiz "the sum is: "
.text
main:
li $s1, 0
la $t0, A1
addi $s0, $zero, 0
read:
beq $s1, 10, prep
li $v0, 4
la $a0, input
syscall
li $v0, 5
syscall
sw $v0, ($t0)
addi $t0, $t0, 4
addi $s1, $s1, 1
j read
prep:
la $a0, A1
addi $a1, $a0, 40
jal summation
summation:
subi $sp, $sp, 8
sw $ra, 4($sp)
lw $t0, 0($a0)
sw $t0, 0($sp)
sgt $t1, $a0, $a1
beq $t1, $zero, L1
addi $v0, $zero, 0
addi $sp, $sp, 8
jr $ra
L1:
addi $a0, $a0, 4
jal summation
lw $a0, 0($sp)
lw $ra 4($sp)
addi $sp, $sp, 8
add $v0, $a0, $v0
jr $ra

Recursive series MIPS isn't working as expected

I must implement a recursive series in MIPS, here is the high level code:
int suite(n)
{
if (n == 0) return 0;
else
return (suite(n-1) + 4*n);
}
I have several problems with my assembly code. The first one is that it doesn't give the expected result, as it adds 4 each time.
My second problem is that it doesn't end. I've used a recursive textbook example for a factorial.
Here's the assembly code:
.data
msg: .asciiz "Entrer un nombre : "
.text
.globl main
main:
#print msg
li $v0,4
la $a0,msg
syscall
#input prompt
li $v0,5
syscall
addi, $a0, $v0, 0
jal suite
suite:
addi $sp, $sp,-12
sw $a1, 8($sp)
sw $a0, 4($sp)
sw $ra, 0($sp)
addi $t0, $0, 1
slt $t0, $a0, $t0
beq $t0,$0 else
addi $sp, $sp, 12
li $v0, 1
syscall
add $v0, $0, $0
jr $ra
else:
add $a1, $a0, $a0
add $a1, $a1, $a1
addi $a0, $a0, -1
jal suite
lw $ra, 0($sp)
lw $a0, 4($sp)
lw $a1, 8($sp)
addi $sp, $sp, 12
add $a0, $v0, $a1
print:
li $v0, 1
syscall
add $v0, $0, $0
jr $ra
end:
Any help would be helpful.

Resources