MIPS汇编中如何遍历二进制堆实现摩尔斯码解码?
MIPS摩尔斯码解码:二进制堆索引计算溢出解决方法
核心问题分析
你遇到的算术溢出,本质是使用mul指令进行有符号数乘法时,索引值增长到一定程度触发了有符号溢出异常。摩尔斯码解码的堆索引都是非负整数,改用**无符号左移(sll)**替代乘法,既能实现2*k的计算,又不会触发溢出异常。
正确实现代码
假设当前堆索引k存储在$a0中,临时计算用指定寄存器$t2,摩尔斯字符(./-)存储在$t0中,具体实现如下:
# 处理摩尔斯字符,更新堆索引 process_morse_char: # 判断当前字符是点还是划 beq $t0, 0x2E, calc_left_child # ASCII '.' 的值是0x2E beq $t0, 0x2D, calc_right_child # ASCII '-' 的值是0x2D calc_left_child: # 点对应左子节点:k = 2*k +1 sll $t2, $a0, 1 # 左移1位等价于乘以2,无符号运算不触发溢出 addi $t2, $t2, 1 # 加1得到左子节点索引 move $a0, $t2 # 将更新后的索引写回$a0 j index_updated calc_right_child: # 划对应右子节点:k = 2*k +2 sll $t2, $a0, 1 # 左移1位计算2*k addi $t2, $t2, 2 # 加2得到右子节点索引 move $a0, $t2 # 更新$a0中的当前索引 j index_updated index_updated: # 后续读取decoder_heap对应索引的内容等操作
关键细节说明
为什么用
sll而不是mul?
MIPS的mul指令会对有符号数进行溢出检查,当k大于2^30时,2*k会超出32位有符号数的范围(最大值为2^31-1),触发溢出异常。而sll是无符号移位操作,对于非负的堆索引来说,和乘法效果完全一致,且不会触发溢出(摩尔斯码的解码堆深度有限,索引远达不到2^32的上限)。边界检查可选优化
为避免索引超出decoder_heap的实际范围,可以在更新索引后加入边界判断:li $t3, HEAP_MAX_INDEX # 替换为你的decoder_heap最大有效索引值 bgt $a0, $t3, invalid_morse_code # 索引越界时处理无效摩尔斯码
内容的提问来源于stack exchange,提问作者checkchecker
相关产品推荐
相关产品推荐

