Skip to content

RohanKapurDEV/sim8086

Repository files navigation

sim8086

An Intel 8086 instruction decoder and (partial) simulator, written in Rust as part of Casey Muratori's Performance-Aware Programming course.

It reads a binary of assembled 8086 machine code, disassembles it back into NASM-style assembly, and can optionally simulate the effect of instructions on CPU registers and flags.

Usage

# Disassemble a binary (defaults: -a ./listing_37, -o ./output_recent.asm)
cargo run -- -a listing_39 -o listing_39_out.asm

# Disassemble and simulate register state
cargo run -- -a listing_39 -o listing_39_out.asm --sim
Flag Description Default
-a, --asm-bin-path <PATH> Path to the assembled 8086 binary to decode ./listing_37
-o, --output-file <PATH> Where to write the disassembled listing ./output_recent.asm
-s, --sim Simulate register/flag effects while decoding off

With --sim, register changes are appended to the listing as comments and the final register state is printed at the end:

mov ax, 1
; ax: 0x00 -> 0x01

The repository includes the course listing files (listing_37listing_46), both as assembled binaries and as their .asm sources, for testing. To check the decoder's correctness, assemble its output with nasm and compare it against the original binary.

Project structure

src/
├── main.rs               Entry point: reads the binary, runs the decoder, writes output
├── cli.rs                Command-line arguments (clap)
├── cpu_state.rs          Registers, flags, and register read/write helpers for simulation
└── decoder/
    ├── mod.rs            Decode loop and opcode dispatch
    ├── stream.rs         Byte-stream helpers (u8 / i8 / i16 / u16 reads)
    ├── fields.rs         REG / R/M / accumulator lookup tables
    ├── operand.rs        Shared ModRM, displacement, and immediate decoding
    ├── mov.rs            MOV family handlers
    ├── arithmetic.rs     ADD / SUB / CMP handlers
    └── jump.rs           Conditional jump handlers

The dispatch loop in decoder/mod.rs matches opcode prefixes from shortest (4 bits) to longest (a full byte) and hands each instruction to a family-specific handler. The handlers share the ModRM/addressing-mode logic in operand.rs, since every two-operand 8086 instruction encodes its operands the same way.

Supported instructions

MOV

  • Register/memory to/from register
  • Immediate to register
  • Immediate to register/memory
  • Memory to/from accumulator

ADD / SUB / CMP

  • Register/memory with register to either
  • Immediate to register/memory
  • Immediate to accumulator

Conditional jumps: je, jl, jle, jb, jbe

Simulation coverage

Simulation (--sim) is intentionally partial — it covers what the course exercises needed at this point:

  • mov immediate → register, and register → register
  • add / sub immediate → register, including the zero flag
  • The sign flag, cmp simulation, memory operands, and the instruction pointer are not simulated yet

Limitations

  • Only the instruction subset above is decoded; unknown opcode bytes are skipped silently
  • Jump targets are emitted as raw signed displacements (e.g. je -4) rather than labels, so listings with jumps won't reassemble as-is
  • Segment registers, string operations, and most of the rest of the 8086 ISA are not implemented

About

Intel 8086 instruction decoder and (partial) simulator

Resources

Stars

1 star

Watchers

1 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors