8000
Skip to content

Latest commit

 

History

2 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 

Repository files navigation

LC-3 Virtual Machine

A C++17 implementation of a virtual machine for the LC-3 (Little Computer 3) — a simplified 16-bit educational computer architecture. The VM loads LC-3 machine code binaries and executes them by emulating the fetch-decode-execute cycle of the real hardware, including its registers, memory, condition flags, and memory-mapped I/O devices.

This project is a systems-programming exercise focused on low-level concepts: binary instruction decoding, two's-complement arithmetic, bitwise manipulation, endianness handling, and polymorphic instruction dispatch.

Features

  • Full LC-3 instruction set — all 16 opcodes (ADD, AND, NOT, BR, JMP, JSR, LD, LDI, LDR, LEA, ST, STI, STR, TRAP, RTI, reserved) are implemented.
  • TRAP-based OS routines — keyboard input (GETC, IN), character/string output (OUT, PUTS), and program termination (HALT).
  • Memory-mapped I/O — the keyboard status/data registers (KBSR/KBDR) and the machine control register (MCR) are intercepted transparently during memory reads/writes.
  • 65,536 words of addressable memory and 8 general-purpose registers (R0R7), matching the real LC-3 architecture.
  • Condition flags (N/Z/P) updated after every register write, driving conditional branching.
  • Raw terminal mode on Unix-like systems, so console programs can read keystrokes immediately without waiting for Enter.
  • Big-endian binary loading.bin program images are read and byte-swapped to the host's native endianness.
  • Extensible dispatch design — instructions are implemented as individual executor classes registered in an O(1) opcode-to-executor lookup table, making it straightforward to add or modify instructions.

Architecture

The VM is organized around a small set of focused components:

Component Responsibility
LC3VM Orchestrates the fetch-decode-execute loop; owns memory, registers, and condition flags.
Memory 65,536 x 16-bit word address space; intercepts memory-mapped I/O addresses on read.
Registers The 8 general-purpose 16-bit registers (R0R7).
ConditionFlags Tracks the N/Z/P condition flags used by BR.
InstructionRegistry Maps each 4-bit opcode to its IInstructionExecutor implementation for O(1) dispatch.
IInstructionExecutor Interface implemented by each instruction (ADD, AND, BR, ...) in src/instructions.cpp.
ITrapRoutine Interface implemented by each OS trap routine (GETC, OUT, PUTS, IN, HALT) in src/trap_routines.cpp.
ProgramLoader Reads a big-endian .bin image from disk and swaps it to host byte order.
ALU Shared arithmetic/bitwise helpers (e.g. sign extension) used by instruction executors.
Terminal Puts the host terminal into raw/non-canonical mode so keyboard TRAPs behave like real hardware input.
LC3Runner Thin driver that configures the terminal, loads a program into an LC3VM, and runs it.

Instruction set

Opcode Mnemonic Description
0b0000 BR Conditional branch
0b0001 ADD Addition
0b0010 LD Load
0b0011 ST Store
0b0100 JSR Jump to subroutine
0b0101 AND Bitwise AND
0b0110 LDR Load base + offset
0b0111 STR Store base + offset
0b1000 RTI Return from interrupt
0b1001 NOT Bitwise complement
0b1010 LDI Load indirect
0b1011 STI Store indirect
0b1100 JMP Jump
0b1101 Reserved / unused
0b1110 LEA Load effective address
0b1111 TRAP Operating system call

TRAP routines

Vector Name Description
0x20 GETC Read a single character from the keyboard (no echo)
0x21 OUT Write a character to the console
0x22 PUTS Write a null-terminated string to the console
0x23 IN Prompt and read a single character (with echo)
0x25 HALT Stop execution and print a halt message

Memory-mapped I/O

Address Register Purpose
0xFE00 KBSR Keyboard status register
0xFE02 KBDR Keyboard data register
0xFE04 CRTSR Display status register
0xFE06 CRTDR Display data register
0xFFFE MCR Machine control register

Project structure

LC3/
├── inc/                  # Public headers for the VM's components
│   ├── lc3vm.hpp         # Core VM orchestrator
│   ├── memory.hpp        # Memory subsystem
│   ├── registers.hpp     # Register file
│   ├── cond_flags.hpp    # Condition flags (N/Z/P)
│   ├── instructions.hpp  # Concrete instruction executor classes
│   ├── iinstr_exe.hpp    # Instruction executor interface
│   ├── instruction_registry.hpp  # Opcode dispatch table
│   ├── trap_routines.hpp # Concrete TRAP routine classes
│   ├── itrap_routine.hpp # TRAP routine interface
│   ├── program_loader.hpp# .bin file loader
│   ├── terminal.hpp      # Raw terminal mode helpers
│   ├── alu.hpp           # Arithmetic/bitwise helpers
│   ├── bit_utils.hpp     # Bit manipulation utilities
│   ├── constants.hpp     # Opcodes, trap vectors, MMIO addresses
│   └── lc3runner.hpp     # High-level program runner
├── src/                  # Implementation files corresponding to inc/
└── tests/                # Test suite, sample programs, and build files
    ├── main.cpp           # CLI entry point (build target: lc3vm)
    ├── test_utils.cpp     # Unit tests for utility/ALU functions
    ├── test_instructions.cpp  # Unit tests for instruction execution
    ├── Makefile           # Build rules for the VM and test binaries
    └── *.bin              # Sample LC-3 programs (2048, fib22, print10, rogue)

Building

The project is built with g++ (C++17) via the Makefile located in tests/.

cd tests
make          # builds the lc3vm executable

Running a program

./lc3vm <path-to-program.bin>

Example, using one of the bundled sample programs:

./lc3vm 2048.bin
./lc3vm fib22.bin
./lc3vm print10.bin
./lc3vm rogue.bin

Running the tests

cd tests
make check

This builds and runs test_utils (ALU/utility function tests) and test_instructions (instruction execution tests).

Sample programs

The tests/ directory includes several pre-assembled .bin images that exercise the VM end to end:

  • 2048.bin — the 2048 puzzle game
  • fib22.bin — Fibonacci sequence computation
  • print10.bin — prints the numbers 0 through 9
  • rogue.bin — a small Rogue-like dungeon-crawler game

Requirements

  • A C++17-compatible compiler (e.g. g++)
  • A POSIX-like terminal for raw keyboard input handling (see terminal.hpp)

About

A C++17 virtual machine emulating the LC-3 architecture - fetch-decode-execute pipeline, full 16-opcode instruction set, TRAP-based I/O, and memory-mapped devices.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

0