Himansh Raj

Building an 8085 Microprocessor Simulator

· 3 min read

Building an 8085 Microprocessor Simulator

I built a full Intel 8085 simulator in C++ — a program that emulates the instruction set, memory, registers, and flags of a processor that first shipped in the 1970s. The point wasn't nostalgia. It was to understand, instruction by instruction, what actually happens when a CPU runs code.

Most of us live several abstraction layers above the metal. Writing an emulator is one of the few ways to force yourself all the way down to registers and opcodes.

Why I made it

The 8085 is a great teaching target: it's simple enough to hold in your head, but real enough to teach the fundamentals every modern CPU still uses.

I wanted to:

  • see how a single instruction moves the processor from one state to the next,
  • watch registers and flags change with my own eyes,
  • and understand how the same program can be expressed as mnemonics, hex, or raw bytes.

Emulating it meant I couldn't hand-wave any part. Every instruction had to be implemented correctly, or the whole program would drift into a wrong state.

What it does

The simulator emulates the core of the 8085:

  • 64KB of addressable memory — the full 16-bit address space the chip can reach.
  • The full register and flag model — data transfer, arithmetic, logical, branch, stack, and machine-control instructions.
  • Step-by-step execution — run one instruction at a time and print the register state after each step.
  • Serial I/O support — matching the 8085's own serial capabilities.

A tiny program to add two numbers looks like this:

MVI_A, 05    ; Load 5 into accumulator
MOV_B_A      ; Move accumulator to register B
MVI_A, 03    ; Load 3 into accumulator
ADD_B        ; Add B to accumulator
STA 2000     ; Store result at memory location 2000H
HLT          ; Halt program

Running that and watching the accumulator go from 05 to 03 to 08, with the store landing at 2000H, makes the machine feel real in a way that reading a textbook never did.

Multiple ways to feed it code

One design choice I'm happy with: the simulator accepts programs three different ways.

  • Binary file loading — drop in raw machine code.
  • Hexadecimal input — type in opcodes and operands by hand.
  • Mnemonic-based input — write in assembly-like mnemonics and let the simulator handle the rest.

That progression is itself a lesson. It makes the equivalence between a mnemonic, its hex opcode, and the underlying bytes completely explicit — three representations of the exact same instruction.

What I learned

Building this reinforced a few things:

  1. A CPU is a state machine, and nothing more mysterious. Fetch, decode, execute, update flags, repeat. Once you implement that loop, the mystique disappears.
  2. Flags are where the subtlety lives. Getting carry, zero, and sign to update correctly on every arithmetic and logical operation was the fiddliest part, and the most instructive.
  3. Step-by-step visibility changes how you debug. Being able to halt and inspect state after each instruction is exactly the intuition you want when debugging real code, too.

If you're studying low-level systems, writing an emulator for a simple processor is one of the highest-leverage exercises I know of.

If you want to look at the code, here it is: 8085 Simulator on GitHub.