Recursion in Mips - recursion

I'm currently trying to figure out how to code a function of finding the lowest integer in MIPS following this algorithm...
int Min( int[] A, int low, int high)
{ if (low== high) return A[low];
int mid = (low+high)/2;
int min1 = Min( int[] A, low, mid);
int min2 =Min( int[] A, mid +1, high);
if(min1>min2) return min2;
return min1;
}
I'm receiving problems as I attempt to code this in MIPS. Here is my current MIPS code. The user inputs up to 6 integers which are stored in an array. The registers $a0, $a1, and $a2 are used as arguments for the function.
$a0 = int[]A
$a1 = int low //index
$a2 = int high //index
Here is the recursion function...
min:
bne $a1, $a2, recur
mul $t4, $a1, 4
add $a0, $a0, $t4
lw $v1, 0($a0)
jr $ra
# recursion start
recur:
addiu $sp, $sp, -12 #reserve 12 bytes on stack
sw $ra, 0($sp) #push return address
# mid = (low+high)/2 t0 = mid t1= min1 t2=min2 t3 = mid+1
add $t0, $a1, $a2 # t0 = low + high
div $t0, $t0, 2 # t0 = (low+high)/2
# mid1 = min(int[]A,low,mid)
min1:
sw $a2, 4($sp) #push high
addi $t3, $t0, 1 # mid+1
sw $t3, 8($sp) #store mid+1
move $a2, $t0 #change high to mid
jal min #compute
# check
move $t1, $v1 #set up the min1 = return value
# mid2 = min(int[]A,mid+1,high)
min2:
lw $a2, 4($sp) #reload high prior call
lw $a1, 8($sp) #change low to mid+1
jal min #compute
move $t2, $v1 #set as the min2 = return value
confirm:
# return mid2 if mid1 > mid2
bgt $t1, $t2, returnMid2
# else return mid1
move $v1, $t1
j minFinal
returnMid2:
move $v1, $t2
minFinal:
lw $ra, 0($sp)
addiu $sp, $sp, 12 #release stack
jr $ra
The problem is whatever combination of integers I input during the program, I never get the minimum value but rather the number "543976553". I've been looking over my code and notes and I still don't have a clue.

For mid1, try putting the return value on the stack and then moving it to $t1 AFTER mid2 is called. Then compare $v0 with $t1 instead of comparing $t1 with $t2

When using the div command in MIPS, doesn't one need to acquire the quotient from $LO ?
thus your logic for (high+low)/2 might look something like
add $t0, $a1, $a2 # t0 = low + high
addi $t5, $zero, 2 # t5=2
div $t0, $t5 # LO = t0/t5, HI = t0%t5
addi $t0, $LO, 0 # t0 = LO (t0/t5)
some of those lines are written just how I learned to do MIPS but you may have a different style for loading immediate values into a register.
I also can't promise this will fix everything, but at first glance, that is something I noticed.

Related

MIPS recursive function not working properly

I'm doing a factorial recursive function in MIPS. Here is the code:
fact: #a1 = n a2 = res
addi $t1,$zero,1
beq $a1,$t1,end # if n == 1 return res
#else
mul $a2,$a2,$a1
subi $a1,$a1,1
jal fact
end:
sb $a2,res
jr $ra
The problem is, this code only works when i write j fact instead of jal fact, with jal fact the code run infinitely for some reason.
fact: #a1 = n a2 = res
addi $t1,$zero,1
beq $a1,$t1,end # if n == 1 return res
#else
addi $sp, $sp, 8
sw $a1, 0($sp) # in the top of the stack store the argument you called fact
sw $ra, 4($sp) # ra holds the return adress ( I do not know whether you know it)
mul $a2,$a2,$a1
subi $a1,$a1,1
jr $ra
jal fact
lw $a1, 0($sp) # load the value from memory adress that the top stack pointer shows to back to the register a1
lw $ra, 4($sp)
addi $sp, $sp, 8 # delete current top , top-1 from the stack
jr $ra
end:
sb $a2,res
jr $ra

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

implementing recursive function in MIPS

