I am trying to find the GCD of two numbers with recursion.
This code is what I've done so far but apparently it gets into an infinite loop and i can't understand why and how to solve this problem.
I would appreciate some help
.data
string1: .asciiz "Enter the first number: "
string2: .asciiz "Enter the second number: "
string3: .asciiz "GCD is : "
.text
li $v0,4
la $a0,string1
syscall
li $v0, 5
syscall
add $s0,$v0,$zero #s0 = first number
li $v0,4
la $a0,string2
syscall
li $v0, 5
syscall
add $s1,$v0,$zero #s1= second number
slt $t0,$s0,$s1
beq $t0,$zero,L # if first number < second number , swap
add $t1,$s0,$zero
add $s0,$s1,$zero
add $s1,$t1,$zero
L:
add $a0,$s0,$zero # put first number in $a0 as input argument
add $a1,$s1,$zero # put second number in $a1 as input argument
jal GCD
GCD:
addi $sp,$sp,-4
sw $ra,0($sp)
bne $a1,$zero,L1 # base case condition
add $v0,$zero,$a0 # if base case is true
addi $sp,$sp,4
jr $ra
L1:
div $a0,$a1
add $a0,$a1,$zero
mfhi $a1
jal GCD
lw $ra,0($sp)
addi $sp,$sp,4
jr $ra
add $s3,$v0,$zero # put result in $s3
li $v0,4
la $a0,string3
syscall
li $v0,1
add $a0,$s3,$zero
syscall
So your program starts execution at the beginning of the .text segment and continues straight onto the line jal GCD after the L label.
Next your program jumps to the GCD label where it executes until the jr $ra which makes it return to the jal which has as its next instruction of course GCD. This causes the infinite loop.
So the problem here is that you have inserted the GCD function in the middle of your main function. Generally speaking it is always an error to jal to the next line.
So you should move the definition of GCD elsewhere and consider what it is that you would like to run after returning from this function.
Related
I want to write a program that calculates the square of n using recursion based on the equation n^2 = (n - 1)^2 + 2(n - 1) + 1 But I don't know how to write the nonbasecase: part. Can anyone help?
A python program would be
def square(n) {
if (n==0):
return 0
else:
return square(n-1) + 2*(n-1) + 1
}
Here is what I got so far.
start:
li $a0, 0x0003 #$a0 contains the number to be squared
jal square # recursive call
square:
subi $sp, $sp, 8 # decrement the stack pointer $sp
sw $ra, 4($sp) # push the return address register $ra
sw $a0, 0($sp) # push argument register $a0
li $t0, 0x0001 # load $t0 with 1 as part of test for base case
bne $a0, $t0, nonbasecase # branch if not the base case
li $v0, 0x0001 # return base result in $v0
addi $sp, $sp 8 # recover stack space
jr $ra # jump to return address in $ra
nonbasecase:
#not sure how to write when it is not the base case
jr $ra # jump to contents of return address register $ra
Write the function so that it inputs n2 and n and returns n2+2*n+1 and n+1.
I am writing a program that accepts a user given strings and will output 1 if it is a palindrome or 0 if it isn't. It has to use recursion, however I am having trouble figuring out how to format the jal and jr statements so that recursion works properly.
main:
la $a0, askForString #simple text asking for user input
li $v0, 4
syscall
li $v0, 8
la $a0, userInput #points a0 to space allocated to get user input
li $a1, 41 #allows the user to enter input up to 40 characters
syscall
la $a0, userInput
li $v0, 4
syscall
lw $s0, userInput
j palindrome
palindrome:
la $a1, userInput
addu $a1,$a1,$s1
lbu $a0,($a1) # read the character in $s1 spot of the user inputted word
addi $sp, $sp, -4
sw $a0, 0($sp) #add the specific character to the stack so it can be looked at later
addi $s1, $s1, 1 #advance the count to look at the next character
jal palindrome
lw $t0, 0($sp) #load the last letter of the user given word from the stack
addi $sp, $sp, 4
la $a1, userInput
addu $a1,$a1,$s2
lbu $a0,($a1) # read the character in $s2 spot of the user inputted word
addi $s2, $s2, 1 #advance the count to look at the next character
bne $a0, $t0, fail #if the letters are not equal, print 0, not a palindrome
jr $ra
success:
la $a0, '1'
li $v0, 11
syscall
j end
fail:
la $a0, '0'
li $v0, 11
syscall
j end
end:
li $v0, 10 #op code to exit the program
syscall
I know the palindrome part of the program almost definitely does not work and has no way of knowing where the end of the word is, but if anyone could me with simply the recursion part that would be extremely helpful.
.data
input:.space 80 #buffer space for input
built:.space 80 #buffer space for built string from looping
#string values to call when printing
message: .asciiz "Please enter a string:"
newline: .asciiz "\n"
ispaly: .asciiz "\n This is a palindrome"
notpaly: .asciiz "\n This is not a palindrome"
.text
main:
la $a0, message # user input message
li $v0, 4 #mips to print string
syscall #call return values
la $a0, input #users input
li $a1, 80 #allocating space for the buffer of size 80
li $v0, 8 #reading the buffer
syscall #call return values
secondinput:
la $t1,built #creating a new buffer string while going through the loop
loop:
lb $t5,($a0) #loading the byte into the buffer
beq $t5, 10, check # if it has a new line
bgt $t5, 47, digittest #and has value greater then ascii 47
jal dontbuild #if it is not then we increment to next character
digittest:
blt $t5, 58, dobuild #proceeding from above, if it is less then ascii 58(digits)
bgt $t5, 64, capital #and greater then ascii 64 we dont build it into our new buffer(built)
jal dontbuild #jump to dontbuild function
capital:
blt $t5, 91, dobuild #buffer being (built) is less than ascii 91 its a capital letter
bgt $t5, 96, punctuation #if its greater then 96 its is a lowercase
j dontbuild #jump to dontbuild
dobuild:
bgt $t5, 96, makelow #built value byte is already lowercase
j lower #go to lower function
punctuation:
blt $t5,123, dobuild #buffer being built has a value less then 123 and passed previous functions it is a capital and we make it lower
j dontbuild #otherwise we dont add to buffer(built)
makelow:
addi $t5,$t5, -32 #if value is lower subtract 32 to make it capital
j lower #jump to lower function and increment
lower:
sb $t5,($t1) #store the byte so it does not get modified
addi $a0,$a0, 1 #increment for comparison
addi $t1,$t1,1 #increment for comparison
j loop #go back up to loop
dontbuild:
addi $a0,$a0,1 #increment to next character
j loop #jump to loop
check:
la $t4, built #buffer that was built
sb, $zero,($a0) #store the byte in argument
addi $t1,$t1,-1 #decrement from the end of our $t1 register
loop2:
lb $t3,($t4) #load byte into temporary register
lb $t2,($t1) #load byte into temporary register
beq $t3,$t2,next #check if each byte is equal
j notp #if they are not go to not a palindrome
next:
jal test #if they are equal
addi $t4,$t4,1 #increment through the string
addi $t1,$t1,-1 #decrement through the string
j loop2 #go through the loop
j notp #if it runs into a non equal value its not a palindrome
test:
beq $t4,$t1,isp #if all values are equal it calls palindrome
addi $t1,$t1,-1
beq $t4,$t1,isp #do we need to check any other values
addi $t1,$t1,1
jr $ra #return to os
isp:
la $a0, input # the users input
li $v0, 4
syscall #call return values
li $v0, 4 #print a new line
la $a0, newline
syscall
la $a0,built
li $v0, 4
syscall
la $a0,ispaly #string that it is a palindrome
syscall #call return values
j exit #end
notp:
la $a0, input #users input
li $v0, 4
syscall #call return values
li $v0, 4 #print a new line
la $a0, newline
syscall
la $a0,built
li $v0, 4
syscall
la $a0, notpaly #string that it is not a palindrome
syscall #call return values
j exit
exit:
li $v0, 10 #end program
syscall #call return values
This code compiles but I am having some errors with my output.
At the line addi $t5,$t5, -32 to make an uppercase value lowercase. It makes everything uppercase.
Here is a test output.
Please enter a string:A man, a plan, a canal --Panama!
A man, a plan, a canal --Panama!
AMANAPLANACANALPANAMA
This is a palindrome
The output that I need is
amanaplanacanalpanama
In ascii characters you have to add 32 to go from uppercase to lowercase
for example A=65 so 65+32= 97 which = a.
When i try to do the opposite in my code
subi $t5,$t5, 32
I get the same output with uppercase values
If i change it to
addi $t5,$t5, 32
The output is
Please enter a string:A man, a plan, a canal --Panama!
A man, a plan, a canal --Panama!
A■■■■■■■■■■■■■■■■P■■■■■
This is not a palindrome
Basically every lowercase value is a square.
And the last issue is that my test loop is not seen as recursion. Is this true?
In ascii characters you have to add 32 to go from uppercase to
lowercase for example A=65 so 65+32= 97 which = a.
You're substracting 32 in both cases, not adding. addi $t5,$t5, -32 (adding -32) is the same as subi $t5,$t5, 32 (substracting 32).
Basically every lowercase value is a square.
Because you're adding 32 to lowercased characters and you end up with non-printable characters, which are shown as squares.
And the last issue is that my test loop is not seen as recursion. Is
this true?
I don't see where test is looped. Anyways, you have no recursion in your code, only loops. Recursion is when a function calls itself and you have no functions in your code.
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.
I'm having trouble dealing with stacks recursively in MIPS. I get the concept, but my program isn't reacting as I mean it to.
My goal is to take user input as n and print the Fibonacci number at n. What I have so far is below.
(I'm fairly certain the problem is in the actual calculation of the number in the fib function.) Thanks for any help! :)
.text
main:
# Prompt user to input non-negative number
la $a0,prompt
li $v0,4
syscall
li $v0,5
syscall
move $t2,$v0
# Call function to get fibonnacci #n
move $a0,$t2
move $v0,$t2
jal fib
move $t3,$v0
# Output message and n
la $a0,result
li $v0,4
syscall
move $a0,$t2
li $v0,1
syscall
la $a0,result2
li $v0,4
syscall
move $a0,$t3
li $v0,1
syscall
la $a0,endl
li $v0,4
syscall
# End program
li $v0,10
syscall
fib:
# Compute and return fibonacci number
beqz $a0,zero
beq $a0,1,one
sub $sp,$sp,4
sw $ra,0($sp)
sub $a0,$a0,1
jal fib
lw $ra,0($sp)
add $sp,$sp,4
sub $t8,$v0,2 # n - 2
sub $t9,$v0,1 # n - 1
add $v0,$t8,$t9 # add n-2,n-1
jr $ra # decrement/next in stack
zero:
li $v0,0
jr $ra
one:
li $v0,1
jr $ra
.data
prompt: .asciiz "Enter a non-negative number: "
result: .asciiz "F_"
result2: .asciiz " = "
endl: .asciiz "\n"
Example runs:
Enter a non-negative number: 5
F_5 = -29
Enter a non-negative number: 6
F_6 = -61
Correct runs:
Enter a non-negative number: 5
F_5 = 5
Enter a non-negative number: 6
F_6 = 8
Here is a properly working code:
.text
main:
# Prompt user to input non-negative number
la $a0,prompt
li $v0,4
syscall
li $v0,5 #Read the number(n)
syscall
move $t2,$v0 # n to $t2
# Call function to get fibonnacci #n
move $a0,$t2
move $v0,$t2
jal fib #call fib (n)
move $t3,$v0 #result is in $t3
# Output message and n
la $a0,result #Print F_
li $v0,4
syscall
move $a0,$t2 #Print n
li $v0,1
syscall
la $a0,result2 #Print =
li $v0,4
syscall
move $a0,$t3 #Print the answer
li $v0,1
syscall
la $a0,endl #Print '\n'
li $v0,4
syscall
# End program
li $v0,10
syscall
fib:
# Compute and return fibonacci number
beqz $a0,zero #if n=0 return 0
beq $a0,1,one #if n=1 return 1
#Calling fib(n-1)
sub $sp,$sp,4 #storing return address on stack
sw $ra,0($sp)
sub $a0,$a0,1 #n-1
jal fib #fib(n-1)
add $a0,$a0,1
lw $ra,0($sp) #restoring return address from stack
add $sp,$sp,4
sub $sp,$sp,4 #Push return value to stack
sw $v0,0($sp)
#Calling fib(n-2)
sub $sp,$sp,4 #storing return address on stack
sw $ra,0($sp)
sub $a0,$a0,2 #n-2
jal fib #fib(n-2)
add $a0,$a0,2
lw $ra,0($sp) #restoring return address from stack
add $sp,$sp,4
#---------------
lw $s7,0($sp) #Pop return value from stack
add $sp,$sp,4
add $v0,$v0,$s7 # f(n - 2)+fib(n-1)
jr $ra # decrement/next in stack
zero:
li $v0,0
jr $ra
one:
li $v0,1
jr $ra
.data
prompt: .asciiz "This program calculates Fibonacci sequence with recursive functions.\nEnter a non-negative number: "
result: .asciiz "F_"
result2: .asciiz " = "
endl: .asciiz "\n"
Hope to be usefull
Adel Zare
adel.zare.63 [at] gmail [dot] com
You appear to have misunderstood the algorithm (or just implemented it incorrectly). What you're doing is this:
int fib(int n) {
if (n == 0)
return 0;
else if (n == 1)
return 1;
int ret = fib(n - 1);
return (ret - 2) + (ret - 1);
}
What you should be doing is this:
int fib(int n) {
if (n == 0)
return 0;
else if (n == 1)
return 1;
return fib(n - 1) + fib(n - 2);
}