andreeaiban/Computer-Architecture

GitHub: andreeaiban/Computer-Architecture

Java 编写的 MIPS 指令解码器,将十六进制机器码解析为指令格式、操作码、寄存器和常量等位字段,主要用于计算机体系结构学习。

Stars: 0 | Forks: 0

# MIPS 指令解码器 这是一个 Java 程序,用于解码原始的十六进制编码的 MIPS 机器指令——将其解析为指令格式、操作、寄存器、移位量和常量/偏移量——支持以下九种指令:`add`、`addi`、`sub`、`and`、`or`、`slt`、`lw`、`sw` 和 `beq`。

R-type and I-type 32-bit instruction field layout

这正是该解码器所实现的具体位字段布局:R 型指令将其 32 位划分为一个 6 位的格式字段、两个 5 位的源寄存器、一个 5 位的目标寄存器、一个 5 位的移位量和一个 6 位的操作/功能码;I 型指令则划分为一个 6 位的 opcode、一个 5 位的源寄存器、一个 5 位的目标寄存器和一个 16 位的立即数常量/偏移量。 ## 工作原理 **1. 十六进制转二进制 (`hex2bin()`)** 每个十六进制字符都通过 `Integer.parseInt(char, 16)` 单独进行转换,然后格式化为 4 位二进制字符串(前导补零),最后拼接在一起——从而将 8 个字符的十六进制指令转换为完整的 32 字符二进制字符串。 **2. 格式检测 (`instructionType()`)** 检查前 6 位是否等于 `"000000"`。如果是,则为 R 型;否则为 I 型。这是真正的 MIPS 约定——R 型指令的 opcode 始终为零,因为它们的实际操作是编码在末尾的功能字段中的。 **3. R 型解码 (`rType()`)** - 操作:将**最后 6 位**与查找表进行匹配(`add`→`100000`,`sub`→`100010`,`and`→`100100`,`or`→`100101`,`slt`→`101010`) - 两个源寄存器:第 6–10 位和第 11–15 位 - 目标寄存器:第 16–20 位 - 移位量:第 21–25 位 - 常量/偏移量:始终报告为 `none`(R 型指令没有此项) **4. I 型解码 (`iType()`)** - 操作:将**前 6 位**与查找表进行匹配(`addi`→`001000`,`lw`→`100011`,`sw`→`101011`,`beq`→`000100`) - 源寄存器:第 6–10 位 - 目标寄存器:第 11–15 位 - 移位量:始终报告为 `none`(I 型指令没有此项) - 常量/偏移量:剩余的 16 位,即第 16–31 位 **5. 二进制转十进制 (`bin2Dec()`)** 这一步值得详细说明,因为它的实际运作方式乍看之下并非如此。每个字段首先通过 `Integer.parseInt(bitString)` 进行处理,**没有指定基数(radix)**——这意味着它会将其解析为十进制,而不是二进制。这看起来像是一个 bug。但是,由于字符串中的每个字符都已经是 `0` 或 `1`,将其“作为十进制解析”只会保留相同的数字序列,形成一个看起来像十进制的整数(例如,二进制的 `"00101"` 会变成整数 `101`)。然后,`bin2Dec()` 会通过 `% 10` / `/ 10` 将该数字逐位拆解,并使用 2 的幂重新组合——逐位来看,这完全就是一个二进制到十进制的转换。我手动追踪过这个过程(`"00101"` → `101` → 循环正确地返回 `5`)——这是一种真正复杂且迂回的实现方式,`Integer.parseInt(bitString, 2)` 本可以一步到位完成同样的事情。但它是**正确**的,并没有坏掉。 ## 一个真实且客观的局限性 与 `bin2Dec()` 不同,这里有一个确实值得指出的局限性:I 型常量/偏移量字段在解码时**没有进行符号扩展**。真实的 MIPS 16 位立即数是带符号的二进制补码——前导位为 `1` 表示负的偏移量。该实现只是每次都将原始的 16 位直接传入相同的无符号 `bin2Dec()` 逻辑中运行,因此真正的负分支偏移量或立即数值会被输出为一个巨大的正数,而不是正确的负数。它对所有非负数情况都是准确的,这刚好覆盖了所有九个硬编码的测试指令,但如果缺少这个修复,它就不是一个通用的解码器。 ## 测试数据 该程序的 `main()` 运行了九个硬编码的十六进制指令,完整涵盖了所有九种支持的操作: ``` 8E510064 AE330064 02538822 014B9025 222800A5 014B482A 02324020 12320064 012A9824 ``` 例如,`8E510064` → 二进制 `10001110010100010000000001100100` → 前 6 位 `100011` → I 型,匹配到 `lw` —— 这是一个真实的、被正确解码的加载字指令,其源寄存器、目标寄存器和偏移量均提取自预期的位范围。 ## 本仓库展示了什么 - 对真实的指令集架构(MIPS)进行手动的位级解析,而不是一种玩具格式——这确实是反汇编程序自动化执行的第一步 - 使用实际的 MIPS 约定正确区分指令格式(R 型全零的 opcode) - 在两种不同的指令布局中进行细致的字符串索引位字段提取 - 仔细阅读他人看似不寻常的代码,从而能够将“虽然复杂但有效”的实现与“真正损坏”的实现区分开来,而不是仅凭外表做出假设 - 认识到实际遗留的缺陷(仅支持无符号的偏移量解码),而不是夸大该实现的正确性
标签:JS文件枚举, MIPS, 域名枚举, 指令解码, 计算机体系结构, 逆向工程基础