You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

MIPS汇编字符串反转中的加载与存储字节问题排查

MIPS字符串反转调试问题

尝试用MIPS汇编实现字符串反转功能,但作为汇编新手不会调试。当前代码无法反转测试字符串,还触发运行错误:

Exception occurred at PC=0x00000004
Bad address in text read: 0x00000005

控制台提示存在错误的指令地址,无法定位问题,猜测可能出在lb和sb指令的使用上。

相关代码

reverse_string子程序

## $a0 --> address of string
## $v0 --> string length

reverse_string:
    j string_length # this subroutine works
    la $t3, STR_str # contains the string
    
    div $t9, $v0, 2 # divide string length by 2
    add $t8, $zero, $zero # this is the counter
    sub $v0, $v0, 1 # string length - 1
    add $t7, $t3, $v0 # offset by string length - 1 to find last character
    j reverse_string_loop

reverse_string_loop:
    beq $t8, $t9, end_for_all # check if it has reached the halfway point
    lb $t1, 0($t7)     # load last character into $t1
        lb $t2, 0($t3)     # load current character into $t2
        sb $t1, 0($t3)     # store last character at current location
        sb $t2, 0($t7)     # store current character at last location
    add $t3, $t3, 1 
    sub $t7, $t7, 1
    add $t8, $t8, 1

主程序

### reverse_string
##

li  $v0, 4
la $a0, STR_reverse_string
syscall

la $a0, STR_str
jal reverse_string

la $a0, STR_str
jal print_test_string


lw  $ra, 0($sp) # POP return address
addi    $sp, $sp, 4


jr  $ra

问题分析与修复

1. 无条件跳转导致后续代码被跳过

reverse_string开头的j string_length是致命错误:j指令会直接跳转到string_length,但不会保存返回地址,执行完string_length后不会回到reverse_string的后续代码(la $t3...这些行永远不会执行)。

修复:用jal string_length替代j string_length,jal会自动把返回地址存入$ra,执行完子程后可以继续执行后续代码。

2. 硬编码字符串地址,忽略传入参数

子程序定义里说明$a0是字符串地址,但代码里直接用la $t3, STR_str硬编码,没有使用传入的$a0,导致子程序无法处理主程序传入的字符串。

修复:把la $t3, STR_str改成move $t3, $a0,使用主程序传入的字符串地址。

3. 循环缺少跳转,执行一次后跑飞

reverse_string_loop执行完一次循环体后,没有跳转回循环开头的指令,会继续往下执行内存中后续的非法指令,触发地址错误。

修复:在循环体最后添加j reverse_string_loop,保证循环能重复执行。

4. 未定义end_for_all标签

代码里用beq $t8, $t9, end_for_all跳转,但没有定义该标签,会导致跳转到非法地址。

修复:添加end_for_all标签,并在标签处添加返回主程序的指令:

end_for_all:
    jr $ra

5. 寄存器使用注意事项

确保string_length子程序正确将字符串长度返回至$v0,且没有破坏$t3等需要使用的寄存器(如果string_length使用了临时寄存器,需要提前保存)。

修复后的reverse_string子程序示例

reverse_string:
    jal string_length # 调用子程并保存返回地址
    move $t3, $a0     # 使用传入的字符串地址,而非硬编码
    
    div $t9, $v0, 2   # 计算循环次数(长度/2)
    add $t8, $zero, $zero # 初始化计数器
    sub $v0, $v0, 1   # 最后一个字符的索引(长度-1)
    add $t7, $t3, $v0 # 最后一个字符的地址
    j reverse_string_loop

reverse_string_loop:
    beq $t8, $t9, end_for_all # 到达中点则退出循环
    lb $t1, 0($t7)     # 加载末尾字符
    lb $t2, 0($t3)     # 加载当前字符
    sb $t1, 0($t3)     # 交换存储
    sb $t2, 0($t7)
    add $t3, $t3, 1    # 指针右移
    sub $t7, $t7, 1    # 指针左移
    add $t8, $t8, 1    # 计数器+1
    j reverse_string_loop # 回到循环开头

end_for_all:
    jr $ra # 返回主程序

内容的提问来源于stack exchange,提问作者user23033721

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 17:03:33