Recursion MIPS汇编中的简单递归问题

Recursion MIPS汇编中的简单递归问题,recursion,assembly,mips,Recursion,Assembly,Mips,所以我试着用mips写一个程序,只做一些简单的递归,我读了关于这个主题的每一篇文章和问题,但是没有用。不管怎么说,我正试着把我的名字倒排出来。因此,我一次读取一个字节,查找字符串末尾的0,如果找到它,我将开始展开并打印保存的字节。 提前感谢您的帮助 代码: 有一些问题 加载$t6应该是一个字节操作。否则,的条件分支的意义不正确。打印的系统调用应该是11[putc],而不是4[put]。处的堆栈帧还原有问题,否则 我已经创建了三个版本。显示错误的注释版本。一个清理和工作的版本。我从头开始创建了一个

所以我试着用mips写一个程序,只做一些简单的递归,我读了关于这个主题的每一篇文章和问题,但是没有用。不管怎么说,我正试着把我的名字倒排出来。因此,我一次读取一个字节,查找字符串末尾的0,如果找到它,我将开始展开并打印保存的字节。 提前感谢您的帮助

代码:


有一些问题

加载
$t6
应该是一个字节操作。否则,
的条件分支的意义不正确。打印的系统调用应该是11[
putc
],而不是4[
put
]。
处的堆栈帧还原有问题,否则

我已经创建了三个版本。显示错误的注释版本。一个清理和工作的版本。我从头开始创建了一个版本


以下是带注释的版本[请原谅不必要的样式清理]:

    .data
Yn:         .asciiz     "frodobaggins"  # yn stands for your name
# print name backwards
    .text

main:
    li      $v0,4                   # syscall for print string
    la      $a1,Yn                  # load Yn's address into a0
    addi    $sp,$sp,-4              # increment stack pointer
    sw      $a1,0($sp)              # store address of a1 (Yn) into stack pointer
    jal     recurse                 # recursive func call
    addi    $sp,$sp,4               # increment sp back to beggining
    addi    $v0,$0,10               # v0 = exit
    syscall                         # exit

recurse:
    lw      $a3,0($sp)              # load my name into reg $a3

# NOTE/BUG: this should be lb
# NOTE/BUG: by loading $t6 _before_ we've saved it, we are destroying the
# value that _caller_ set
    ###lw       $t6,0($a3)              # read byte
    lb      $t6,0($a3)              # read byte

    addi    $sp,$sp,-12             # increment stack ptr
    sw      $ra,8($sp)              # store address of $ra onto stack
    sw      $t6,4($sp)              # store the byte loaded into $t6 onto stack

# NOTE/BUG: this should be beq and _not_ bne
    ###bne      $t6,$0,otherwise        # if t6 == 0 goto otherwise
    beq     $t6,$0,otherwise        # if t6 == 0 goto otherwise

    add     $a3,$a3,1               # a1 = a1 + 1
    sw      $a3,0($sp)              # push the word, without the byte $t6 used

    jal     recurse

    lw      $t6,4($sp)              # load the byte that was stored into $t6
    lw      $ra,8($sp)              # get $ra ready for returning

# NOTE/BUG: this is the puts syscall -- what we want is putc (i.e. 11)
    ###addi $v0,$0,4                # setup $v0 to tell pc to print to console
    addi    $v0,$0,11               # setup $v0 to tell pc to print to console

# NOTE/BUG: we want to load the byte into $a0
# NOTE/BUG: at this point $t6 has the byte value and _not_ a pointer
    ###lw       $a0,0($t6)              # console always reads from $a0
    move    $a0,$t6

    syscall
    addi    $sp,$sp,12              # put stack pointer back
    jr      $ra                     # string is finished, return.

otherwise:
    # because this is just returning, i need to get the ra that was just
    # stored on the stack
    lw      $ra,8($sp)
# NOTE/BUG: by _not_ restoring the $t6 value of _caller_ things are broken
    jr      $ra                     # go back to original call of jal

这是工作版本。注意早期堆栈帧设置和在
处弹出的完整堆栈帧,否则
。这是比较常见的。也就是说,只有一个地方可以建立堆栈框架。而且,只有一个位置可以弹出框架并返回:

    .data
Yn:         .asciiz     "frodobaggins"  # yn stands for your name
# print name backwards
    .text

