MIPS Assembly - Recursive Function - recursion

I'm trying to make a programm that calculates the greatest common divisor between two numbers using a recursive function. The problem is the programm seems to calculate the right answer at the first time it reaches the "exitmdc" function, after that it should return to the main function but instead it is returning to the GCD function (called mdc because it's in portuguese). The result changes because of that. I don't know what's causing this issue because the recursive functions that I've seen seem to work this way.
C++ Function:
int rec_mdc(int x, int y) {
if(x==y)
return x;
else if (x < y)
return rec_mdc(x, y-x);
else
return rec_mdc(x, x–y);
}
}
My Assembly programm:
.data
InformaPrimeiro: .asciiz "Informe um numero: "
InformaSegundo: .asciiz "\nInforme um segundo numero: "
novaLinha: .asciiz "\n"
.text
main:
jal insereNumero
jal mdc
add $a0,$v0,$zero
li $v0,1
syscall
li $v0, 10
syscall
insereNumero:
li $v0,4 # Informa ao computador que uma string/texto está sendo impresso
la $a0, InformaPrimeiro # Carrega o endereço no registrador de argumentos
syscall # Chamada do sistema
#Escolha do usuário:
li $v0,5 # 5 corresponde aos inteiros
syscall
move $a1, $v0
li $v0,4
la $a0, InformaSegundo
syscall
li $v0,5
syscall
move $a2, $v0
jr $ra
mdc:
addi $sp, $sp, -12 # colocaremos 3 itens na pilha
sw $a1, 0 ($sp) # salvamos o argumento n
sw $a2, 4 ($sp) # salvamos o argumento n2
sw $ra, 8 ($sp) # salvamos o endereço de retorno
beq $a1,$a2,exitmdc
blt $a1, $a2, if
bgt $a1, $a2, else
if:
sub $a2, $a2, $a1
jal mdc
else:
sub $a1, $a1, $a2
jal mdc
exitmdc:
add $v0, $zero, $a1
lw $ra, 8($sp)
lw $a2, 4($sp)
lw $a1, 0($sp)
addi $sp, $sp, 12
jr $ra
The "insereNumero" function is just for the user input

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

Mips Recursive Assignment

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

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```

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.

Recursive assembly code stack pointer issues. (mips)

def count_partitions(n, m):
if n == 0:
return 1
elif n < 0:
return 0
elif m == 0:
return 0
else:
l = count_partitions(n, m-1) + count_partitions(n-m, m)
return l
Trying to convert this python code into MIPS assembly. My assembly code does its job but after it gets to the right answer, it continues and gets to absurd numbers.
I tried debugging with mars.jar and found out that my stack pointer didnt get updated at one point. Thanks a lot.
My code:
.data
prompt1: .asciiz "\Enter an integer to partition (n): "
prompt2: .asciiz "\Enter an integer for size of the partition (m): "
default: .asciiz "\nstuff "
.text
main:
la $a0, prompt1
li $v0,4
syscall
li $v0, 5
syscall
move $t0, $v0 # $t0 = n
la $a0, prompt2
li $v0,4
syscall
li $v0, 5
syscall
move $t1, $v0 # $t1 = m
add $a0, $t0, $zero
add $a1, $t1, $zero
addi $sp,$sp,-4
sw $ra,0($sp)
jal count_partitions
lw $ra,0($sp)
addi $sp,$sp,4
move $a0,$v0
li $v0, 1
syscall #prints the default
li $v0, 10
syscall
count_partitions:
addi $sp,$sp,-16
sw $s1,12($sp)
sw $a1,8($sp)
sw $a0,4($sp)
sw $ra,0($sp)
bne $a0,$zero,case1
addi $v0,$v0,1
j return
case1:
slti $t0,$a0,0
beq $t0,$zero,case2
j return
case2:
bne $a1,$zero,case3
j return
case3:
addi $a1,$a1,-1
jal count_partitions
addi $t7,$zero,1
mult $v0,$t7
mflo $s1
addi $a1,$a1,1
sub $a0,$a0,$a1
jal count_partitions
addi $t7,$zero,1
mult $v0,$t7
mflo $t2
add $v0,$s1,$t2
return:
lw $ra,0($sp)
lw $a0,4($sp)
lw $a1,8($sp)
lw $s1,12($sp)
addi $sp,$sp,16
jr $ra

Resources