【问题标题】:Mips Recursive AssignmentMips 递归赋值
【发布时间】:2020-03-29 22:36:59
【问题描述】:

我希望每个人都在这 covid-19 时代没事。我正在做一项任务,我希望有人能指出我哪里出错了。我在 MIPS 程序中输入一个数字,该数字将被放入一个返回以下内容的递归函数中:

准则是: 递归函数接受单个正整数作为输入参数,定义为:

如果n=0,递归(n) = 1

递归(n) = n * 递归(n-1) + 1 如果 n >0

我的递归运行正常,但是当函数展开时,我觉得我迷失在返回中。我也很确定我正在做的很多事情可能看起来很混乱,因为我是 MIPS 的新手。这是我的版本:

这是我的代码:

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

在接下来的几个小时里会一直在破解它。我感谢任何帮助,并希望每个人都有一个愉快的星期天。谢谢!

【问题讨论】:

  • 这是一个糟糕的 pc 值。几乎唯一的方法是通过jr(或您没有的jalr),因此在您的各种jr 上放置一些断点,并检查寄存器值是否在0x004000000 附近。
  • 您在寄存器用法、序言和尾声中有许多拼写错误或错误。遗憾的是,这是一个问答网站,它不适合交互式指导或调试。如果您遇到困难,您可以尝试codementor.io 寻求此类帮助。

标签: recursion assembly mips


【解决方案1】:

我确实解决了这个问题,我只需要掌握一个概念,即在需要保存 $ra 值的任何地方,创建一个堆栈变量。工作代码如下:

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

【讨论】:

    猜你喜欢
    • 2018-09-05
    • 2014-03-19
    • 2016-07-13
    • 2011-05-20
    • 2013-05-12
    • 1970-01-01
    • 2015-02-25
    • 2015-09-12
    • 2014-03-28
    相关资源
    最近更新 更多