【问题标题】:MIPS Assembly - Trying to write a recursive program to calculate nCr (Combination)MIPS 汇编 - 尝试编写递归程序来计算 nCr(组合)
【发布时间】:2017-08-20 00:53:13
【问题描述】:

我正在尝试创建一个 mips 汇编程序来递归计算 nCr

我已经编写了整个程序,包括一个驱动程序,但它不能正常运行。我所有的输入和输出都有效,但我的递归算法返回了疯狂的数字。例如,nCr ==268501120 而不是 10。

更新代码:http://pastebin.com/52ueQu99

这只是我的算法的一个 sn-p:

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

【问题讨论】:

  • 你的printAnswer 例程对我来说毫无意义。例如,您在末尾打印的整数值(应该是n)实际上是answerIs 字符串的地址,除非我完全弄错了。
  • 你很有可能是对的。我不确定哪个参数会保持最终结果。我得出的结论是 t3 持有结果。我想我错了?你知道我该如何解决这个问题吗?再次感谢您的帮助。
  • 很可能$t3 在那时持有n - 我没有阅读所有代码。但是$t3 不是系统调用 1 的参数; $a0 是。因此,您可能需要move $a0,$t3 而不是那个la 指令。 la 伪指令用于将某物的地址(通常是标签)加载到寄存器中。
  • 哈哈,你说得对!我倒着写了那条指令。我的程序现在运行得稍微好一些。 5c2 现在返回 -1 而不是那个巨大的数字。

标签: assembly recursion mips combinations ncr


【解决方案1】:

这段代码有很多错误,很难一一列举。 对于初学者来说,它有语法错误和缺少标签,所以它甚至没有汇编。 然后,输入值永远不会写入$t3$t4,因为您将操作数顺序颠倒了。 此外,您的CheckBounds 使用JAL 而不保存$ramain 也是如此。 至于打印,结果在$v0,所以你需要先保存它,然后再通过打印前面的东西来破坏$v0

修复所有这些似乎使它工作。

你真的应该学会使用调试器/模拟器来修复你的错误。例如,发现寄存器没有预期值很容易。

【讨论】:

  • 感谢您的意见。我很欣赏你的批评。我只有大约 2 周或 ASM 经验,所以我对此非常了解。我正在使用 MARS 进行编译,它似乎对我有用。没有任何语法错误或缺少标签吗?我的编译和运行我只是得到不正确的结果。感谢您对实例化 t3 和 t4 的建议。我经常对 mips 指令感到困惑,因为它似乎有些向前阅读,有些向后阅读。 V0 从我的堆栈分配的第 12 个字节开始保存?请参见第 82 行。我正在使用 MARS 调试器。它只是让我的眼睛流血哈哈。
  • 第 22 行缺少 .asciiz 指令 - 语法错误。您没有定义 main 符号。 printAnswer 的开头结果在 $v0 中(由于第 91 行),但没有保存,随后被第 120 行销毁。因此,在第 136 行,$t3 不包含结果。
  • 啊,asciiz 不错。不敢相信我忽略了这一点..对不起。我的全球课程,由我的教授提供的测试课程访问。所以它是从顶部调用的。所以我认为它只会从 .data 直接流向第一行代码。我认为这是错误的吗?感谢 v0 销毁提示!
  • 更新代码:pastebin.com/RN4Wba2y 当我使用手动传递的参数对其进行测试时,它总是返回 2 并且似乎无法识别和无效参数。例如 5C2 应该是 10 而不是 2。当我用教授的测试用例对其进行测试时,它会出错并显示:E:\Dropbox\School Stuff\College\Junior Year\Fall Semester\CIS 251\Assembly Homework 4\nCr 中的错误.asm 第 43 行:0x0040003c 处的运行时异常:无效的整数输入(系统调用 5)我不知道现在发生了什么......有什么想法吗?
  • 您仍然没有正确的初始 $t3$t4(第 35 和 45 行)。此外,您尝试在 $v1(第 92 行)中返回值,但您没有相应地调整第 83 行或第 110 行。当然最好还是像往常一样将返回值留在$v0中,适当的保存并恢复在printAnswer中即可。
【解决方案2】:

我冒昧地稍微重构了您的代码并跳过了错误检查部分来向您展示最重要的部分。本质上,我已经实现了迭代的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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多