在MARS中转换十六进制为整数时出现"invalid program counter value"错误怎么办?
解决MIPS十六进制转整数时的"invalid program counter value: 0x00000000"错误
这个错误本质是程序执行到了没有合法指令的内存地址(0x00000000),问题出在你的代码调用和终止逻辑上,我来帮你拆解问题并修正:
为什么会出现这个错误?
你写的代码里,读取完用户输入后直接进入了hex_convert的逻辑,但并没有用jal(跳转并链接)指令来调用这个转换函数。jal的作用是把当前指令的下一个地址存入$ra寄存器,这样jr $ra才能正确返回。而你直接跳转到hex_convert,$ra里的初始值很可能是0,当执行到jr $ra时,程序就会跳转到0x00000000这个无效地址,触发错误。
除此之外,你的代码还有两个小问题:
- 读取输入时会把用户按下的回车(ASCII码10)也读进去,这个字符不在你的
hexvals映射表里,会导致转换结果出错; - 转换完成后没有打印结果的逻辑,也没有正确终止程序的指令。
修正后的完整代码
.data getHex: .asciiz "Enter 32-bit hex: " userInput: .space 9 # 8位十六进制字符 + 1个终止符,预留足够空间 hexvals: .word 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0, 0, 0, 10, 11, 12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 11, 12, 13, 14, 15 .text main: # 打印提示信息 li $v0, 4 la $a0, getHex syscall # 读取用户输入(最多8个十六进制字符) li $v0, 8 la $a0, userInput li $a1, 9 syscall # 调用十六进制转换函数,用jal保存返回地址 jal hex_convert # 打印转换后的整数结果 li $v0, 1 move $a0, $v0 # 把转换结果从$v0移到$a0,用于打印 syscall # 正确终止程序 li $v0, 10 syscall hex_convert: li $v0, 0 # 初始化累加器为0 la $t0, hexvals # 加载十六进制值映射表的地址 loop: lb $t1, 0($a0) # 读取当前字符 # 遇到换行符或空字符就结束转换 beq $t1, 10, end beq $t1, $zero, end sll $v0, $v0, 4 # 累加器左移4位,等价于乘以16 addi $t2, $t1, -48 # 计算字符与'0'的偏移量 sll $t2, $t2, 2 # 偏移量×4,因为每个word占4字节 addu $t2, $t2, $t0 # 计算映射表中对应值的地址 lw $t3, 0($t2) # 获取对应的十进制值 addu $v0, $v0, $t3 # 累加到结果中 addi $a0, $a0, 1 # 指针后移,处理下一个字符 j loop end: jr $ra # 返回主程序的调用位置
核心修正说明
- 新增
main入口标签,用jal hex_convert调用转换函数,确保$ra被正确设置为返回地址,解决程序计数器无效的问题; - 添加
syscall 10指令,让程序执行完后正确终止,避免乱跑内存; - 增加了对输入换行符的判断,防止转换无效字符;
- 补充了打印转换结果的逻辑,让你能直观看到转换后的整数。
内容的提问来源于stack exchange,提问作者Hayden Labrie