I'm a bit confused on how to compile recursive functions in mips:
the following question was in a previous exam in my computer organization course:
the question asks us to compile:
int sum(int n){
if (n <= 1)
return 1;
else
return n + sum( sum(n-1) – sum(n-2) );
}
My attempt at tackling this problem:
sum: bgt $a0, 1, sum_recursive
add $v0, $0,1
jr $ra
sum_recursive: sub $sp, $sp, -12
sw $ra ,0($sp) # storing the return address
sw $a0, 4($sp) # storing the argument n
addi $a0, $a0, -1 # n-1
jal sum
sw $v0, 8($sp) # the return value of sum(n-1)
lw $a0, 4($sp) # a0=n
addi $a0, $a0, -2 # a0=n-2
jal sum
lw $t0, 8($sp) # the return value of sum (n-1)
sub $v0, $t0, $v0 # sum(n-1) - sum (n-2)
lw $a0, 4($sp)
add $a0, $v0, $0 # a0=sum (n-1)-sum (n-2)
jal sum
lw $a0, 4($sp)
add $v0, $v0, $a0 # $v0 = n+ sum (sum (n-1)- sum(n-2))
lw $ra, 0($sp)
lw $a0, 4 ($sp)
add $sp, $sp, 12
jr $ra
Thank you

Recursive function using MIPS assembly

