MIPS assembly interpreter implementing the functionality required in mips.pdf and mips-instructions.csv .This project was made as a part of a C++ course. It supports all of the instructions mentioned in the aforementioned files and more! It supports mips-assemble mips-interpret mips-execute and a debugger.
-
mips-assemble- Assembly to binary converter with three operation modes:Usage Modes:
mips-assemble(no parameters) - Reads fromstd::cin, outputs binary tostd::coutmips-assemble input.asm- Reads frominput.asm, outputs binary tostd::coutmips-assemble input.asm output.bin- Reads frominput.asm, writes binary tooutput.bin
-
mips-interpret- Executes give.asmfile. It writes the instructions into MIPSState and executes all of them. Requiresmainlabel to be present. -
mips-execute- Executes the given binary file. The binary must support all of the functions as described inmips.pdfandmips-instructions.csv. -
debugger- Working debugger for MIPS. It takes an .asm file and runs on top of it. After executing an instruction it shows next instruction to execute and supports the following commands:
Available Commands:
| Command | Alias | Description |
|---|---|---|
step |
s |
Execute next instruction |
reg $name |
r |
Show register value |
mem8 address |
m8 |
Show 8-bit memory value |
mem16 address |
m16 |
Show 16-bit memory value |
mem32 address |
m32 |
Show 32-bit memory value |
help |
h |
Show all available commands |
quit |
q |
Exit debugger |
I have decided not to use a single file for the core implementation but rather use multiple header files that just provide the required functionality. The main files simply include the functionality they require. This makes the code more readable and efficient.
MIPSState.hpp- this file contains the current state of the machine. It contains the currently running program in memory and provides functions for memory/register read/writeconverter.hpp- converts a single line of assembly operation from std::string into a binary of type uint32_t. It also contains helper functions for trimming strings.file_processing.hpp- Contains the functionality to convert assembly files into binary and writes them either to a file or into MIPSState to be executed. Uses a 2-pass parser for accurate label resolution and instruction ordering.
Main Functions:
-
void process_instructions(input_filename, output_stream)- Core assembly processing function that implements a 2-pass parsing strategy:- Pass 1: Scans the entire file to collect all labels, instructions, and static data, building a complete
CodeBlockwith resolved addresses - Pass 2: Iterates through the organized
CodeBlock(instructions and data now in execution order) and writes the binary representation to the specified output stream - Arguments:
input_filename(assembly file path) andoutput_stream(eitherstd::coutor opened file stream) - Output: Binary representation ready for execution or storage
- Pass 1: Scans the entire file to collect all labels, instructions, and static data, building a complete
-
void load_into_mips_state(input_filename, mips_state)- Works similary toprocess_instructionsbut instead of writing to a file it writes to a mips_state. -
execution_core.hpp- Core MIPS instruction execution engine that handles the logic of running MIPS programs:
Main Functions:
-
execute_instruction(program_counter, mips_state_ptr)- Executes a single instruction. Takes PC and MIPSState and executes one instruction. Returns a new PC value and updates the MIPSSTate. -
execute_all_instructions(mips_state_ptr)- Runs complete MIPS programs starting at PC = 0. Executes all of the instructions in MIPSSteate until it reaches an exit instruction
mips_errors.hpp- Contains all custom errors. Each error provides a description of what happened and which line / operation caused it. Errors gracefully exit with value 1
I have implemented testing for core components of the program. I have implemented 3 tests each of them testing different part of the program and 1 big test (main_asm_test.cpp) reliant on files inside Asm_tests. Each test uses the same core method expect_eq(got, want, name). It prints is the test has passed or not and shows gotten output compared to the wanted one.
-
main_asm_test.cpp- The main testing file. It goes through all.asmfiles insideAsm_testsand first converts them into binary and then executes them. Each.asmfile I wrote contains the expected output in a comment at the top. This Allows for a very easy dynamic verification of tests. -
test_MIPSState.cpp- tests the MIPSState functionality including register/ memory operations and basic error handling -
test_converter.cpp- Comprehensive test for MIPS converter covering R-type, I-type, and J-type instructions. Tests conversion of assembly lines into binary with values computed using the MIPS converter reference.
I have created Makefiles both for core functions and tests. Since this project is quite complex I tried to add comments that should help in understanding the functionality of the program. I have only used the standard library and my own methods. I have also added sources that I used in this project.