main:
    li      $v0,4                   # syscall for print string
    la      $a1,Yn                  # load Yn's address into a0

    addi    $sp,$sp,-4              # increment stack pointer
    sw      $a1,0($sp)              # store address of a1 (Yn) into stack

    jal     recurse                 # recursive func call

    addi    $sp,$sp,4               # increment sp back to beggining

    addi    $v0,$0,10               # v0 = exit
    syscall                         # exit

recurse:
    lw      $a3,0($sp)              # load my name into reg $a3
    lb      $t6,0($a3)              # read byte

    addi    $sp,$sp,-12             # establish stack frame
    sw      $ra,8($sp)              # store address of $ra onto stack
    sw      $t6,4($sp)              # store the byte loaded into $t6 onto stack

    beq     $t6,$0,otherwise        # if t6 == 0 goto otherwise

    add     $a3,$a3,1               # a1 = a1 + 1

    sw      $a3,0($sp)              # push the word, without the byte $t6 used
    jal     recurse

    lw      $t6,4($sp)              # load the byte that was stored into $t6
    lw      $ra,8($sp)              # get $ra ready for returning

    addi    $v0,$0,11               # setup $v0 to tell pc to print to console
    move    $a0,$t6
    syscall

otherwise:
    lw      $ra,8($sp)              # restore return address from stack
    lw      $t6,4($sp)              # store the byte loaded into $t6 onto stack
    addi    $sp,$sp,12              # put stack pointer back
    jr      $ra                     # string is finished, return.

这是我的重构版本。它更符合mips ABI。可能有一些细微的变化:

    .data
name:   .asciiz     "frodobaggins"
nl:     .asciiz     "\n"

    .text
    .globl  main
main:
    li      $v0,4                   # print string syscall
    la      $a0,name                # string address
    syscall

    li      $v0,4                   # print string syscall
    la      $a0,nl                  # string address
    syscall

    la      $a0,name                # string address
    jal     recurse1

    li      $v0,4                   # print string syscall
    la      $a0,nl                  # string address
    syscall

    li      $v0,10
    syscall

# recurse1 -- reverse print string
#
# arguments:
#   a0 -- current string pointer
recurse1:
    sub     $sp,$sp,8               # create stack frame
    sw      $ra,4($sp)              # save return address
    sw      $a0,0($sp)              # save current string pointer

    lb      $t0,0($a0)              # get current byte
    beqz    $t0,recurse1_exit       # is it EOS? if yes, fly

    addu    $a0,$a0,1               # advance to next char
    jal     recurse1                # print other chars
    subu    $a0,$a0,1               # go back to our character

    lb      $a0,0($a0)              # get current byte
    li      $v0,11                  # putc syscall number
    syscall

recurse1_exit:
    lw      $ra,4($sp)              # restore return address
    lw      $a0,0($sp)              # restore current string pointer
    add     $sp,$sp,8               # pop stack frame
    jr      $ra                     # return

# recurse2 -- reverse print string
#
# arguments:
#   a0 -- current string pointer
recurse2:
    sub     $sp,$sp,8               # create stack frame
    sw      $ra,4($sp)              # save return address
    sw      $a0,0($sp)              # save current string pointer

    lb      $t0,0($a0)              # get current byte
    beqz    $t0,recurse2_exit       # is it EOS? if yes, fly

    addu    $a0,$a0,1               # advance to next char
    jal     recurse2                # print other chars
    lw      $a0,0($sp)              # restore our pointer

    lb      $a0,0($a0)              # get current byte
    li      $v0,11                  # putc syscall number
    syscall

recurse2_exit:
    lw      $ra,4($sp)              # restore return address
    lw      $a0,0($sp)              # restore current string pointer
    add     $sp,$sp,8               # pop stack frame
    jr      $ra                     # return

# recurse3 -- reverse print string
#
# arguments:
#   a0 -- current string pointer
recurse3:
    sub     $sp,$sp,8               # create stack frame
    sw      $ra,4($sp)              # save return address

    lb      $t0,0($a0)              # get current byte
    sw      $t0,0($sp)              # save current char value
    beqz    $t0,recurse3_exit       # is it EOS? if yes, fly

    addu    $a0,$a0,1               # advance to next char
    jal     recurse3                # print other chars

    lw      $a0,0($sp)              # get current byte
    li      $v0,11                  # putc syscall number
    syscall

