Lightweight, modular 8-bit CPU emulator with a multiple-pass assembler written in C/C++ for fun to explore computer architecture, instruction execution, and low-level programming.
click here to view instruction specifications
fullemuasmdemo.mp4
NOTE: Has only been tested on windows 11
CPU Emulator
- Signed 8-bit arithmetic with overflow detection
- Support for multiple number formats (decimal, hex, binary)
- Supports jmp operations and subroutines
JMP, JMP_ZRO, JMP_ABV, JMP_NEG, CALL, RET - Program loads from external binary file generated by the assembler,
(program.bin) - Has configurable debug output (RAM view, PC tracing, error logging)
Assembler
- Two-pass assembly process (symbol resolution, code generation)
- Label support with forward and backward referencing
- Multiple number formats (decimal, hex, binary)
- Pointer syntax (
*rXfor register-indirect) - Syntax validation and robust Error Reporting
- Symbol table generation
- Has configureable debug output (Symbol table view, Binary out)
Assembler Pipeline
flowchart LR
A{{.asm file}} -- raw assembly --> B(CLEANER
removes comments)
B -- cleaned assembly string --> C[TOKENIZER
lexical analysis]
C -- string of tokens --> D[PASS ONE
symbols & validation]
D -- Symbol table --> E[PASS TWO
machine code
generation]
D -- Verified tokens --> E
E -- Machine code --> F{{.bin file}}
1. Clone Repo
2. Modify the file program.asm to run your own assembly instructions
3. Build and run CPU Emulator and Assembler
# build and run with makefile
make run
# build and run manually
g++ -Iassembler/include -o assembler assembler/src/*.cpp
./assembler
gcc -Iemulator/include -o emulator emulator/src/*.c
./emulator.exe ; EXAMPLE PROGRAM: SUMS ARRAY OF NUMNERS (sum = 76)
; EXECUTES IN 36 CYCLES
; initialize array
LI r15 12; use temp register to load array values
STR 0xF0 r15
STR 0xF1 r15
LI r15 48
STR 0xF2 r15
LI r15 4
STR 0xF3 r15
LI r15 0; clear r15
LI r0 0; sum
LI r1 4; no of elements in array
LI r2 0xF0; pointer to array start
START:
LD r3 *r2; load array element with pointer
ADD r0 r0 r3; add to sum
ADDI r2 r2 1; increment pointer
SUBI r1 r1 1; decrement counter
JMP_ZRO FINISH; when the end of the array is reached, jump to FINISH
JMP START; jump to START
FINISH:
STR 0xFE r0; store result in RAM location 0xFE
HALT; end program
- Average CPI: 1 cycle per instruction
- Fibonacci(8): 47 cycles, 21 result
- 5! Factorial: 23 cycles, 120 result
- Sum of Array (4 elements): 36 cycles
- Prime Number Checker: (coming soon)
- Bubble Sort: (coming soon)
- Create ALU that handles signed arithmetic
- Create RAM & ROM and load program
- Create Control Unit
- Can Execute Instructions
- Track Preformance Metrics
- Subroutine support
- State & Stack Operations
- Load program
- Impliment Tokenizer & Symbol Table
- Impliment First Pass
- Impliment Second Pass
- Generate Binary File
- Modify Control Unit to decode & process binary instructions
- Transition from 2D RAM to 1D
- Better Handling of edge cases on the CPU emulator
- Run Bubble sorting Algorithm on CPU
