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