recurse3_exit:
    lw      $ra,4($sp)              # restore return address
    add     $sp,$sp,8               # pop stack frame
    jr      $ra                     # return

有一些问题

加载
$t6
应该是一个字节操作。否则,
的条件分支的意义不正确。打印的系统调用应该是11[
putc
],而不是4[
put
]。
处的堆栈帧还原有问题,否则

我已经创建了三个版本。显示错误的注释版本。一个清理和工作的版本。我从头开始创建了一个版本


以下是带注释的版本[请原谅不必要的样式清理]:

    .data
Yn:         .asciiz     "frodobaggins"  # yn stands for your name
# print name backwards
    .text

main:
    li      $v0,4                   # syscall for print string
    la      $a1,Yn                  # load Yn's address into a0
    addi    $sp,$sp,-4              # increment stack pointer
    sw      $a1,0($sp)              # store address of a1 (Yn) into stack pointer
    jal     recurse                 # recursive func call
    addi    $sp,$sp,4               # increment sp back to beggining
    addi    $v0,$0,10               # v0 = exit
    syscall                         # exit

recurse:
    lw      $a3,0($sp)              # load my name into reg $a3

# NOTE/BUG: this should be lb
# NOTE/BUG: by loading $t6 _before_ we've saved it, we are destroying the
# value that _caller_ set
    ###lw       $t6,0($a3)              # read byte
    lb      $t6,0($a3)              # read byte

    addi    $sp,$sp,-12             # increment stack ptr
    sw      $ra,8($sp)              # store address of $ra onto stack
    sw      $t6,4($sp)              # store the byte loaded into $t6 onto stack

# NOTE/BUG: this should be beq and _not_ bne
    ###bne      $t6,$0,otherwise        # if t6 == 0 goto otherwise
    beq     $t6,$0,otherwise        # if t6 == 0 goto otherwise

    add     $a3,$a3,1               # a1 = a1 + 1
    sw      $a3,0($sp)              # push the word, without the byte $t6 used

    jal     recurse

    lw      $t6,4($sp)              # load the byte that was stored into $t6
    lw      $ra,8($sp)              # get $ra ready for returning

# NOTE/BUG: this is the puts syscall -- what we want is putc (i.e. 11)
    ###addi $v0,$0,4                # setup $v0 to tell pc to print to console
    addi    $v0,$0,11               # setup $v0 to tell pc to print to console

# NOTE/BUG: we want to load the byte into $a0
# NOTE/BUG: at this point $t6 has the byte value and _not_ a pointer
    ###lw       $a0,0($t6)              # console always reads from $a0
    move    $a0,$t6

    syscall
    addi    $sp,$sp,12              # put stack pointer back
    jr      $ra                     # string is finished, return.

otherwise:
    # because this is just returning, i need to get the ra that was just
    # stored on the stack
    lw      $ra,8($sp)
# NOTE/BUG: by _not_ restoring the $t6 value of _caller_ things are broken
    jr      $ra                     # go back to original call of jal

这是工作版本。注意早期堆栈帧设置和在
处弹出的完整堆栈帧,否则
。这是比较常见的。也就是说,只有一个地方可以建立堆栈框架。而且,只有一个位置可以弹出框架并返回:

    .data
Yn:         .asciiz     "frodobaggins"  # yn stands for your name
# print name backwards
    .text

main:
    li      $v0,4                   # syscall for print string
    la      $a1,Yn                  # load Yn's address into a0

    addi    $sp,$sp,-4              # increment stack pointer
    sw      $a1,0($sp)              # store address of a1 (Yn) into stack

    jal     recurse                 # recursive func call

    addi    $sp,$sp,4               # increment sp back to beggining

    addi    $v0,$0,10               # v0 = exit
    syscall                         # exit

