MIPSsim实验报告精讲:指令语义、数据通路与三个汇编程序的避坑要点

发布时间:2026/10/10 15:44:05
MIPSsim实验报告精讲:指令语义、数据通路与三个汇编程序的避坑要点
简介面向计算机系统结构课程学习的 MIPS 指令系统实验报告资源适合高校本科生或自学处理器架构的初学者。报告基于 MIPSsim 模拟器覆盖 MIPS 指令语义、寄存器与内存操作、64 位整数求补等典型实验场景能帮助读者快速掌握 MIPS RISC 架构的编程与调试方法。资源包内含 1 个 docx 文档共 754KB内容为完整实验报告包含实验目的、操作步骤、汇编代码示例、执行结果与问题分析等模块可直接用于实验参考或报告撰写。目前已有 647 人浏览学习。报告重点展示了阶乘计算、利用逻辑左移与右移实现乘除、64 位整数求补等实现并给出 MIPS 汇编代码及寄存器分配思路读者可据此理解 SLL、SRL、ADDIU、BGTZ 等指令的用法同时加深对 .data 与 .text 段、$r0 恒定零等体系结构特性的认识为后续学习操作系统、编译原理及嵌入式系统设计等内容打下基础。1. MIPSsim 实验报告里的三个程序一次看懂指令语义、数据通路与踩坑点第一次把这份实验报告里的阶乘程序在 MIPSsim 里跑通时我一边看着 r1 从 6 一路乘到 720一边才真正理解了“指令系统”和“体系结构”这两个词在计算机系统结构课里的分量——不是背指令表而是看着 MUL 怎么改寄存器、BGTZ 怎么让 PC 跳回标号。这份报告覆盖了 MIPS 汇编最常用的三类场景循环、移位替代乘除、64 位数据求补代码量不大但对理解数据通路和指令语义非常关键。它适合刚接触 MIPSsim 的学生、准备课程实验或复试手写汇编的考生以及想在动手写代码前先看一遍完整示例的开发者。下面的内容按“原理—代码—踩坑”推进每个程序我都会先讲设计思路再给可直接运行的代码和参数说明。2. MIPSsim 基础与 MIPS 指令语义r0、.data 与 ADDIULW 取数范式2.1 r0 为什么恒为 0立即数装载和清零都靠它MIPS 有 32 个通用寄存器 r0 到 r31其中 r0 是唯一一个“只读”且恒为 0 的寄存器。硬件上对它执行写入会被直接丢弃这个设计一方面简化了数据通路——不需要额外的清零逻辑另一方面给汇编代码提供了一个稳定的零值来源。几乎所有需要装载常量的指令都写成 ADDIU rd, r0, imm 的形式源操作数是 r0立即数作为被加数结果写入目标寄存器。比如实验一的 ADDIU r1, r0, 6就是把整数 6 放进 r1。有些同学刚接触时会问“C 语言里 int a6MIPS 为什么不写一条 MOV”。MIPS 没有通用的“装载立即数”单指令加载小常量的标准做法就是 ADDIU/ADDI 配 r0。如果需要把某个计算结果拷贝到另一个寄存器也可以写成 ADDIU rd, rs, 0或者用 OR rd, rs, r0。MIPSsim 的寄存器窗口里 r0 始终显示 0手工改不动这一点在做循环初值、累加清零时特别方便。我做实验时习惯先确认 r0 没被动过再往下看指令流因为一旦某条指令错误地把 r0 当目标寄存器整个程序的初值就全乱了。还有一个容易忽略的点ADDIU 里的立即数只有 16 位但因为做了符号扩展取值范围是 -32768 到 32767。实验里的 6、1、8 都是小常量直接用没问题如果立即数超过这个范围ADDIU 就不够用了需要 LUI 先装载高 16 位再 ORI 拼低 16 位。这个边界在后续写大数组偏移量或大常量时会遇到。2.2 .text 与 .data地址、标签和值的关系MIPS 汇编源文件里常见两段.text 放指令.data 放数据。实验二代码里的 X: .word 112 做了三件事在内存里分配一个 32 位字、初始值写成 112、把该内存单元的地址绑定到标号 X。这里最容易被新手误解的是“标号是地址不是值”。ADDIU r1, r0, X 装进 r1 的是 X 所在的内存地址并不是 112要拿到 112 必须再执行 LW r1, 0(r1)以 r1 里存的地址去内存取数。如果把 X 直接当数值参与 SUB、SLL算出来的结果没有任何意义。MIPSsim 的基本操作流程我一般这样走把代码保存成 .txt 或 .asm 文件在模拟器里打开后先看有没有语法错误提示然后点单步执行逐条观察最后用连续执行看最终结果。寄存器窗口中 r0 到 r31 的值会随每条指令更新内存窗口也能按地址查看 .data 段的内容。调试时我习惯把寄存器窗口和内存窗口并排放这样执行到 LW 时可以同时看到“地址寄存器的值”和“内存中取出的值”两个状态地址和值的关系一目了然。文件扩展名有时候会踩坑——某些 MIPSsim 版本只认纯文本格式的 .asm如果直接从 Word 复制粘贴保存文件里会带不可见字符加载时直接解析失败。.text main: ADDIU $r1, $r0, X ; r1 X 的地址 LW $r1, 0($r1) ; r1 内存中 X 的值提示MIPSsim 打开中文注释乱码时把文件另存为 UTF-8 或改用纯英文注释能省掉很多排查时间。2.3 ADDIU LW 的内存读取范式与三操作数指令格式LW 的完整格式是 LW rt, offset(base)先把 base 寄存器的值与 16 位符号扩展后的 offset 相加得到内存地址再把这个地址处的 32 位数据写入 rt。所以“把数据段的值取到寄存器”固定是两条指令先 ADDIU 把标签地址装入一个寄存器再 LW 从零偏移处取数。如果数据是连续存放的多个 32 位字可以用 0(r1)、4(r1)、8(r1) 这样的偏移连续取值这正是实验三里取低 32 位和高 32 位的基础。MIPS 算术指令大多是三操作数ADD rd, rs, rt结果写入 rd源寄存器不被破坏。SUB、SLL、SRL、MUL 都遵循这个格式。刚写完 x86 或 ARM 汇编的同学最容易在这里翻车——把 MUL r1, r2 当两操作数用模拟器直接解析失败。写指令时对照一下“三个逗号四段”基本能避免这类低级错误。三操作数设计的价值在于不用准备额外的临时寄存器就能保留原始输入比如实验二里 X 和 Y 的值要被反复使用如果没有三操作数格式中间得多挪好几次数据。MIPS 指令本质上是一个 32 位定长字包含 opcode、rs、rt、rd、shamt、funct 等字段。rs 和 rt 是两个源寄存器rd 是目标寄存器SLL/SRL 这种移位指令把 shamt 字段用作移位量。理解这个布局后再看汇编代码就能明白为什么每条指令都写得那么规整——每个操作数在机器码里都有固定的位段硬件的译码电路才能高效地取出来。3. 三个实验程序逐段拆解阶乘循环、移位乘除与 64 位求补3.1 阶乘循环MUL、SUB 与 BGTZ 的组合这一节对应实验报告里的“附 1求阶乘”完整代码是.text main: ADDIU $r1, $r0, 6 ; r1 6保存初始输入并累积阶乘结果 ADDIU $r3, $r0, 1 ; r3 1用作比较基准和递减步长 SUB $r2, $r1, $r3 ; r2 n - 1循环变量 PROG1: MUL $r1, $r1, $r2 ; r1 r1 * r2 SUB $r2, $r2, $r3 ; r2 r2 - 1 BGTZ $r2, PROG1 ; r2 0 则跳回 PROG1 NOP ; 延迟槽填充 NOP ; 程序收尾逻辑上用了三个寄存器r1 记录初始输入 n 同时累积阶乘结果r3 固定为 1 用于递减r2 作为循环变量从 n-1 开始每轮减 1。手动算一遍 6 的阶乘初始 r16r25进入 PROG1 后 r1 依次变成 30、120、360、720r2 从 5 减到 0当 r20 时 BGTZ 条件不成立退出循环。整个循环执行次数是 n-1最后一次乘的是 1所以结果正好是 6×5×4×3×2×1。BGTZ 的语义是“大于零则跳转”它只和 0 比较不需要第二个寄存器比 SLT BNE 的组合省一条指令。把 ADDIU r1, r0, 6 里的 6 改成其他正整数就能计算不同输入的阶乘想改变结果存放位置需要同时把 MUL 和 SUB 的目标寄存器一起改避免把中间结果写乱。这里有两个容易忽视的细节。第一MUL 在 MIPSsim 里是三操作数乘法r1 r1 × r2如果换到只支持 MULT/MFLO 的模拟器这条指令就跑不通需要用 MULT 后接 MFLO 才能取回乘积。第二BGTZ 后面的两个 NOP。MIPS 分支指令之后有一条延迟槽无论是否跳转该位置的指令都会先执行。实验报告在分支后放 NOP就是为了防止循环体里多执行一条无关指令。如果删掉 NOP程序多执行的那条指令可能是上一条 SUB阶乘结果就会变成多乘或少乘了一次。3.2 逻辑移位代替乘法除法SLL 与 SRL 的适用边界这一节对应实验报告里的“附 2求 (X-Y)*2-(XY)/8”X112Y8结果保存在 r1。完整代码是.text main: ADDIU $r1, $r0, X ; r1 数据段标号 X 的地址 LW $r1, 0($r1) ; r1 112 ADDIU $r2, $r0, Y ; r2 数据段标号 Y 的地址 LW $r2, 0($r2) ; r2 8 SUB $r3, $r1, $r2 ; r3 X - Y 104 SLL $r3, $r3, 1 ; r3 104 * 2 208 ADD $r4, $r1, $r2 ; r4 X Y 120 SRL $r4, $r4, 3 ; r4 120 / 8 15 ADD $r1, $r3, $r4 ; r1 208 15 223 NOP NOP .data X: .word 112 Y: .word 8左移 1 位相当于乘以 2右移 3 位相当于除以 8因为 2^12、2^38。这种方法只在除数是 2 的幂时成立。SLL rd, rt, sa 中 sa 是移位量5 位无符号立即数取值范围 0 到 31SRL 是逻辑右移高位补 0不是算术右移所以不能用它直接对有符号负数做除以 2 的操作——负数右移一位需要高位补 1逻辑右移补 0 之后符号位就变了。要做有符号数的右移得用 SRA 算术右移指令。这段代码里最值得核对的是最后一条指令。题目文字写的是 (X-Y)*2-(XY)/8按减号手算结果应该是 208 - 15 193但报告里给出的示例代码最后一条写的是 ADD模拟器跑出来是 223。我拿到这类实验报告的习惯是先用手算一遍预期值再对照代码判断该信哪个。以题目要求为准代码里的末条应该改成 SUB r1, r3, r4 才能得到 193。这个差异后面会在避坑章节再展开一次因为它不是个例很多流传的实验代码都会出现文字和代码不一致的情况。3.3 64 位整数求补XORI 取反与进位判断的完整代码这一节对应实验报告里的“附 364 位整数求补运算”。求补运算的本质是按位取反再加 1MIPS 没有单条指令能对 64 位数整体求补MIPSsim 也不支持直接 load/store 64 位数据所以只能拆成高低两个 32 位分别处理。报告里给了一个关键判断只有低 32 位取反后是 32 位全 1即原值为 0时加 1 才会产生进位这时高 32 位需要额外加 1。补全后的完整代码是这样.text main: ADDIU $r1, $r0, X ; r1 数据段基地址 LW $r2, 0($r1) ; r2 低 32 位本例为 112 LW $r3, 4($r1) ; r3 高 32 位本例为 90 XORI $r2, $r2, -1 ; 低 32 位按位取反 XORI $r3, $r3, -1 ; 高 32 位按位取反 ADDIU $r4, $r2, 1 ; 低 32 位取反后加 1 BNE $r4, $r0, SKIP ; 加 1 后结果不为 0说明没有进位 ADDIU $r3, $r3, 1 ; 有进位高 32 位补 1 SKIP: ADDIU $r2, $r4, 0 ; 结果低 32 位 - r2 ADDIU $r3, $r3, 0 ; 结果高 32 位 - r3 NOP NOP .data X: .word 112 ; 低 32 位 Y: .word 90 ; 高 32 位XORI 的立即数 -1 在 MIPSsim 里按符号扩展处理扩展成 32 位全 1正好用来做按位取反。这里有个规范上的差异值得留意标准 MIPS 规范里 XORI 这类逻辑立即数指令是零扩展的直接写 -1 只会影响低 16 位但实验报告和 MIPSsim 的实际表现是按符号扩展处理所以这个写法在 MIPSsim 里能直接得到预期结果。如果换到别的模拟器稳妥做法是先用 LUI ORI 构造 0xFFFFFFFF再执行 XOR避免依赖具体模拟器的立即数扩展方式。LW r3, 4(r1) 的 4 是偏移量因为数据段里 X 在低地址、Y 在高地址连续存放的两个 32 位字间隔 4 字节。执行完取反和加 1 后用 BNE r4, r0 判断低 32 位是否产生了进位如果 r4 是 0说明低 32 位取反后是全 1加 1 后溢出回到了 0此时高 32 位必须补 1如果 r4 不是 0说明没有进位跳过补 1 直接保存结果。结果按实验要求放回 r3高 32 位和 r2低 32 位。实验文字里给了两种输入场景一种高 32 位为 90、低 32 位为 112另一种高 32 位为 90、低 32 位为 0。第二种场景特意把低 32 位设成 0就是为了触发进位路径——只要把 .data 里的 X 改成 0重跑同一段代码就能看到 BNE 条件不成立、高 32 位加 1 的那条分支。拿这两种场景对照着跑一遍64 位求补的两个分支就都覆盖到了。4. 常见问题与避坑记录MIPSsim 上跑这三个程序的五个教训4.1 标号当数值用LW 前面缺了一条 ADDIU现象寄存器里出现的是 112 这个地址值而不是数据本身后续 SUB、SLL 算出来的结果和手算完全对不上。我在实验二里第一次跑X-Y的时候r1 装着 112r2 装着 8减法结果却不是 104而是另一个地址差值。原因把 .data 里的标号 X 当成了数值 112 直接用。标号是内存地址不是数据地址和值之间隔着一层内存访问。ADDIU r1, r0, X 只是拿到了 X 的地址没有真正把 112 读进寄存器。解决凡是从 .data 段取数一律先 ADDIU r, r0, 标签再 LW r, 0(r)。我后来写代码前会在草稿上标一下“这一步拿到的是地址还是值”地址就继续传给 LW 使用值才能进算术运算。两个角色混用是 MIPS 汇编新手最容易踩的坑没有之一。4.2 题目和代码不一致ADD 与 SUB 的差异现象手算 (112-8)×2-(1128)/8 得到 193但按报告示例代码连续执行r1 里却是 223。原因报告示例代码的最后一条写的是 ADD r1, r3, r4而题目文字要求的是减号。文字和代码对不上说明这份实验报告在整理时没有按题目复核最终结果。解决以题目要求为准把最后一条改成 SUB r1, r3, r4 再跑输出就是 193。这个教训让我养成了一个习惯拿到任何实验报告先看题目描述里的数学关系再手动推一遍预期值最后才跑模拟器对照。代码可以抄但预期值必须自己算否则连模拟器跑错了都发现不了。4.3 64 位求补时漏掉进位现象输入高 32 位为 90、低 32 位为 0 时结果的高 32 位比预期少了 1。原因直接对低 32 位执行 ADDIU r2, r2, 1 后进位被丢进了无效的溢出位高 32 位完全没有感知到这个进位。求补运算是按位取反再加 1加 1 这步可能产生跨 32 位边界的进位不判断就会丢。解决先把取反后的低 32 位加 1 的结果放到临时寄存器 r4再用 BNE r4, r0 判断结果是否为 0。为 0 说明低 32 位取反后是全 1原值为 0必须让高 32 位补 1不为 0 则直接跳过。这个分支逻辑是 64 位求补里最容易丢分的地方建议把两种输入场景都跑一遍确认两个分支都生效。4.4 删掉 NOP 后循环行为异常现象把 BGTZ 后面的两个 NOP 删掉阶乘程序有时会多执行一条指令结果从 720 变成 5040 或更大的错值。原因MIPS 分支延迟槽机制。BGTZ 后面的那条指令无论是否跳转都会先执行一遍。如果你在延迟槽位置放了一条 SUB循环里就相当于每轮多减一次如果在循环末尾放了一条乘法的残余指令最后一次循环会多乘一个本不该乘的数。解决在分支和目标之间保留 NOP 作为延迟槽填充或者放一条与业务无关的指标令。MIPSsim 如果实现了流水线延迟槽删掉 NOP 的影响立刻可见即使某些版本不模拟流水线保留 NOP 也是规范的 MIPS 汇编习惯。我自己的规矩是分支指令后面至少留一个 NOP程序末尾也放一个和报告里的写法保持一致。4.5 ADDIU 溢出不报错现象把阶乘输入从 6 改成 13 之后连续执行的结果突然变成很大的负数和手算的 6227020800 差得离谱。原因ADDIU 不做溢出检查32 位结果超出有符号数范围时最高位进位被直接丢弃结果按补码解释成负数。12 的阶乘约 4.79 亿还在 32 位范围内13 的阶乘约 62.27 亿就溢出了。解决先估算数据范围超过 32 位有符号数范围时改用多步计算或 64 位方案。这个实验本身只要求 6 的阶乘不会触发溢出但如果你想验证程序的通用性改大输入值就要有这个预期。做实验时我一直保留这样一个习惯每次改输入前先问自己一句“新的结果会不会超过 32 位”提前踩一脚刹车比跑完发现负数再回头找原因省事得多。5. 验证与进阶用单步跟踪和改参数把三条程序彻底吃透5.1 单步执行时的四个观察点在 MIPSsim 里我一般不会一上来就点“连续执行”而是先单步走一遍完整流程每执行一条指令看四个地方当前 PC 值、目标寄存器的值、内存窗口对应地址、以及 BGTZ 跳转前后 PC 是否真的回到标号位置。阶乘实验的跳转比较直观——每次 BGTZ 判定 r2 大于 0 时PC 都会跳回 PROG1连续跳 5 次后不再跳转。把这条路径看清楚比背十遍“分支指令改变控制流”都管用。64 位求补实验单步时重点看 LW r2, 0(r1) 和 LW r3, 4(r1) 这两条观察内存窗口里 X 和 Y 的地址关系以及取反后 r2 变成了什么数。XORI 执行前后r2 的十六进制显示会从 0x00000070 变成 0xFFFFFF8F这种视觉变化能帮人把“按位取反”从抽象概念变成具体操作。5.2 改参数验证通用性只跑通原始样例不算真正做完实验我建议把三个程序的输入都改一遍再跑。阶乘输入从 6 改成 7预期输出 5040实验二把 X 改成 24、Y 改成 4验证移位逻辑是否仍然成立64 位求补把低 32 位从 112 改成 0观察进位分支是否触发。每次修改后都重新加载文件不要只在内存窗口里改值——MIPSsim 的 .data 数据区是加载文件时初始化的直接改内存不会影响后续重新执行的结果。5.3 连续执行与单步结果互相校验单步确认逻辑没问题后再用连续执行跑一遍完整程序对比两次最终结果。如果一致说明指令流里没有隐藏的延迟槽或分支异常如果不一致八成是哪个位置的 NOP 写错了回单步模式慢慢查。从那以后我每次跑这类汇编实验都强制自己先单步过一遍、再改参数对照预期值、最后连续执行收尾这套流程至少帮我省下过一个小时的调试时间。希望帮到你。本文还有配套的精品资源点击获取