所以我试图用mips写一个程序只做一些简单的递归,我读了所有其他文章和关于我能找到的主题的问题,但无济于事。无论如何我试图向后打印我的名字。所以我一次读取一个字节,在我的字符串末尾寻找0,如果我发现它,我开始展开并打印我保存的字节。 提前感谢您的帮助。
代码:
.data
# print name backwards
Yn: .asciiz "frodobaggins" #yn stands for your name
.text
main:
li $v0, 4 #the v registers tell system what to do 4 ==
print_string
la $a1, Yn #load Yn's address into a0
addi $sp, $sp, -4 #increment stack pointer, always initially points to garbage
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
lw $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
bne $t6, $0, otherwise #if t6 == 0 goto otherwise
add $a3, $a3, 1 #a1 = a1 + 1
sw $a3, 0($sp) #store the word, without the byte $t6 used, onto the stack
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, 4 #setup $v0 to tell pc to print to console
lw $a0, 0($t6) #console always reads from $a0
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)
jr $ra #go back to original call of jal
答案 0 :(得分:0)
有一些问题。
加载$t6
应该是一个字节操作。 otherwise
的条件分支有不正确的意义。要打印的系统调用应该是11 [putc
]而不是4 [puts
]。在otherwise
恢复堆栈帧是有问题的。
我创建了三个版本。带注释的版本,显示错误。清理和工作版本。而且,我是从头开始创建的一个版本。
这里是带注释的版本[请原谅无偿的风格清理]:
.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
这是工作版本。请注意早期堆栈帧设置和完整堆栈帧弹出otherwise
。这有点多见。也就是说,建立堆栈帧的唯一一个地方。并且,只有一个地方可以弹出框架并返回:
.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.
这是我的重构版本。这是一个更符合ABI标准的mips。可能会有一些细微的变化:
.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