Assembly MIPS汇编-尝试编写递归程序来计算nCr(组合)

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($

我正在尝试创建一个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($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
中适当地保存和恢复它即可。