MIPS 帮助:递归函数
MIPS Help: Recursive Functions
我正在尝试将此递归函数编码为 MIPS。
我的问题是我不确定如何执行递归步骤。
我很确定我做对了其余部分。
int recur(int n) {
if(n == 1 || n == 2) {
return 2;
} else {
return (n-4)+n*recur(n-2);
}
}
.data
promptMessage: .asciiz "Enter a number that is greater than or equal to 0: "
resultMessage: .asciiz "\nThe answer is: "
input: .word 0
answer: .word 0
.text
.globl main
main:
#Read the number from the user
li $v0, 4
la $a0, promptMessage
syscall
li $v0, 5
syscall
sw $v0, input
#Call the function
lw $a0, input
jal recur
sw $v0, answer
#Display result
li $v0, 4
la $a0, resultMessage
syscall
li $v0, 1
lw $a0, answer
syscall
.globl recur
recur:
addi $sp, $sp, -8
sw $a0, 0($sp)
sw $ra, 4($sp)
#Base Case if(n == 0 || n == 1) return 2;
li $v0, 2
beq $a0, $zero, DONE
beq $a0, 1, DONE
#RECURSIVE STEP
addi $a0, $a0, -2
jal recur
你做得很好。首先创建 C 代码。你们很亲密。
我不得不添加计算步骤和函数结尾代码。
此外,还有一个错误,在 main 打印数字后,有 no 系统调用 10(退出),因此代码会失败并无限递归。
我稍微修改了 C 代码,使其与 MIPS 代码更兼容。
为了好玩和便于测试,我将 main 更改为循环并重新提示,直到它得到一个负数。
我已经清理并测试了代码,添加了注释[请原谅不必要的样式清理]:
.data
# NOTE: these should appear first to maintain alignment to a 4 byte boundary
# (or the .align 4 will do it) otherwise, the lw/sw ops can fail on an
# alignment exception
.align 4
input: .word 0
answer: .word 0
promptMessage: .asciiz "Enter a number that is greater than or equal to 0 (-1 to stop): "
resultMessage: .asciiz "\nThe answer is: "
nl: .asciiz "\n"
.text .globl
main:
# prompt user
li $v0,4
la $a0,promptMessage
syscall
# Read the number from the user
li $v0,5
syscall
sw $v0,input
# negative value means stop
# NOTE: added this
bltz $v0,main_exit
# Call the function
lw $a0,input
jal recur
sw $v0,answer
# Display result message
li $v0,4
la $a0,resultMessage
syscall
# display number
li $v0,1
lw $a0,answer
syscall
# output newline
li $v0,4
la $a0,nl
syscall
# NOTE: this was added to allow multiple tries, but without it, there was
# the bug below
j main
# BUG: syscall to exit here was _missing_ so got fallthrough into "recur"
# causing the stack to overflow
main_exit:
li $v0,10
syscall
.globl recur
# recur -- recursion
#
# arguments:
# a0 -- the "n" value
#
# pseudo code:
# * int
# * recur(int n)
# * {
# * int r;
# *
# * if (n == 1 || n == 2) {
# * return 2;
# * }
# *
# * r = recur(n - 2);
# *
# * return (n - 4) + (n * r);
# * }
recur:
addi $sp,$sp,-8
sw $a0,0($sp)
sw $ra,4($sp)
# Base Case if(n == 0 || n == 1) return 2;
li $v0,2
beq $a0,$zero,recur_done
beq $a0,1,recur_done
# RECURSIVE STEP
addi $a0,$a0,-2 # n -= 2
jal recur
lw $a0,0($sp) # we need "n" back (not (n - 2))
# NOTE: this calculation was missing
mul $v0,$v0,$a0 # r *= n (i.e. (n * r))
addi $a0,$a0,-4 # n -= 4 (i.e. (n - 4))
add $v0,$v0,$a0 # sum them
# NOTE: this is the standard reversal for this function's stack prolog
recur_done:
lw $a0,0($sp)
lw $ra,4($sp)
addi $sp,$sp,8
jr $ra
我正在尝试将此递归函数编码为 MIPS。
我的问题是我不确定如何执行递归步骤。
我很确定我做对了其余部分。
int recur(int n) {
if(n == 1 || n == 2) {
return 2;
} else {
return (n-4)+n*recur(n-2);
}
}
.data
promptMessage: .asciiz "Enter a number that is greater than or equal to 0: "
resultMessage: .asciiz "\nThe answer is: "
input: .word 0
answer: .word 0
.text
.globl main
main:
#Read the number from the user
li $v0, 4
la $a0, promptMessage
syscall
li $v0, 5
syscall
sw $v0, input
#Call the function
lw $a0, input
jal recur
sw $v0, answer
#Display result
li $v0, 4
la $a0, resultMessage
syscall
li $v0, 1
lw $a0, answer
syscall
.globl recur
recur:
addi $sp, $sp, -8
sw $a0, 0($sp)
sw $ra, 4($sp)
#Base Case if(n == 0 || n == 1) return 2;
li $v0, 2
beq $a0, $zero, DONE
beq $a0, 1, DONE
#RECURSIVE STEP
addi $a0, $a0, -2
jal recur
你做得很好。首先创建 C 代码。你们很亲密。
我不得不添加计算步骤和函数结尾代码。
此外,还有一个错误,在 main 打印数字后,有 no 系统调用 10(退出),因此代码会失败并无限递归。
我稍微修改了 C 代码,使其与 MIPS 代码更兼容。
为了好玩和便于测试,我将 main 更改为循环并重新提示,直到它得到一个负数。
我已经清理并测试了代码,添加了注释[请原谅不必要的样式清理]:
.data
# NOTE: these should appear first to maintain alignment to a 4 byte boundary
# (or the .align 4 will do it) otherwise, the lw/sw ops can fail on an
# alignment exception
.align 4
input: .word 0
answer: .word 0
promptMessage: .asciiz "Enter a number that is greater than or equal to 0 (-1 to stop): "
resultMessage: .asciiz "\nThe answer is: "
nl: .asciiz "\n"
.text .globl
main:
# prompt user
li $v0,4
la $a0,promptMessage
syscall
# Read the number from the user
li $v0,5
syscall
sw $v0,input
# negative value means stop
# NOTE: added this
bltz $v0,main_exit
# Call the function
lw $a0,input
jal recur
sw $v0,answer
# Display result message
li $v0,4
la $a0,resultMessage
syscall
# display number
li $v0,1
lw $a0,answer
syscall
# output newline
li $v0,4
la $a0,nl
syscall
# NOTE: this was added to allow multiple tries, but without it, there was
# the bug below
j main
# BUG: syscall to exit here was _missing_ so got fallthrough into "recur"
# causing the stack to overflow
main_exit:
li $v0,10
syscall
.globl recur
# recur -- recursion
#
# arguments:
# a0 -- the "n" value
#
# pseudo code:
# * int
# * recur(int n)
# * {
# * int r;
# *
# * if (n == 1 || n == 2) {
# * return 2;
# * }
# *
# * r = recur(n - 2);
# *
# * return (n - 4) + (n * r);
# * }
recur:
addi $sp,$sp,-8
sw $a0,0($sp)
sw $ra,4($sp)
# Base Case if(n == 0 || n == 1) return 2;
li $v0,2
beq $a0,$zero,recur_done
beq $a0,1,recur_done
# RECURSIVE STEP
addi $a0,$a0,-2 # n -= 2
jal recur
lw $a0,0($sp) # we need "n" back (not (n - 2))
# NOTE: this calculation was missing
mul $v0,$v0,$a0 # r *= n (i.e. (n * r))
addi $a0,$a0,-4 # n -= 4 (i.e. (n - 4))
add $v0,$v0,$a0 # sum them
# NOTE: this is the standard reversal for this function's stack prolog
recur_done:
lw $a0,0($sp)
lw $ra,4($sp)
addi $sp,$sp,8
jr $ra