From 51dae3128b2e360f195b39ef11bc36881d17b99a Mon Sep 17 00:00:00 2001 From: Joseph Ferano Date: Sat, 14 Jun 2025 10:31:35 +0700 Subject: [PATCH] Listings 0056, 0057. Improve README --- README.org | 100 +++++++++++++++++++++++++++++++++++++--- asm_files/list-0056.asm | 41 ++++++++++++++++ asm_files/list-0056.txt | 72 +++++++++++++++++++++++++++++ asm_files/list-0057.asm | 42 +++++++++++++++++ asm_files/list-0057.txt | 71 ++++++++++++++++++++++++++++ 5 files changed, 320 insertions(+), 6 deletions(-) create mode 100644 asm_files/list-0056.asm create mode 100644 asm_files/list-0056.txt create mode 100644 asm_files/list-0057.asm create mode 100644 asm_files/list-0057.txt diff --git a/README.org b/README.org index 89d04ee..54d78cb 100644 --- a/README.org +++ b/README.org @@ -1,8 +1,96 @@ #+OPTIONS: toc:nil -* 8086 CPU Emulator -Following along with [[https://www.computerenhance.com/p/table-of-contents][Performance Aware by Computer Enhance]] -* License -This project is licensed under the terms of the MIT license. For more -information, see the included LICENSE file. However, some of this is related to -a paid course so maybe pay for the course if you want to use these files? +* 8086 CPU Simulator + +A complete 8086 processor emulator written in Odin, featuring instruction decoding, execution, and cycle-accurate simulation. Implements a comprehensive subset of the Intel 8086 instruction set with proper flag handling, memory management, and register operations. + +** Features + +- *Complete 8086 instruction decoding* - Supports MOV, arithmetic, jumps, loops, stack operations, and more +- *Cycle-accurate execution* - Proper CPU state management with registers and flags +- *Memory simulation* - 1MB addressable memory space with effective address calculation +- *Comprehensive testing* - 21 assembly test programs with automated validation +- *Reference validation* - Compares execution results against reference CPU states + +** Architecture + +The simulator is organized into several focused modules: + +- =sim8086.odin= - Main entry point and program orchestration +- =types.odin= - Core data structures (CPU state, instructions, operands) +- =instructions.odin= - Complete 8086 instruction set definitions +- =decoding.odin= - Binary instruction decoding and parsing +- =execution.odin= - CPU execution engine with flag calculations +- =printing.odin= - Assembly output formatting +- =testing.odin= - Reference state parsing and validation + +** Building and Running + +#+BEGIN_SRC bash +# Build the simulator +make + +# Decode and print assembly +./sim8086 program.bin instructions + +# Execute with register dump +./sim8086 program.bin registers + +# Full execution with memory dump +./sim8086 program.bin all dump +#+END_SRC + +** Testing + +Comprehensive test coverage included: + +#+BEGIN_SRC bash +# Run all assembly tests +./test_asm.sh + +# Run reference CPU validation tests +./test_ref_cpu.sh +#+END_SRC + +Test files cover: +- Basic MOV operations and addressing modes +- Arithmetic and logical operations with proper flag setting +- Jump and loop instructions +- Stack operations (PUSH/POP) +- Complex programs with multiple instruction types + +** Technical Implementation + +*** Instruction Decoding +- Bit-level parsing of 8086 machine code +- Support for all addressing modes (register, immediate, memory, direct) +- Proper handling of prefixes and multi-byte instructions + +*** Execution Engine +- Register file with proper 8/16-bit access patterns +- CPU flags (Zero, Carry, Sign, Overflow, etc.) with accurate calculations +- Effective address computation for memory operations +- Instruction pointer management and control flow + +*** Memory Model +- 1MB linear address space +- Little-endian byte ordering +- Memory-mapped I/O simulation + +** Supported Instructions + +*Data Movement:* MOV, PUSH, POP, XCHG, LEA, LDS, LES +*Arithmetic:* ADD, SUB, MUL, DIV, INC, DEC, CMP, NEG +*Logical:* AND, OR, XOR, NOT, TEST +*Shifts/Rotates:* SHL, SHR, SAR, ROL, ROR, RCL, RCR +*Control Flow:* JMP, JE, JNE, JL, JG, LOOP, CALL, RET +*String Operations:* MOVS, CMPS, SCAS, LODS, STOS +*System:* INT, IRET, HLT, NOP + +Built following the [[https://www.computerenhance.com/p/table-of-contents][Performance Aware Programming]] course by Casey Muratori. + +** License + +This project is licensed under the MIT License - see the LICENSE file for details. + +*Note:* Some test files are derived from the Performance Aware Programming course materials. Consider supporting the course if you find this project useful. diff --git a/asm_files/list-0056.asm b/asm_files/list-0056.asm new file mode 100644 index 0000000..327cbd0 --- /dev/null +++ b/asm_files/list-0056.asm @@ -0,0 +1,41 @@ +; ======================================================================== +; +; (C) Copyright 2023 by Molly Rocket, Inc., All Rights Reserved. +; +; This software is provided 'as-is', without any express or implied +; warranty. In no event will the authors be held liable for any damages +; arising from the use of this software. +; +; Please see https://computerenhance.com for further information +; +; ======================================================================== + +; ======================================================================== +; LISTING 56 +; ======================================================================== + +bits 16 + +mov bx, 1000 +mov bp, 2000 +mov si, 3000 +mov di, 4000 + +mov cx, bx +mov dx, 12 + +mov dx, [1000] + +mov cx, [bx] +mov cx, [bp] +mov [si], cx +mov [di], cx + +mov cx, [bx + 1000] +mov cx, [bp + 1000] +mov [si + 1000], cx +mov [di + 1000], cx + +add cx, dx +add [di + 1000], cx +add dx, 50 diff --git a/asm_files/list-0056.txt b/asm_files/list-0056.txt new file mode 100644 index 0000000..0340d5f --- /dev/null +++ b/asm_files/list-0056.txt @@ -0,0 +1,72 @@ +************** +**** 8086 **** +************** + +WARNING: Clocks reported by this utility are strictly from the 8086 manual. +They will be inaccurate, both because the manual clocks are estimates, and because +some of the entries in the manual look highly suspicious and are probably typos. + +--- test\listing_0056_estimating_cycles execution --- +mov bx, 1000 ; Clocks: +4 = 4 | bx:0x0->0x3e8 ip:0x0->0x3 +mov bp, 2000 ; Clocks: +4 = 8 | bp:0x0->0x7d0 ip:0x3->0x6 +mov si, 3000 ; Clocks: +4 = 12 | si:0x0->0xbb8 ip:0x6->0x9 +mov di, 4000 ; Clocks: +4 = 16 | di:0x0->0xfa0 ip:0x9->0xc +mov cx, bx ; Clocks: +2 = 18 | cx:0x0->0x3e8 ip:0xc->0xe +mov dx, 12 ; Clocks: +4 = 22 | dx:0x0->0xc ip:0xe->0x11 +mov dx, [+1000] ; Clocks: +14 = 36 (8 + 6ea) | dx:0xc->0x0 ip:0x11->0x15 +mov cx, [bx] ; Clocks: +13 = 49 (8 + 5ea) | cx:0x3e8->0x0 ip:0x15->0x17 +mov cx, [bp] ; Clocks: +13 = 62 (8 + 5ea) | ip:0x17->0x1a +mov word [si], cx ; Clocks: +14 = 76 (9 + 5ea) | ip:0x1a->0x1c +mov word [di], cx ; Clocks: +14 = 90 (9 + 5ea) | ip:0x1c->0x1e +mov cx, [bx+1000] ; Clocks: +17 = 107 (8 + 9ea) | ip:0x1e->0x22 +mov cx, [bp+1000] ; Clocks: +17 = 124 (8 + 9ea) | ip:0x22->0x26 +mov word [si+1000], cx ; Clocks: +18 = 142 (9 + 9ea) | ip:0x26->0x2a +mov word [di+1000], cx ; Clocks: +18 = 160 (9 + 9ea) | ip:0x2a->0x2e +add cx, dx ; Clocks: +3 = 163 | ip:0x2e->0x30 flags:->PZ +add word [di+1000], cx ; Clocks: +25 = 188 (16 + 9ea) | ip:0x30->0x34 +add dx, 50 ; Clocks: +4 = 192 | dx:0x0->0x32 ip:0x34->0x37 flags:PZ-> + +Final registers: + bx: 0x03e8 (1000) + dx: 0x0032 (50) + bp: 0x07d0 (2000) + si: 0x0bb8 (3000) + di: 0x0fa0 (4000) + ip: 0x0037 (55) + + +************** +**** 8088 **** +************** + +WARNING: Clocks reported by this utility are strictly from the 8086 manual. +They will be inaccurate, both because the manual clocks are estimates, and because +some of the entries in the manual look highly suspicious and are probably typos. + +--- test\listing_0056_estimating_cycles execution --- +mov bx, 1000 ; Clocks: +4 = 4 | bx:0x0->0x3e8 ip:0x0->0x3 +mov bp, 2000 ; Clocks: +4 = 8 | bp:0x0->0x7d0 ip:0x3->0x6 +mov si, 3000 ; Clocks: +4 = 12 | si:0x0->0xbb8 ip:0x6->0x9 +mov di, 4000 ; Clocks: +4 = 16 | di:0x0->0xfa0 ip:0x9->0xc +mov cx, bx ; Clocks: +2 = 18 | cx:0x0->0x3e8 ip:0xc->0xe +mov dx, 12 ; Clocks: +4 = 22 | dx:0x0->0xc ip:0xe->0x11 +mov dx, [+1000] ; Clocks: +18 = 40 (8 + 6ea + 4p) | dx:0xc->0x0 ip:0x11->0x15 +mov cx, [bx] ; Clocks: +17 = 57 (8 + 5ea + 4p) | cx:0x3e8->0x0 ip:0x15->0x17 +mov cx, [bp] ; Clocks: +17 = 74 (8 + 5ea + 4p) | ip:0x17->0x1a +mov word [si], cx ; Clocks: +18 = 92 (9 + 5ea + 4p) | ip:0x1a->0x1c +mov word [di], cx ; Clocks: +18 = 110 (9 + 5ea + 4p) | ip:0x1c->0x1e +mov cx, [bx+1000] ; Clocks: +21 = 131 (8 + 9ea + 4p) | ip:0x1e->0x22 +mov cx, [bp+1000] ; Clocks: +21 = 152 (8 + 9ea + 4p) | ip:0x22->0x26 +mov word [si+1000], cx ; Clocks: +22 = 174 (9 + 9ea + 4p) | ip:0x26->0x2a +mov word [di+1000], cx ; Clocks: +22 = 196 (9 + 9ea + 4p) | ip:0x2a->0x2e +add cx, dx ; Clocks: +3 = 199 | ip:0x2e->0x30 flags:->PZ +add word [di+1000], cx ; Clocks: +33 = 232 (16 + 9ea + 8p) | ip:0x30->0x34 +add dx, 50 ; Clocks: +4 = 236 | dx:0x0->0x32 ip:0x34->0x37 flags:PZ-> + +Final registers: + bx: 0x03e8 (1000) + dx: 0x0032 (50) + bp: 0x07d0 (2000) + si: 0x0bb8 (3000) + di: 0x0fa0 (4000) + ip: 0x0037 (55) diff --git a/asm_files/list-0057.asm b/asm_files/list-0057.asm new file mode 100644 index 0000000..58c7e46 --- /dev/null +++ b/asm_files/list-0057.asm @@ -0,0 +1,42 @@ +; ======================================================================== +; +; (C) Copyright 2023 by Molly Rocket, Inc., All Rights Reserved. +; +; This software is provided 'as-is', without any express or implied +; warranty. In no event will the authors be held liable for any damages +; arising from the use of this software. +; +; Please see https://computerenhance.com for further information +; +; ======================================================================== + +; ======================================================================== +; LISTING 57 +; ======================================================================== + +bits 16 + +mov bx, 1000 +mov bp, 2000 +mov si, 3000 +mov di, 4000 + +mov cx, [bp + di] +mov [bx + si], cx + +mov cx, [bp + si] +mov [bx + di], cx + +mov cx, [bp + di + 1000] +mov [bx + si + 1000], cx + +mov cx, [bp + si + 1000] +mov [bx + di + 1000], cx + +add dx, [bp + si + 1000] + +add word [bp + si], 76 + +add dx, [bp + si + 1001] +add [di + 999], dx +add word [bp + si], 75 diff --git a/asm_files/list-0057.txt b/asm_files/list-0057.txt new file mode 100644 index 0000000..0461b61 --- /dev/null +++ b/asm_files/list-0057.txt @@ -0,0 +1,71 @@ +************** +**** 8086 **** +************** + +WARNING: Clocks reported by this utility are strictly from the 8086 manual. +They will be inaccurate, both because the manual clocks are estimates, and because +some of the entries in the manual look highly suspicious and are probably typos. + +--- test\listing_0057_challenge_cycles execution --- +mov bx, 1000 ; Clocks: +4 = 4 | bx:0x0->0x3e8 ip:0x0->0x3 +mov bp, 2000 ; Clocks: +4 = 8 | bp:0x0->0x7d0 ip:0x3->0x6 +mov si, 3000 ; Clocks: +4 = 12 | si:0x0->0xbb8 ip:0x6->0x9 +mov di, 4000 ; Clocks: +4 = 16 | di:0x0->0xfa0 ip:0x9->0xc +mov cx, [bp+di] ; Clocks: +15 = 31 (8 + 7ea) | ip:0xc->0xe +mov word [bx+si], cx ; Clocks: +16 = 47 (9 + 7ea) | ip:0xe->0x10 +mov cx, [bp+si] ; Clocks: +16 = 63 (8 + 8ea) | ip:0x10->0x12 +mov word [bx+di], cx ; Clocks: +17 = 80 (9 + 8ea) | ip:0x12->0x14 +mov cx, [bp+di+1000] ; Clocks: +19 = 99 (8 + 11ea) | ip:0x14->0x18 +mov word [bx+si+1000], cx ; Clocks: +20 = 119 (9 + 11ea) | ip:0x18->0x1c +mov cx, [bp+si+1000] ; Clocks: +20 = 139 (8 + 12ea) | ip:0x1c->0x20 +mov word [bx+di+1000], cx ; Clocks: +21 = 160 (9 + 12ea) | ip:0x20->0x24 +add dx, [bp+si+1000] ; Clocks: +21 = 181 (9 + 12ea) | ip:0x24->0x28 flags:->PZ +add word [bp+si], 76 ; Clocks: +25 = 206 (17 + 8ea) | ip:0x28->0x2b flags:PZ-> +add dx, [bp+si+1001] ; Clocks: +25 = 231 (9 + 12ea + 4p) | ip:0x2b->0x2f flags:->PZ +add word [di+999], dx ; Clocks: +33 = 264 (16 + 9ea + 8p) | ip:0x2f->0x33 flags:PZ->P +add word [bp+si], 75 ; Clocks: +25 = 289 (17 + 8ea) | ip:0x33->0x36 flags:P->A + +Final registers: + bx: 0x03e8 (1000) + bp: 0x07d0 (2000) + si: 0x0bb8 (3000) + di: 0x0fa0 (4000) + ip: 0x0036 (54) + flags: A + + + +************** +**** 8088 **** +************** + +WARNING: Clocks reported by this utility are strictly from the 8086 manual. +They will be inaccurate, both because the manual clocks are estimates, and because +some of the entries in the manual look highly suspicious and are probably typos. + +--- test\listing_0057_challenge_cycles execution --- +mov bx, 1000 ; Clocks: +4 = 4 | bx:0x0->0x3e8 ip:0x0->0x3 +mov bp, 2000 ; Clocks: +4 = 8 | bp:0x0->0x7d0 ip:0x3->0x6 +mov si, 3000 ; Clocks: +4 = 12 | si:0x0->0xbb8 ip:0x6->0x9 +mov di, 4000 ; Clocks: +4 = 16 | di:0x0->0xfa0 ip:0x9->0xc +mov cx, [bp+di] ; Clocks: +19 = 35 (8 + 7ea + 4p) | ip:0xc->0xe +mov word [bx+si], cx ; Clocks: +20 = 55 (9 + 7ea + 4p) | ip:0xe->0x10 +mov cx, [bp+si] ; Clocks: +20 = 75 (8 + 8ea + 4p) | ip:0x10->0x12 +mov word [bx+di], cx ; Clocks: +21 = 96 (9 + 8ea + 4p) | ip:0x12->0x14 +mov cx, [bp+di+1000] ; Clocks: +23 = 119 (8 + 11ea + 4p) | ip:0x14->0x18 +mov word [bx+si+1000], cx ; Clocks: +24 = 143 (9 + 11ea + 4p) | ip:0x18->0x1c +mov cx, [bp+si+1000] ; Clocks: +24 = 167 (8 + 12ea + 4p) | ip:0x1c->0x20 +mov word [bx+di+1000], cx ; Clocks: +25 = 192 (9 + 12ea + 4p) | ip:0x20->0x24 +add dx, [bp+si+1000] ; Clocks: +25 = 217 (9 + 12ea + 4p) | ip:0x24->0x28 flags:->PZ +add word [bp+si], 76 ; Clocks: +33 = 250 (17 + 8ea + 8p) | ip:0x28->0x2b flags:PZ-> +add dx, [bp+si+1001] ; Clocks: +25 = 275 (9 + 12ea + 4p) | ip:0x2b->0x2f flags:->PZ +add word [di+999], dx ; Clocks: +33 = 308 (16 + 9ea + 8p) | ip:0x2f->0x33 flags:PZ->P +add word [bp+si], 75 ; Clocks: +33 = 341 (17 + 8ea + 8p) | ip:0x33->0x36 flags:P->A + +Final registers: + bx: 0x03e8 (1000) + bp: 0x07d0 (2000) + si: 0x0bb8 (3000) + di: 0x0fa0 (4000) + ip: 0x0036 (54) + flags: A