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之间的add和lw指令,读取指令后还需要判断指令类型:
lw是I型指令,opcode(高6位)为0x23add是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




