You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Mars模拟器中直接读取文本段报错的解决及add/lw指令统计实现问询

解决MIPS中无法从text段读取指令的问题

首先,你碰到的Runtime exception at 0x00400048: Cannot read directly from text segment!错误,本质是MIPS架构的text段(代码存储区)是只读区域,而SPIM这类模拟器默认限制了lw这类数据加载指令直接访问text段——毕竟lw原本是用来从data段加载数据的,直接碰代码段会触发权限校验失败。

下面给你几个可行的解决办法,以及适配你统计指令需求的建议:

1. 最简单的方法:修改模拟器启动参数

如果你用的是SPIM模拟器,启动时加上-allow-text-insns参数,就能允许从text段加载指令。这样你原来写的lw $s0, 0($a0)就能正常工作,直接读取$a0指向的start地址处的指令内容。

2. 无需改参数:用字节加载拼接完整指令

如果不想调整模拟器设置,可以用lb(字节加载)指令逐字节读取text段的内容,再拼接成32位的完整指令。示例代码如下:

la $a0, start          # 把start的地址放到$a0
# 逐字节读取4个字节
lb $t0, 0($a0)
lb $t1, 1($a0)
lb $t2, 2($a0)
lb $t3, 3($a0)
# 拼接成32位指令
sll $t0, $t0, 24       # 第一个字节左移24位到最高位
sll $t1, $t1, 16       # 第二个字节左移16位
sll $t2, $t2, 8        # 第三个字节左移8位
or $s0, $t0, $t1       # 拼接前两个字节
or $s0, $s0, $t2       # 拼接第三个字节
or $s0, $s0, $t3       # 拼接第四个字节,最终$S0就是start处的完整指令

3. 适配你统计指令的额外建议

既然你要统计start和end之间的addlw指令,读取指令后还需要判断指令类型:

  • lw是I型指令,opcode(高6位)为0x23
  • add是R型指令,opcode为0,同时funct字段(低6位)为0x20

你可以用这段逻辑来判断计数:

# 假设$S0已经存了当前读取的指令
srl $t0, $s0, 26       # 提取高6位opcode
li $t1, 0x23
beq $t0, $t1, count_lw # 如果是lw指令,跳转到计数逻辑
li $t1, 0
beq $t0, $t1, check_add # 如果是R型指令,检查funct字段
j next_instruction     # 不是目标指令,跳到下一个

count_lw:
addi $t5, $t5, 1       # lw计数+1
j next_instruction

check_add:
andi $t2, $s0, 0x3F    # 提取低6位funct
li $t3, 0x20
beq $t2, $t3, count_add # 如果是add指令,计数
j next_instruction

count_add:
addi $t5, $t5, 1       # add计数+1

next_instruction:
addi $a0, $a0, 4       # 地址+4,指向下一条指令
bne $a0, $a1, loop     # 没到end地址,继续循环

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

火山引擎 最新活动