MIPS程序执行报错:无效程序计数器值0x00000000,求排查原因
解决MIPS汇编中"invalid program counter value: 0x00000000"错误
先把你给出的代码整理成更易读的格式:
test_1: addi $sp, $sp, -4 sw $ra, 0($sp) jal test_2 lw $ra, 0($sp) addi $sp, $sp, 4 jr $ra test_2: addi $sp, $sp, -4 sw $ra, 4($sp) # 这里就是问题的核心! jal test_3 lw $ra, 4($sp) addi $sp, $sp, 4 jr $ra
你遇到的错误根源在于test_2中保存返回地址$ra的偏移量写错了,我们来拆解细节:
- 当
test_2执行addi $sp, $sp, -4时,栈指针$sp已经向低地址(栈底方向)移动了4字节,刚分配的栈空间的起始地址就是当前$sp的值。 - 但你写的
sw $ra, 4($sp)会把$ra存到$sp + 4的位置——这个地址属于栈的上方未分配区域(甚至可能是栈外无效内存),根本不是你为test_2的$ra预留的空间。 - 后续执行
lw $ra, 4($sp)时,读取的是这个无效区域的值,未初始化的内存通常是0x00000000,最后jr $ra尝试跳转到地址0,自然触发了PC无效的错误。
另外你对栈空间的理解有个小误区:不需要手动计算栈的绝对偏移,只需要基于当前$sp用偏移0访问刚分配的空间即可,test_2执行addi $sp, $sp, -4后,栈指针已经自动调整到了正确的位置。
修正后的test_2代码如下:
test_2: addi $sp, $sp, -4 sw $ra, 0($sp) # 用0偏移访问刚分配的栈空间 jal test_3 lw $ra, 0($sp) addi $sp, $sp, 4 jr $ra
这样修改后,test_2会正确把自身的返回地址保存到预留的栈空间,后续读取时能拿到有效地址,执行jr $ra就能正常返回,不会再触发错误。
内容的提问来源于stack exchange,提问作者Nime
相关产品推荐
相关产品推荐

