Assembly MIPS汇编-尝试编写递归程序来计算nCr(组合)
我正在尝试创建一个mips汇编程序来递归计算 我已经编写了整个程序,包括一个驱动程序,但它不能正常运行。我所有的输入和输出都工作,但我的递归算法返回的是疯狂的数字。例如,nCr==268501120,而不是10 更新代码: 这里只是我算法的一个片段:Assembly MIPS汇编-尝试编写递归程序来计算nCr(组合),assembly,recursion,mips,combinations,ncr,Assembly,Recursion,Mips,Combinations,Ncr,我正在尝试创建一个mips汇编程序来递归计算 我已经编写了整个程序,包括一个驱动程序,但它不能正常运行。我所有的输入和输出都工作,但我的递归算法返回的是疯狂的数字。例如,nCr==268501120,而不是10 更新代码: 这里只是我算法的一个片段: nCk: sub $sp, $sp, 16 #allocate the needed space in stack. sw $ra, 0($sp) #save return address in first position sw $t3, 4($
nCk:
sub $sp, $sp, 16 #allocate the needed space in stack.
sw $ra, 0($sp) #save return address in first position
sw $t3, 4($sp) #save n in the stack
sw $t4, 8($sp) #save k in the stack
sub $t3, $t3, 1 #Subtract one from n
sub $t4, $t4, 1 #Subtract one from k
jal checkBounds #Check for end of recursion.
sw $v0, 12($sp) #copy returned 1 or 0 into stack.
lw $t3, 4($sp) #Load original n back into t3.
lw $t4, 8($sp) #Load original k back into t4.
sub $t3, $t3, 1 #Subtract one from n again. (n-1 step of recursive algorithm)
jal checkBounds #Check for end of recursion with n 1 number lower.
lw $t2, 12($sp) #Load the value held in the previously returned v0.
add $v0, $v0, $t2 #Add old returned value to new returned value.
lw $ra, 0($sp) #Load the original return address.
addi $sp, $sp, 16 #Add 16 more bytes to the stack.
jr $ra
checkBounds: #Check if program should still recurse
beq $t3, $t4, return1 #If n==k
beq $t4, $0, return1 #if k==0
li $v0, 0 #If (j!=k || k!=0){ return 0};
jal nCk
jr $ra
return1: #Returns 1
li $v0, 1
jr $ra
这段代码有很多错误,很难列出。 对于初学者来说,它有语法错误和缺少标签,所以它甚至不能组装。 然后,输入值永远不会写入
$t3
和$t4
,因为操作数顺序颠倒了。
此外,您的CheckBounds
使用JAL
,而不保存$ra
。main
也是如此。
至于打印,结果是$v0
,因此您需要在打印前面的内容之前保存它
解决所有这些问题似乎能让它起作用
您应该真正学会使用调试器/模拟器来修复bug。例如,发现寄存器没有期望值很容易。我冒昧地对代码进行了一点重构,跳过了错误检查部分,向您展示了最重要的部分。本质上,我已经实现了迭代的
factorial
过程,它不会对输入值进行任何错误检查。然后在主程序中,我从用户那里获取输入,计算阶乘并应用公式。希望有帮助
.data
enterN: .asciiz "Please enter the n value: \n"
enterK: .asciiz "Please enter the k value: \n"
output: .asciiz "Result is: "
.text
j main
factorial:
# iterative factorial procedure
# $a0 - number, no error checking is performed on input
# $v0 - factorial of the number
addi $sp, $sp, -4
sw $ra, 0($sp)
li $v0, 1
li $s0, 1
factorial_begin:
beq $s0, $a0, factorial_end # n == 1?
mul $v0, $v0, $a0 # $v0 = $v0 * n
subi $a0, $a0, 1 # n = n - 1
j factorial_begin
factorial_end:
lw $ra, 0($sp)
addi $sp, $sp, 4
jr $ra
main:
# compute cobination (n choose k) = n! / k!(n-k)!
# ----------------------------------------------
la $a0, enterN #Ask for the first param, n.
li $v0, 4 #String syscall
syscall #Prints out string.
li $v0, 5
syscall #Places inputted value in v0.
la $t0, ($v0) # $t0 = n
# computer factorial of n
move $a0, $t0
jal factorial
move $t1, $v0 # $t1 = n!
la $a0, enterK #Asks for the second param, k.
li $v0, 4 #String syscall
syscall #Prints out string
li $v0, 5
syscall #Places inputted value in v0.
la $t2, ($v0) # $t2 = k
# computer factorial of k
move $a0, $t2
jal factorial
move $t3, $v0 # $t3 = k!
sub $a0, $t0, $t2 # $a0 = n - k
jal factorial
move $t4, $v0 # $t4 = (n-k)!
mul $t3, $t3, $t4 # $t3 = k! * (n-k)!
div $t1, $t1, $t3 # $t1 = n! / (k! * (n-k)!)
# print out the result
la $a0, output
li $v0, 4
syscall
move $a0, $t1
li $v0, 1
syscall
你的
printAnswer
程序对我来说毫无意义。例如,您在末尾打印的整数值(应该是n
)实际上是answerIs
字符串的地址,除非我完全弄错了。您很可能是对的。我不确定哪一个参数会保留最终结果。我得出的结论是t3保持了结果。我想我错了?你知道我怎么解决这个问题吗?再次感谢您的帮助。很可能$t3
在那一点上保持n
,我没有阅读所有代码。但是,$t3
不是syscall1的参数<代码>$a0为。因此,您可能需要移动$a0,$t3,而不是la
指令。la
伪指令用于将某物(通常是标签)的地址加载到寄存器中。哈哈,你说得对!我把那条指令写反了。我的程序现在运行得稍微好一点。5c2现在返回-1,而不是那个巨大的数字。感谢您的输入。我欣赏你的批评。我只有约2周或ASM的经验,所以我非常了解这一点。我正在使用MARS进行编译,它似乎在我这边起作用。没有语法错误或缺少标签吗?我的编译和运行结果不正确。感谢您对t3和t4实例化的建议。我经常对mips指令感到困惑,因为它似乎有些是向前读的,有些是向后读的。V0从堆栈分配的第12个字节开始保存?见第82行。我正在使用MARS调试器。它只是让我的眼睛流血哈哈。第22行缺少一个.asciiz
指令-语法错误。您没有定义main
符号。printAnswer
结果的开头是$v0
(由于第91行),但未保存,随后被第120行销毁。因此,在第136行,$t3
不包含结果。啊,在asciiz上捕捉得不错。真不敢相信我忽略了这一点。。很抱歉我的课程是globl,由我的教授提供的一个测试班访问。所以它是从顶部调用的。所以我想它会直接从.数据流到第一行代码。我这么想是不是错了?感谢v0销毁提示!更新的代码:当我使用手动传递的参数测试它时,它总是返回2,并且似乎无法识别无效的参数。例如,5C2应该是10而不是2。当我用教授的测试用例测试它时,它会出错并说:E:\Dropbox\School Stuff\College\Junior Year\Fall Semmer\CIS 251\Assembly Home 4\nCr.asm第43行:0x0040003c的运行时异常:无效的整数输入(syscall 5)我不知道现在发生了什么。。有什么想法吗?您仍然没有正确的$t3
,$t4
(第35行和第45行)。另外,您尝试返回$v1
(第92行)中的值,但没有相应地调整第83行或第110行。当然,最好像往常一样将返回值保留在$v0
中,只需在printAnswer
中适当地保存和恢复它即可。