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

如何用lw/lb读取内存字符?MIPS补码转换地址越界问题排查

问题分析与解决

地址越界的核心原因

lb $t4, ($t1)触发地址越界,本质是$t1寄存器存储的内存地址不合法,常见场景:

  • 未初始化地址:$t1没有被赋值为合法的内存区域(比如直接使用未赋值的寄存器,或者指向了系统保留/只读内存)
  • 缓冲区溢出:循环读取时没有控制边界,导致$t1超出了你定义的二进制串内存范围
  • 非法地址赋值:错误地将数值(不是内存地址)加载到$t1中

快速排查与修复

1. 确保$t1指向合法内存

先在.data段定义足够大小的缓冲区,然后用la指令加载地址:

.data
    bin_buffer: .space 33  # 32位二进制ASCII + 1字节结束符,足够存储补码
.text
    la $t1, bin_buffer  # 初始化$t1为缓冲区起始地址

2. 循环时添加边界控制

处理32位补码时,循环次数不能超过32次,避免指针越界:

li $t0, 0          # 循环计数器,从0到31
loop_start:
    bge $t0, 32, loop_end  # 超过32次就退出
    lb $t4, ($t1)          # 现在$t1不会越界
    # 你的翻转逻辑...
    addi $t1, $t1, 1       # 指针后移
    addi $t0, $t0, 1       # 计数器+1
    j loop_start
loop_end:

需求实现细节

1. ASCII位翻转('0'↔'1')

读取到的$t4是ASCII码('0'=0x30,'1'=0x31),直接通过条件判断或异或翻转:

# 读取ASCII字符到$t4后
beq $t4, 0x30, write_1
beq $t4, 0x31, write_0
# 可选:处理非法字符
write_1:
    li $t4, 0x31
    j flip_done
write_0:
    li $t4, 0x30
flip_done:
    sb $t4, ($t1)  # 写回内存

2. 负数补码加1操作

补码加1要在**所有位翻转(取反)**之后执行,从最低位开始处理进位:

# 假设$t1指向二进制串的最低位(缓冲区最后一个有效字符)
li $t2, 1          # 初始进位为1
li $t0, 0          # 计数器
addi $t1, $t1, 31  # 指向32位串的最后一位(索引31)
add_one_loop:
    lb $t4, ($t1)
    sub $t4, $t4, 0x30  # 转成数值0/1
    add $t4, $t4, $t2   # 加进位
    beq $t4, 2, carry
    beq $t4, 1, set_1
    # 结果为0,进位清零
    li $t4, 0x30
    li $t2, 0
    sb $t4, ($t1)
    j next_bit
carry:
    li $t4, 0x30
    li $t2, 1
    sb $t4, ($t1)
    j next_bit
set_1:
    li $t4, 0x31
    li $t2, 0
    sb $t4, ($t1)
next_bit:
    addi $t1, $t1, -1  # 指针左移一位
    addi $t0, $t0, 1
    bne $t0, 32, add_one_loop

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 09:00:20