【发布时间】:2014-06-03 23:55:41
【问题描述】:
我得到了下面的代码示例。
代码从$a0(作为参数传递)中的任何数字开始计数/打印到 0。除了$ra 正在做的事情之外,我可以关注所有事情。那部分让我很困惑。
我知道当我们使用jal 时,$ra 会跟踪返回地址(因此程序知道返回到哪里)。跟踪代码虽然起初$ra 保存在堆栈上,并设置为函数执行完成后我们将返回的位置。但是,每次再次调用 printnums 时不会创建一个新的 $ra 值吗?然后该值将保存在内存中。这意味着当我们最后jr 时,它会跳转到最后保存的$ra 值(它指向jal printnums 之后的ret:)?
还是每次保存$ra 时都会在内存中保留额外的 4 个字节,而不是一遍又一遍地覆盖相同的 4 个字节?如果是这种情况,当我们在堆栈上释放空间时,我们会“弹出”每个$ra,直到我们找到第一个被保存的并返回到函数之外的正确位置。那是对的吗?
我只是想确保我正确理解了这一点。谢谢您的帮助。
printnums: # $a0 has value
addi $sp, $sp, -4 # reserve room for return address
sw $ra, ($sp) # save return address
beq $a0, $0, ret # check ending condition
addi $v0, $0, 1 # set command to print int
syscall # print value in $a0
addi $a0, $a0, -1 # decrement value
jal printnums # call printnums again
ret:
lw $ra, ($sp) # restore $ra
addi $sp, $sp, 4 # deallocate space on stack
jr $ra # return
【问题讨论】:
-
这是一个名为 Tail Call Elimination en.wikipedia.org/wiki/Tail_call 的优化示例
标签: mips