recurse:
    lw      $a3,0($sp)              # load my name into reg $a3
    lb      $t6,0($a3)              # read byte

    addi    $sp,$sp,-12             # establish stack frame
    sw      $ra,8($sp)              # store address of $ra onto stack
    sw      $t6,4($sp)              # store the byte loaded into $t6 onto stack

    beq     $t6,$0,otherwise        # if t6 == 0 goto otherwise

    add     $a3,$a3,1               # a1 = a1 + 1

    sw      $a3,0($sp)              # push the word, without the byte $t6 used
    jal     recurse

    lw      $t6,4($sp)              # load the byte that was stored into $t6
    lw      $ra,8($sp)              # get $ra ready for returning

    addi    $v0,$0,11               # setup $v0 to tell pc to print to console
    move    $a0,$t6
    syscall

otherwise:
    lw      $ra,8($sp)              # restore return address from stack
    lw      $t6,4($sp)              # store the byte loaded into $t6 onto stack
    addi    $sp,$sp,12              # put stack pointer back
    jr      $ra                     # string is finished, return.

这是我的重构版本。它更符合mips ABI。可能有一些细微的变化:

    .data
name:   .asciiz     "frodobaggins"
nl:     .asciiz     "\n"

    .text
    .globl  main
main:
    li      $v0,4                   # print string syscall
    la      $a0,name                # string address
    syscall

    li      $v0,4                   # print string syscall
    la      $a0,nl                  # string address
    syscall

    la      $a0,name                # string address
    jal     recurse1

    li      $v0,4                   # print string syscall
    la      $a0,nl                  # string address
    syscall

    li      $v0,10
    syscall

# recurse1 -- reverse print string
#
# arguments:
#   a0 -- current string pointer
recurse1:
    sub     $sp,$sp,8               # create stack frame
    sw      $ra,4($sp)              # save return address
    sw      $a0,0($sp)              # save current string pointer

    lb      $t0,0($a0)              # get current byte
    beqz    $t0,recurse1_exit       # is it EOS? if yes, fly

    addu    $a0,$a0,1               # advance to next char
    jal     recurse1                # print other chars
    subu    $a0,$a0,1               # go back to our character

    lb      $a0,0($a0)              # get current byte
    li      $v0,11                  # putc syscall number
    syscall

recurse1_exit:
    lw      $ra,4($sp)              # restore return address
    lw      $a0,0($sp)              # restore current string pointer
    add     $sp,$sp,8               # pop stack frame
    jr      $ra                     # return

# recurse2 -- reverse print string
#
# arguments:
#   a0 -- current string pointer
recurse2:
    sub     $sp,$sp,8               # create stack frame
    sw      $ra,4($sp)              # save return address
    sw      $a0,0($sp)              # save current string pointer

    lb      $t0,0($a0)              # get current byte
    beqz    $t0,recurse2_exit       # is it EOS? if yes, fly

    addu    $a0,$a0,1               # advance to next char
    jal     recurse2                # print other chars
    lw      $a0,0($sp)              # restore our pointer

    lb      $a0,0($a0)              # get current byte
    li      $v0,11                  # putc syscall number
    syscall

recurse2_exit:
    lw      $ra,4($sp)              # restore return address
    lw      $a0,0($sp)              # restore current string pointer
    add     $sp,$sp,8               # pop stack frame
    jr      $ra                     # return

# recurse3 -- reverse print string
#
# arguments:
#   a0 -- current string pointer
recurse3:
    sub     $sp,$sp,8               # create stack frame
    sw      $ra,4($sp)              # save return address

    lb      $t0,0($a0)              # get current byte
    sw      $t0,0($sp)              # save current char value
    beqz    $t0,recurse3_exit       # is it EOS? if yes, fly

    addu    $a0,$a0,1               # advance to next char
    jal     recurse3                # print other chars

    lw      $a0,0($sp)              # get current byte
    li      $v0,11                  # putc syscall number
    syscall

recurse3_exit:
    lw      $ra,4($sp)              # restore return address
    add     $sp,$sp,8               # pop stack frame
    jr      $ra                     # return

你没有问任何问题,是吗?
lw$t6,0($a3)#读取字节
lw
不加载字节;它加载一个单词(4个字节)。我最初将它作为lb,但现在它运行,但实际上不会打印任何内容,所以我将它改为lw,看看我是否至少可以让控制台以这种方式打印一些内容,你不会问任何问题,是吗?
lw$t6,0($a3)#读取字节
lw
不加载字节;它加载一个字(4字节)。我最初把它作为lb,但现在它运行,但实际上不会打印任何东西,所以我把它改为lw,看看我是否至少可以让控制台以这种方式打印东西