I'm having some trouble on an assignment and would appreciate some help. I'm not asking for the answer, I prefer to put two and two together to figure it out myself, but I know so little about MIPS its hard for me to know where to start.
Here is what I started with
.data
.text
main:
addi $sp, $sp, -16 #prepare stack for 4 items
sw $s0, 0($sp)
sw $s1, 4($sp)
sw $s2, 8($sp)
sw $ra, 12($sp)
move $s0, $a0
move $s1, $a1
add $s2, $s0, $s1 #add two previous numbers and store result in $s2
move $v0, $s2 #put answer into $v0
lw $s0, 0($sp)
lw $s1, 4($sp)
lw $s2, 8($sp)
lw $ra, 12($sp)
addi $sp, $sp, 16
jr$ra
Essentially we are to use a recursive function to calculate the fibonacci numbers and a loop to print out the first 10 numbers of the fibonacci sequence.
I have looked up many examples but they all use instructions that we haven't learned yet so I can't make sense of it and I can only assume we aren't expected to use them. In the code above I'm essentially creating a stack to store the $ra along with three values, the two numbers to be added and the sum. Part of my problem is understanding where the function starts and ends and what the totality of the work being done is.
We were also given that to print you use the following
li $v0, 1
move $a0, $s0
syscall
Am I correct in thinking this is printing the value stored in $v0?
Here is the code for your function. I know you are not looking for the answer but sometimes looking for an example and seeing how it works gets you more easily to the point where you understand how it really works.
.data
msg1: .asciiz "Give a number: "
.text
.globl main
main:
li $v0, 4
la $a0, msg1
syscall # print msg
li $v0, 5
syscall # read an int
add $a0, $v0, $zero # move to $a0
jal fib # call fib
add $a0, $v0, $zero
li $v0, 1
syscall
li $v0, 10
syscall
fib:
# $a0 = y
# if (y == 0) return 0;
# if (y == 1) return 1;
# return fib(y - 1) + fib(y - 2);
#save in stack
addi $sp, $sp, -12
sw $ra, 0($sp)
sw $s0, 4($sp)
sw $s1, 8($sp)
add $s0, $a0, $zero
addi $t1, $zero, 1
beq $s0, $zero, return0
beq $s0, $t1, return1
addi $a0, $s0, -1
jal fib
add $s1, $zero, $v0 # $s1 = fib(y - 1)
addi $a0, $s0, -2
jal fib # $v0 = fib(n - 2)
add $v0, $v0, $s1 # $v0 = fib(n - 2) + $s1
exitfib:
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
return1:
li $v0,1
j exitfib
return0:
li $v0,0
j exitfib
Like Gusbro said in order to use recursion in mips you will have to do 2 things. jal (jump and link) to the name of the function but first always store the return address into a stack, $ra, so in the future if you want to return back to the beginning you will be able to using jr $ra. If you don't save a return address and try to access it via jr you will most likely get an invalid program counter error.
Here goes some hints:
You have to write a recursive function, but you are not writing a function at all.
To write this function in MIPS assembler I suggest you first write it in a higher level language (C).
So it would go something like this:
int fib(int n)
{
if(n == 0 or n == 1)
return n;
else return fib(n-1) + fib(n-2);
}
The first line checks whether you are in a base case of the recursion (n=0 or n=1). If thats the case, fib(n) returns n.
Otherwise the recursion step goes which returns the sum of fib(n-1) plus fib(n-2).
So you will have to write a function, define the input/output parameters (which register will held n and which will return fib(n).
The manually compile the C code.
To start a function, just add a label
fib:
then put your stack management code there.
then translate the IF-THEN-ELSE to MIPS assemble.
to issue the recursive call, use jal instruction.
Before returning from the function with jr $ra restore the saved values from the stack.
Your main program will load the input parameter (the register used for input argument n), then jal fib.
This explains how to implement the Fibonacci function in MIPS as well as how to translate a MIPS function back to equivalent C code, it's well detailed : Fibonacci function in MIPS by illinois.edu
The code for the base case:
fib:
bgt $a0, 1, recurse
move $v0, $a0
jr $ra
Convert the code for the base case.
fib:
bgt $a0, 1, recurse
move $v0, $a0
jr $ra
Save callee- and caller-saved registers on the stack.
recurse:
sub $sp, $sp, 12 # We need to store 3 registers to stack
sw $ra, 0($sp) # $ra is the first register
sw $a0, 4($sp) # $a0 is the second register, we cannot assume $a registers will not be overwritten by callee
Call fib recursively:
addi $a0, $a0, -1 # N-1
jal fib
sw $v0, 8($sp) # store $v0, the third register to be stored on the stack so it doesn’t get overwritten by callee
Call fib recursively again:
lw $a0, 4($sp) # retrieve original value of N
addi $a0, $a0, -2 #N-2 jal fib
Write a recursive version of π‘Ÿadd() in C or C++, then use this program to develop a MIPS
program that gets as input two integers 0<π‘Ž ≀255, and 0<𝑏 ≀255, and returns the
result of π‘Ÿadd(π‘Ž,𝑏) in $v1.

Mips recursion sum of digits

So I understand the logic behind how to calculate the sum of digits. I was just wondering whether this recursive function is correct. Assume that the user already entered the number which he or she wants the digit sum for and is stored in $v0.
Sum2:
li $s0, 0
move $a1, $v0
li $s1, 0
li $s2, 10
# I am adjusting the stack frame size to store 3 words
addi $sp, $sp,-12
# These are the sum value, the return address, and the number
sw $s1, 0($sp)
sw $ra, 4($sp)
sw $a1, 8($sp)
Loop2: bne $s0, $a1, SUM3
move $a0, $s1
li $v0, 1
syscall
lw $s1, 0($sp)
lw $ra, 4($sp)
lw $a1, 8($sp)
addi $sp, $sp 12
jr $ra
SUM3:
div $t0, $a1, $s2
mfhi $t0
add $s1, $s1, $t0
div $t1, $a1, $s2
mflo $a1
j Loop2
If the logic isn't clear I am first checking to see if the number doesn't equal zero and if it doesn't I will then get the modulus of the number divided by 10 and add it to the sum which is initially 0 and then divide the user input number by 10 and continue to call the function till the number eventually becomes zero. I also had one quick last question. In Mips would a recursive function or iterative function execute faster?
Your implementation corresponds to something like this:
int sum_digits(int n) {
int res = 0;
while (n != 0) {
res += n % 10;
n /= 10;
}
return res;
}
Actually you're just printing the result rather than returning it, but that's beside the point. It's clearly an iterative function.
A recursive implementation would look something like this:
int sum_digits(int n) {
return (n >= 10) ? ((n % 10) + sum_digits(n / 10)) : (n % 10);
}
I'll leave it to you to translate that into MIPS assembly now that you know what the algorithm looks like.
Proper implementation of recursion to do sum of digits:
.data
n: .word 1965
s: .word 0
.text
main:
lw $t0,n
addi $t1,$zero,10
add $t4,$zero,$zero #the result
recursion:
div $t0,$t1 #n/10 and n%10
mflo $t0 #n=n/10
mfhi $t3 #digit=n%10
add $t4,$t4,$t3 #s=s+digit
bne $t0,$zero,recursion #if n!=0
end:
sw $t4,s
li $v0,10
syscall

Resources