Hey there! 👋 Welcome to my CS2206 Mini Project. I'm incredibly excited to share this with you!
If you've ever wondered what exactly happens under the hood of a computer before an operating system even wakes up, you're in the right place. For this project, I rolled up my sleeves and built a custom two-pass assembler and a fully functional emulator completely from scratch for the SIMPLEX machine architecture, all written in modern C++11.
It was a challenging but incredibly rewarding journey to see raw text instructions turn into binary, and then watch that binary actually execute in a simulated memory environment!
-
Intelligent Assembler (
asm.cpp):- Translates human-readable SIMPLEX assembly code into raw machine-readable binary object files.
- Two-Pass Architecture: It scans the code first to map out all the labels and memory locations, then does a second pass to generate the final machine code perfectly.
- Friendly Error Handling: Nobody likes cryptic errors. The assembler provides helpful line numbers and context if you've made a syntax slip-up, used an invalid instruction, or referenced an undefined label!
-
Robust Emulator (
emu.cpp):- Acts as a virtual CPU, reading the binary output and executing it instruction by instruction.
- Detailed Execution Trace: Watch the magic happen in real-time as it prints the program counter (PC), registers, and the exact instructions being executed.
- Memory Dump: Inspect the state of your virtual memory after the program finishes to verify everything worked as expected.
- Safety First: I've implemented memory bounds checking and infinite loop detection. If your code goes rogue, the emulator steps in to stop it before your computer freezes up.
Ready to get your hands dirty? You just need a standard C++ compiler (like g++). Here is exactly how to get things up and running:
Open your terminal and run these commands to build the tools. The -Wall flag is there because we care about clean, warning-free code!
g++ -std=c++11 -Wall -o asm asm.cpp
g++ -std=c++11 -Wall -o emu emu.cppLet's turn some assembly into machine code. Just pass your assembly file to the assembler:
./asm my_program.asmIf all goes well, it will generate a my_program.obj file (the machine code) and a my_program.l listing file so you can see exactly how it translated your code line by line.
Now for the fun part. Feed that .obj file into the emulator and watch it go:
./emu my_program.objI didn't just build the tools; I wrote some test programs so you can see them in action right away. I highly recommend running these:
bubblesort.asm: A classic! Watch the emulator churn through an array of numbers in memory and sort them perfectly.test06.asm: Math time! This program calculates the beautiful Fibonacci sequence.test05.asm: A simple but effective script that sums up the first N numbers.
Tip: Open these .asm files in your text editor first to see the comments and understand how the SIMPLEX instruction set works before running them!
Building this wasn't just about getting a grade; it completely demystified how software talks to hardware for me. I had to think deeply about:
- Bitwise Operations: Shifting bits around to elegantly pack opcodes and operands into single 32-bit integers.
- State Management: Keeping track of a virtual Program Counter, registers, and a large array acting as our RAM.
- Edge Cases: What happens if a jump instruction points to nowhere? What if we try to read past the end of memory? Handling these gracefully was a huge focus of this project.
I hope you enjoy exploring this as much as I enjoyed building it. Feel free to dive into the source code, break things, and try writing your own .asm programs!