summaryrefslogtreecommitdiff
path: root/archived/less_old_sim8086
diff options
context:
space:
mode:
authorRaymaekers Luca <luca@spacehb.net>2025-08-23 16:22:13 +0200
committerRaymaekers Luca <luca@spacehb.net>2025-08-23 16:22:13 +0200
commitea20bd9b5bcff9db1d86d83188e1e899799f324b (patch)
tree615e2f00e385e93061524c9647b64010ba7df3dd /archived/less_old_sim8086
checkpoint
Diffstat (limited to 'archived/less_old_sim8086')
-rw-r--r--archived/less_old_sim8086/build/error2
-rw-r--r--archived/less_old_sim8086/build/first0
-rw-r--r--archived/less_old_sim8086/build/first.asm0
-rw-r--r--archived/less_old_sim8086/build/listing_0037_single_register_mov1
-rw-r--r--archived/less_old_sim8086/build/listing_0038_many_register_mov1
-rw-r--r--archived/less_old_sim8086/build/listing_0039_more_movsbin0 -> 41 bytes
-rw-r--r--archived/less_old_sim8086/build/listing_0040_challenge_movsbin0 -> 39 bytes
-rw-r--r--archived/less_old_sim8086/build/listing_0041_add_sub_cmp_jnzbin0 -> 247 bytes
-rw-r--r--archived/less_old_sim8086/build/listing_0041_add_sub_cmp_jnz_error2
-rw-r--r--archived/less_old_sim8086/build/listing_0041_add_sub_cmp_jnz_first.asm2
-rw-r--r--archived/less_old_sim8086/build/listing_0041_add_sub_cmp_jnz_second0
-rw-r--r--archived/less_old_sim8086/build/listing_0041_add_sub_cmp_jnz_second.asm0
-rw-r--r--archived/less_old_sim8086/build/listing_0042_completionist_decodebin0 -> 893 bytes
-rw-r--r--archived/less_old_sim8086/build/listing_0042_completionist_decode_error0
-rw-r--r--archived/less_old_sim8086/build/listing_0042_completionist_decode_first1
-rw-r--r--archived/less_old_sim8086/build/listing_0042_completionist_decode_first.asm2
-rw-r--r--archived/less_old_sim8086/build/listing_0042_completionist_decode_secondbin0 -> 2 bytes
-rw-r--r--archived/less_old_sim8086/build/listing_0042_completionist_decode_second.asm3
-rwxr-xr-xarchived/less_old_sim8086/build/sim8086bin0 -> 43848 bytes
-rw-r--r--archived/less_old_sim8086/build/test1
-rw-r--r--archived/less_old_sim8086/build/test.asm3
-rwxr-xr-xarchived/less_old_sim8086/code/build.sh26
-rw-r--r--archived/less_old_sim8086/code/print_binary.c63
-rw-r--r--archived/less_old_sim8086/code/sim8086.cpp855
-rw-r--r--archived/less_old_sim8086/code/sim8086.h70
-rw-r--r--archived/less_old_sim8086/listings/listing_0037_single_register_mov.asm19
-rw-r--r--archived/less_old_sim8086/listings/listing_0038_many_register_mov.asm29
-rw-r--r--archived/less_old_sim8086/listings/listing_0039_more_movs.asm47
-rw-r--r--archived/less_old_sim8086/listings/listing_0040_challenge_movs.asm38
-rw-r--r--archived/less_old_sim8086/listings/listing_0041_add_sub_cmp_jnz.asm121
-rw-r--r--archived/less_old_sim8086/listings/listing_0042_completionist_decode.asm451
-rwxr-xr-xarchived/less_old_sim8086/misc/test_listing50
-rwxr-xr-xarchived/less_old_sim8086/misc/test_source_line_by_line80
-rw-r--r--archived/less_old_sim8086/project.4coder43
34 files changed, 1910 insertions, 0 deletions
diff --git a/archived/less_old_sim8086/build/error b/archived/less_old_sim8086/build/error
new file mode 100644
index 0000000..36d5148
--- /dev/null
+++ b/archived/less_old_sim8086/build/error
@@ -0,0 +1,2 @@
+/home/aluc/zot/computerenhance/sim8086/listings/listing_0042_completionist_decode.asm:395: warning: superfluous LOCK prefix on XCHG instruction [-w+prefix-lock-xchg]
+Segmentation fault (core dumped)
diff --git a/archived/less_old_sim8086/build/first b/archived/less_old_sim8086/build/first
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/archived/less_old_sim8086/build/first
diff --git a/archived/less_old_sim8086/build/first.asm b/archived/less_old_sim8086/build/first.asm
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/archived/less_old_sim8086/build/first.asm
diff --git a/archived/less_old_sim8086/build/listing_0037_single_register_mov b/archived/less_old_sim8086/build/listing_0037_single_register_mov
new file mode 100644
index 0000000..93b300d
--- /dev/null
+++ b/archived/less_old_sim8086/build/listing_0037_single_register_mov
@@ -0,0 +1 @@
+ \ No newline at end of file
diff --git a/archived/less_old_sim8086/build/listing_0038_many_register_mov b/archived/less_old_sim8086/build/listing_0038_many_register_mov
new file mode 100644
index 0000000..5605230
--- /dev/null
+++ b/archived/less_old_sim8086/build/listing_0038_many_register_mov
@@ -0,0 +1 @@
+وډމȈÉ \ No newline at end of file
diff --git a/archived/less_old_sim8086/build/listing_0039_more_movs b/archived/less_old_sim8086/build/listing_0039_more_movs
new file mode 100644
index 0000000..405b804
--- /dev/null
+++ b/archived/less_old_sim8086/build/listing_0039_more_movs
Binary files differ
diff --git a/archived/less_old_sim8086/build/listing_0040_challenge_movs b/archived/less_old_sim8086/build/listing_0040_challenge_movs
new file mode 100644
index 0000000..63b3ec5
--- /dev/null
+++ b/archived/less_old_sim8086/build/listing_0040_challenge_movs
Binary files differ
diff --git a/archived/less_old_sim8086/build/listing_0041_add_sub_cmp_jnz b/archived/less_old_sim8086/build/listing_0041_add_sub_cmp_jnz
new file mode 100644
index 0000000..6c71f1b
--- /dev/null
+++ b/archived/less_old_sim8086/build/listing_0041_add_sub_cmp_jnz
Binary files differ
diff --git a/archived/less_old_sim8086/build/listing_0041_add_sub_cmp_jnz_error b/archived/less_old_sim8086/build/listing_0041_add_sub_cmp_jnz_error
new file mode 100644
index 0000000..0ad0b5f
--- /dev/null
+++ b/archived/less_old_sim8086/build/listing_0041_add_sub_cmp_jnz_error
@@ -0,0 +1,2 @@
+Could not open file.
+diff: ../build/listing_0041_add_sub_cmp_jnz_first: No such file or directory
diff --git a/archived/less_old_sim8086/build/listing_0041_add_sub_cmp_jnz_first.asm b/archived/less_old_sim8086/build/listing_0041_add_sub_cmp_jnz_first.asm
new file mode 100644
index 0000000..2168722
--- /dev/null
+++ b/archived/less_old_sim8086/build/listing_0041_add_sub_cmp_jnz_first.asm
@@ -0,0 +1,2 @@
+bits 16
+jnz test_label1
diff --git a/archived/less_old_sim8086/build/listing_0041_add_sub_cmp_jnz_second b/archived/less_old_sim8086/build/listing_0041_add_sub_cmp_jnz_second
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/archived/less_old_sim8086/build/listing_0041_add_sub_cmp_jnz_second
diff --git a/archived/less_old_sim8086/build/listing_0041_add_sub_cmp_jnz_second.asm b/archived/less_old_sim8086/build/listing_0041_add_sub_cmp_jnz_second.asm
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/archived/less_old_sim8086/build/listing_0041_add_sub_cmp_jnz_second.asm
diff --git a/archived/less_old_sim8086/build/listing_0042_completionist_decode b/archived/less_old_sim8086/build/listing_0042_completionist_decode
new file mode 100644
index 0000000..6bf7b11
--- /dev/null
+++ b/archived/less_old_sim8086/build/listing_0042_completionist_decode
Binary files differ
diff --git a/archived/less_old_sim8086/build/listing_0042_completionist_decode_error b/archived/less_old_sim8086/build/listing_0042_completionist_decode_error
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/archived/less_old_sim8086/build/listing_0042_completionist_decode_error
diff --git a/archived/less_old_sim8086/build/listing_0042_completionist_decode_first b/archived/less_old_sim8086/build/listing_0042_completionist_decode_first
new file mode 100644
index 0000000..b64d64a
--- /dev/null
+++ b/archived/less_old_sim8086/build/listing_0042_completionist_decode_first
@@ -0,0 +1 @@
+ \ No newline at end of file
diff --git a/archived/less_old_sim8086/build/listing_0042_completionist_decode_first.asm b/archived/less_old_sim8086/build/listing_0042_completionist_decode_first.asm
new file mode 100644
index 0000000..e3947a2
--- /dev/null
+++ b/archived/less_old_sim8086/build/listing_0042_completionist_decode_first.asm
@@ -0,0 +1,2 @@
+bits 16
+pop word [bp + si]
diff --git a/archived/less_old_sim8086/build/listing_0042_completionist_decode_second b/archived/less_old_sim8086/build/listing_0042_completionist_decode_second
new file mode 100644
index 0000000..5407bf3
--- /dev/null
+++ b/archived/less_old_sim8086/build/listing_0042_completionist_decode_second
Binary files differ
diff --git a/archived/less_old_sim8086/build/listing_0042_completionist_decode_second.asm b/archived/less_old_sim8086/build/listing_0042_completionist_decode_second.asm
new file mode 100644
index 0000000..000ca41
--- /dev/null
+++ b/archived/less_old_sim8086/build/listing_0042_completionist_decode_second.asm
@@ -0,0 +1,3 @@
+bits 16
+
+add al, [bx + si]
diff --git a/archived/less_old_sim8086/build/sim8086 b/archived/less_old_sim8086/build/sim8086
new file mode 100755
index 0000000..4ae804a
--- /dev/null
+++ b/archived/less_old_sim8086/build/sim8086
Binary files differ
diff --git a/archived/less_old_sim8086/build/test b/archived/less_old_sim8086/build/test
new file mode 100644
index 0000000..866ad47
--- /dev/null
+++ b/archived/less_old_sim8086/build/test
@@ -0,0 +1 @@
+Q \ No newline at end of file
diff --git a/archived/less_old_sim8086/build/test.asm b/archived/less_old_sim8086/build/test.asm
new file mode 100644
index 0000000..8ec3d4e
--- /dev/null
+++ b/archived/less_old_sim8086/build/test.asm
@@ -0,0 +1,3 @@
+bits 16
+
+push cx
diff --git a/archived/less_old_sim8086/code/build.sh b/archived/less_old_sim8086/code/build.sh
new file mode 100755
index 0000000..0c37234
--- /dev/null
+++ b/archived/less_old_sim8086/code/build.sh
@@ -0,0 +1,26 @@
+#!/bin/sh
+
+ThisDir="$(dirname "$(readlink -f "$0")")"
+cd "$ThisDir"
+
+CompilerFlags="
+-ggdb
+-DSIM8086_INTERNAL
+-nostdinc++
+"
+
+WarningFlags="
+-Wall
+-Wextra
+-Wno-unused-label
+-Wno-unused-variable
+-Wno-unused-but-set-variable
+-Wno-missing-field-initializers
+-Wno-write-strings
+"
+
+printf 'sim8086.c\n'
+g++ $CompilerFlags $WarningFlags -o ../build/sim8086 sim8086.cpp
+
+# printf 'print_binary.c\n'
+# gcc -ggdb -Wall -Wno-unused-variable -o ../build/print_binary print_binary.c \ No newline at end of file
diff --git a/archived/less_old_sim8086/code/print_binary.c b/archived/less_old_sim8086/code/print_binary.c
new file mode 100644
index 0000000..1382cae
--- /dev/null
+++ b/archived/less_old_sim8086/code/print_binary.c
@@ -0,0 +1,63 @@
+#include <stdio.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+#include <signal.h>
+
+#define Assert(Expr) \
+ if (!(Expr)) \
+ { \
+ raise(SIGTRAP); \
+ }
+
+
+int
+main(int ArgC, char *Args[])
+{
+ if (ArgC < 2)
+ {
+ fprintf(stderr, "Missing argument.\n");
+ fprintf(stderr, "Usage: %s <filename>\n", Args[0]);
+ }
+ else
+ {
+ struct stat StatBuffer = {0};
+ char *Filename = 0;
+ int FD = -1;
+ int Err = -1;
+ size_t Filesize = 0;
+ char *Buffer = 0;
+
+ Filename = Args[1];
+ FD = open(Filename, O_RDONLY);
+ Assert(FD != -1);
+ Err = stat(Filename, &StatBuffer);
+ Assert(Err != -1);
+ Filesize = StatBuffer.st_size;
+
+ if (Filesize)
+ {
+ Buffer = mmap(0, Filesize, PROT_READ, MAP_SHARED, FD, 0);
+ Assert(Buffer);
+
+ for (size_t At = 0; At < Filesize; At++)
+ {
+ unsigned char Byte = Buffer[At];
+ int Count = 8;
+ while (Count--)
+ {
+ printf("%d", Byte >> 7);
+ Byte <<= 1;
+ }
+ printf(" ");
+ }
+ printf("\n");
+ }
+ else
+ {
+ fprintf(stderr, "Empty file.\n");
+ }
+ }
+
+ return 0;
+}
diff --git a/archived/less_old_sim8086/code/sim8086.cpp b/archived/less_old_sim8086/code/sim8086.cpp
new file mode 100644
index 0000000..be6a1f2
--- /dev/null
+++ b/archived/less_old_sim8086/code/sim8086.cpp
@@ -0,0 +1,855 @@
+/*
+
+Instruction have 6 bytes that define what type of instruction it is.
+
+ Each instruction has zero, one or two operands.
+ The operands can be switched depending on the D bit.
+
+ The MOD field indicates if a displacement follows.
+Except when R/M is 110.
+
+The D and W bits are always in the first byte.
+
+Data is always required.
+
+Reg can happen in the first byte.
+
+Some expressions have a second 3bit field that stores the "sub-kind" of instruction.
+*/
+
+#include <stdint.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+#include "sim8086.h"
+
+#define Assert(Expression) \
+if(!(Expression)) \
+{ \
+*(char *)0 = 0; \
+}
+
+#if SIM8086_INTERNAL
+#define DebugLabel(Name) Name:
+#else
+#define DebugLabel(Name)
+#endif
+
+#define Swap(Type, First, Second) \
+{ \
+Type Temp; \
+Temp = First; \
+First = Second; \
+Second = Temp; \
+}
+
+#define JE 0b01110100
+#define JL 0b01111100
+#define JLE 0b01111110
+#define JB 0b01110010
+#define JBE 0b01110110
+#define JP 0b01111010
+#define JO 0b01110000
+#define JS 0b01111000
+#define JNL 0b01111101
+#define JG 0b01111111
+#define JNB 0b01110011
+#define JA 0b01110111
+#define JNP 0b01111011
+#define JNO 0b01110001
+#define JNS 0b01111001
+#define JNZ 0b01110101
+#define LOOP 0b11100010
+#define LOOPZ 0b11100001
+#define LOOPNZ 0b11100000
+#define JCXZ 0b11100011
+
+#define ADD 0b000
+#define SUB 0b101
+#define CMP 0b111
+
+// Can be indexed by R/M or reg field.
+// Also if the W bit is set it can be used to index and get the wide name.
+global_variable char *RegistersNames[][2] =
+{
+ [0b000] = { "al", "ax" },
+ [0b001] = { "cl", "cx" },
+ [0b010] = { "dl", "dx" },
+ [0b011] = { "bl", "bx" },
+ [0b100] = { "ah", "sp" },
+ [0b101] = { "ch", "bp" },
+ [0b110] = { "dh", "si" },
+ [0b111] = { "bh", "di" }
+};
+#define ACCUMULATOR 0b000
+
+global_variable char *DisplacementsNames[] =
+{
+ [0b000] = "bx + si",
+ [0b001] = "bx + di",
+ [0b010] = "bp + si",
+ [0b011] = "bp + di",
+ [0b100] = "si",
+ [0b101] = "di",
+ [0b110] = "bp",
+ [0b111] = "bx"
+};
+
+global_variable char *SegmentRegistersNames[] =
+{
+ [0b000] = "ss",
+ [0b001] = "cs",
+ [0b010] = "ds",
+ [0b011] = "es",
+};
+
+global_variable char GlobalBinaryTempString[9];
+
+inline
+void MemoryCopy(char *To, char *From, size_t Count)
+{
+ while(Count--) *To++ = *From++;
+}
+
+inline
+void CStringCopy(char *To, char *From)
+{
+ while((*To++ = *From++));
+}
+
+inline
+u32 CStringLength(char *Src)
+{
+ u32 Result = 0;
+ while(Src[Result]) Result++;
+ return Result;
+}
+
+char *PrefixString(char *Dest, char *Prefix)
+{
+ u32 PrefixLength = CStringLength(Prefix);
+ u32 DestLen = CStringLength(Dest);
+
+ // Move the string over by the prefix length
+ for(s32 CharAt = DestLen;
+ CharAt >= 0;
+ CharAt--)
+ {
+ Dest[PrefixLength + CharAt] = Dest[CharAt];
+ }
+
+ // Copy the prefix over
+ MemoryCopy(Dest, Prefix, 5);
+
+ return Dest;
+}
+
+int ReadBytesFromFile(int File, u8 **Dest, size_t Count)
+{
+ int BytesRead = read(File, *Dest, Count);
+ *Dest += BytesRead;
+ Assert(BytesRead == (int)Count || BytesRead == 0);
+ return BytesRead;
+}
+
+char *ByteToBinaryString(u8 Byte)
+{
+ char *Result = GlobalBinaryTempString;
+
+ int Count = 8;
+ while(Count--)
+ {
+ *Result++ = '0' + (Byte >> 7);
+ Byte <<= 1;
+ }
+ *Result = 0;
+
+ return GlobalBinaryTempString;
+}
+
+void SetBitFromBitAt(b32 *Bit, u8 Byte, u32 BitAt)
+{
+ if(BitAt)
+ {
+ *Bit = ((Byte & (1 << (BitAt - 1))) != 0);
+ }
+}
+
+u8 ExtractBitsFromByte(u8 Byte, u8 Bits, u8 BitAt)
+{
+ u8 Result = 0;
+
+ u8 ShiftValue = BitAt - 1;
+ u8 Mask = (Bits << ShiftValue);
+ Result = ((Byte & Mask) >> ShiftValue);
+
+ return Result;
+}
+
+int main(int ArgCount, char *Args[])
+{
+ u8 Bytes[255] = {};
+ instruction InstructionsBuffer[256] = {};
+ instruction_table Table = {};
+ Table.Instructions = InstructionsBuffer;
+ Table.Size = (sizeof(InstructionsBuffer)/sizeof(InstructionsBuffer[0])) - 1;
+
+ Table.Instructions[Table.Count++] =
+ {
+ .Name = "mov",
+ .Description = "Register/memory to/from register",
+ .OperandsCount = 2,
+ .BytesCount = 2,
+ .Bytes =
+ {
+ {
+ .Op = 0b10001000,
+ .OpMask = 0b11111100,
+ .WBitAt = 1,
+ .DBitAt = 2,
+ },
+ {
+ .ModBitsAt = 7,
+ .RegBitsAt = 4,
+ .RMBitsAt = 1
+ }
+ }
+ };
+
+ Table.Instructions[Table.Count++] =
+ {
+ .Name = "mov",
+ .Description = "Immediate to register/memory",
+ .OperandsCount = 2,
+ .HasImmediate = true,
+ .BytesCount = 1,
+ .Bytes =
+ {
+ {
+ .Op = 0b10000110,
+ .OpMask = 0b11111110,
+ .WBitAt = 1,
+ .ModBitsAt = 7,
+ .RMBitsAt = 1
+ }
+ }
+ };
+
+ Table.Instructions[Table.Count++] =
+ {
+ .Name = "mov",
+ .Description = "Immediate to register",
+ .OperandsCount = 2,
+ .HasImmediate = true,
+ .BytesCount = 1,
+ .Bytes = {
+ {
+ .Op = 0b10110000,
+ .OpMask = 0b11110000,
+ .WBitAt = 4,
+ .RegBitsAt = 1,
+ }
+ }
+ };
+
+ Table.Instructions[Table.Count++] =
+ {
+ .Name = "mov",
+ .Description = "Immediate to register/memory",
+ .OperandsCount = 2,
+ .HasImmediate = true,
+ .BytesCount = 2,
+ .Bytes =
+ {
+ {
+ .Op = 0b11000110,
+ .OpMask = 0b11111110,
+ .WBitAt = 1,
+ },
+ {
+ .ModBitsAt = 7,
+ .RMBitsAt = 1,
+ }
+ }
+ };
+
+ Table.Instructions[Table.Count++] =
+ {
+ .Name = "mov",
+ .Description = "Memory to accumulator",
+ .OperandsCount = 2,
+ .HasAddress = true,
+ .ToAccumulator = true,
+ .BytesCount = 1,
+ .Bytes =
+ {
+ {
+ .Op = 0b10100000,
+ .OpMask = 0b11111110,
+ .WBitAt = 1
+ }
+ }
+ };
+
+ // NOTE(luca): This is the same instruction as the previous one with the D bit always set to true...
+ Table.Instructions[Table.Count++] =
+ {
+ .Name = "mov",
+ .Description = "Accumulator to memory",
+ .OperandsCount = 2,
+ .HasAddress = true,
+ .ToAccumulator = true,
+ .FlipOperands = true,
+ .BytesCount = 1,
+ .Bytes =
+ {
+ {
+ .Op = 0b10100010,
+ .OpMask = 0b11111110,
+ .WBitAt = 1
+ }
+ }
+ };
+
+ Table.Instructions[Table.Count++] =
+ {
+ .Name = "nil",
+ .Description = "Reg/Memory with register to either",
+ .OperandsCount = 2,
+ .BytesCount = 2,
+ .Bytes =
+ {
+ {
+ .Op = 0b00000000,
+ .OpMask = 0b11000100,
+ .SubOpMask = 0b111 << 3,
+ .WBitAt = 1,
+ .DBitAt = 2,
+ },
+ {
+ .ModBitsAt = 7,
+ .RegBitsAt = 4,
+ .RMBitsAt = 1,
+ }
+ },
+ .SubInstructionsCount = 5,
+ .SubInstructions =
+ {
+ { 0b000 << 3, "add" },
+ { 0b010 << 3, "adc" },
+ { 0b101 << 3, "sub" },
+ { 0b011 << 3, "sbb" },
+ { 0b111 << 3, "cmp" },
+ }
+ };
+
+ Table.Instructions[Table.Count++] =
+ {
+ .Name = "nil",
+ .Description = "Immediate to register/memory",
+ .OperandsCount = 2,
+ .HasImmediate = true,
+ .BytesCount = 2,
+ .Bytes =
+ {
+ {
+ .Op = 0b10000000,
+ .OpMask = 0b11000100,
+ .WBitAt = 1,
+ .SBitAt = 2,
+ },
+ {
+ .SubOpMask = 0b00111000,
+ .ModBitsAt = 7,
+ .RMBitsAt = 1,
+ }
+ },
+ .SubInstructionsCount = 5,
+ .SubInstructions =
+ {
+ { 0b000 << 3, "add" },
+ { 0b010 << 3, "adc" },
+ { 0b101 << 3, "sub" },
+ { 0b011 << 3, "sbb" },
+ { 0b111 << 3, "cmp" },
+ }
+ };
+
+ Table.Instructions[Table.Count++] =
+ {
+ .Name = "nil",
+ .Description = "Immediate to accumulator",
+ .OperandsCount = 2,
+ .HasImmediate = true,
+ .ToAccumulator = true,
+ .BytesCount = 1,
+ .Bytes =
+ {
+ {
+ .Op = 0b00000100,
+ .OpMask = 0b11000110,
+ .SubOpMask = 0b111 << 3,
+ .WBitAt = 1,
+ },
+ },
+ .SubInstructionsCount = 5,
+ .SubInstructions =
+ {
+ { 0b000 << 3, "add" },
+ { 0b010 << 3, "adc" },
+ { 0b101 << 3, "sub" },
+ { 0b011 << 3, "sbb" },
+ { 0b111 << 3, "cmp" },
+ }
+ };
+
+#define ByteJump(InsName, InsDescription, InsOp) \
+{ \
+.Name = InsName, \
+.Description = InsDescription, \
+.OperandsCount = 1, \
+.IsByteJump = true, \
+.BytesCount = 1, \
+.Bytes = \
+{ \
+{ \
+.Op = InsOp, \
+.OpMask = 0b11111111, \
+} \
+} \
+}
+ Table.Instructions[Table.Count++] = ByteJump("jz", "Jump on zero", 0b01110100);
+ Table.Instructions[Table.Count++] = ByteJump("jl", "Jump on less", 0b01111100);
+ Table.Instructions[Table.Count++] = ByteJump("jle", "Jump on less or equal", 0b01111110);
+ Table.Instructions[Table.Count++] = ByteJump("jb", "Jump on below", 0b01110010);
+ Table.Instructions[Table.Count++] = ByteJump("jbe", "Jump on below or equal", 0b01110110);
+ Table.Instructions[Table.Count++] = ByteJump("jp", "Jump on parity", 0b01111010);
+ Table.Instructions[Table.Count++] = ByteJump("jo", "Jump on overflow", 0b01110000);
+ Table.Instructions[Table.Count++] = ByteJump("js", "Jump on sign", 0b01111000);
+ Table.Instructions[Table.Count++] = ByteJump("jnz", "Jump on not zero", 0b01110101);
+ Table.Instructions[Table.Count++] = ByteJump("jnl", "Jump on not less", 0b01111101);
+ Table.Instructions[Table.Count++] = ByteJump("jnle", "Jump on not less or equal", 0b01111111);
+ Table.Instructions[Table.Count++] = ByteJump("jnb", "Jump on not below", 0b01110011);
+ Table.Instructions[Table.Count++] = ByteJump("jnbe", "Jump on not below or equal", 0b01110111);
+ Table.Instructions[Table.Count++] = ByteJump("jnp", "Jump on not par", 0b01111011);
+ Table.Instructions[Table.Count++] = ByteJump("jno", "Jump on not overflow", 0b01110001);
+ Table.Instructions[Table.Count++] = ByteJump("jns", "Jump on not sign", 0b01111001);
+ Table.Instructions[Table.Count++] = ByteJump("loop", "Loop CX times", 0b11100010);
+ Table.Instructions[Table.Count++] = ByteJump("loopz", "Loop while zero", 0b11100001);
+ Table.Instructions[Table.Count++] = ByteJump("loopnz", "Loop while not zero", 0b11100000);
+ Table.Instructions[Table.Count++] = ByteJump("jcxz", "Jump on CX zero", 0b11100011);
+#undef ByteJump
+
+ Table.Instructions[Table.Count++] =
+ {
+ .Name = "push",
+ .Description = "Register/memory",
+ .OperandsCount = 1,
+ .BytesCount = 2,
+ .Bytes =
+ {
+ {
+ .Op = 0b11111111,
+ .OpMask = 0b11111111,
+ },
+ {
+ .Op = 0b00110000,
+ .OpMask = 0b00111000,
+ .ModBitsAt = 7,
+ .RMBitsAt = 1,
+ }
+ }
+ };
+
+ Table.Instructions[Table.Count++] =
+ {
+ .Name = "push",
+ .Description = "Register",
+ .OperandsCount = 1,
+ .BytesCount = 1,
+ .Bytes =
+ {
+ {
+ .Op = 0b01010000,
+ .OpMask = 0b11111000,
+ .RegBitsAt = 1,
+ },
+ }
+ };
+
+ Table.Instructions[Table.Count++] =
+ {
+ .Name = "push",
+ .Description = "Segment register",
+ .OperandsCount = 1,
+ .HasSegmentRegister = true,
+ .BytesCount = 1,
+ .Bytes =
+ {
+ {
+ .Op = 0b00000110,
+ .OpMask = 0b11000111,
+ .RegBitsAt = 4,
+ },
+ }
+ };
+
+ if(ArgCount > 1)
+ {
+ int File = open(Args[1], O_RDONLY);
+ if(File != -1)
+ {
+ int BytesRead = 0;
+
+ printf("bits 16\n\n");
+
+ int KeepReading = true;
+ while(KeepReading)
+ {
+ u8 *ByteAt = Bytes;
+ BytesRead = ReadBytesFromFile(File, &ByteAt, 1);
+
+ if(BytesRead == 1)
+ {
+ for(u32 InstructionIndex = 0;
+ InstructionIndex < Table.Count;
+ InstructionIndex++)
+ {
+ instruction InsAt = Table.Instructions[InstructionIndex];
+
+ if((Bytes[0] & InsAt.Bytes[0].OpMask) == InsAt.Bytes[0].Op)
+ {
+ DebugLabel(ByteFound);
+ BytesRead = ReadBytesFromFile(File, &ByteAt, InsAt.BytesCount - BytesRead);
+
+ b32 HasMode = false;
+ b32 HasDisplacement = false;
+ b32 HasRegister = false;
+ b32 MemoryMode = false;
+ b32 RegisterMode = false;
+ b32 EffectiveAddressMode = false;
+ b32 Displacement8Bit = false;
+ b32 Displacement16Bit = false;
+ b32 DBitSet = false;
+ b32 SBitSet = false;
+ b32 VBitSet = false;
+ b32 WBitSet = false;
+ u8 RegBits = 0;
+ u8 ModBits = 0;
+ u8 RMBits = 0;
+ s16 DisplacementValue = 0;
+ s16 DataValue = 0;
+ s8 IncrementValue = 0;
+
+ char *InstructionName = InsAt.Name;
+#define OP_DEST 0
+#define OP_SOURCE 1
+ char Operands[2][255] = {};
+ char *SourceOperand = Operands[1];
+ char *DestOperand = Operands[0];
+ u32 NextOperand = OP_DEST;
+
+ if(InsAt.ToAccumulator)
+ {
+ NextOperand = OP_SOURCE;
+ }
+
+ for(u32 BytesIndex = 0;
+ BytesIndex < InsAt.BytesCount;
+ BytesIndex++)
+ {
+ u8 CurrentByte = Bytes[BytesIndex];
+ instruction_byte CurrentInsByte = InsAt.Bytes[BytesIndex];
+
+ if(CurrentInsByte.OpMask)
+ {
+ Assert((CurrentByte & CurrentInsByte.OpMask) == CurrentInsByte.Op);
+ }
+
+ SetBitFromBitAt(&DBitSet, CurrentByte, CurrentInsByte.DBitAt);
+ SetBitFromBitAt(&WBitSet, CurrentByte, CurrentInsByte.WBitAt);
+ SetBitFromBitAt(&SBitSet, CurrentByte, CurrentInsByte.SBitAt);
+ SetBitFromBitAt(&VBitSet, CurrentByte, CurrentInsByte.VBitAt);
+
+ if(CurrentInsByte.SubOpMask)
+ {
+ Assert(InsAt.SubInstructionsCount);
+
+ u8 SubInsBits = (CurrentByte & CurrentInsByte.SubOpMask);
+
+ b32 FoundSubInstruction = false;
+ sub_instruction ScanSubIns = {};
+ for(u32 SubInstructionsIndex = 0;
+ (SubInstructionsIndex < InsAt.SubInstructionsCount) && !FoundSubInstruction;
+ SubInstructionsIndex++)
+ {
+ ScanSubIns = InsAt.SubInstructions[SubInstructionsIndex];
+ FoundSubInstruction = (ScanSubIns.Op == SubInsBits);
+ }
+ Assert(FoundSubInstruction);
+
+ InstructionName = ScanSubIns.Name;
+ }
+
+ if(CurrentInsByte.ModBitsAt)
+ {
+ HasMode = true;
+ ModBits = ExtractBitsFromByte(CurrentByte, 0b11, CurrentInsByte.ModBitsAt);
+
+ if(ModBits == 0b00)
+ {
+ MemoryMode = true;
+ }
+ else if(ModBits == 0b01)
+ {
+ HasDisplacement = true;
+ Displacement8Bit = true;
+ }
+ else if(ModBits == 0b10)
+ {
+ HasDisplacement = true;
+ Displacement16Bit = true;
+ }
+ else if(ModBits == 0b11)
+ {
+ RegisterMode = true;
+ }
+ }
+
+ if(CurrentInsByte.RegBitsAt)
+ {
+ RegBits = ExtractBitsFromByte(CurrentByte, 0b111, CurrentInsByte.RegBitsAt);
+ HasRegister = true;
+ }
+
+ if(CurrentInsByte.RMBitsAt)
+ {
+ RMBits = ExtractBitsFromByte(CurrentByte, 0b111, CurrentInsByte.RMBitsAt);
+
+ if(MemoryMode && RMBits == 0b110)
+ {
+ MemoryMode = false;
+ EffectiveAddressMode = true;
+ }
+ }
+
+ } // for
+
+ DebugLabel(Parsed);
+
+ if(InsAt.HasAddress)
+ {
+ HasMode = true;
+ WBitSet = true;
+ EffectiveAddressMode = true;
+ }
+
+ if(HasRegister)
+ {
+ b32 IsWide = (WBitSet || InsAt.OperandsCount == 1);
+ u32 TargetOperand = OP_DEST;
+ char *OperandName = 0;
+
+ if(!InsAt.HasSegmentRegister)
+ {
+ OperandName = RegistersNames[RegBits][IsWide];
+ }
+ else
+ {
+ OperandName = SegmentRegistersNames[RegBits];
+ }
+
+ b32 OperandIsDest = (DBitSet ||
+ InsAt.HasImmediate ||
+ (InsAt.OperandsCount == 1));
+ TargetOperand = (OperandIsDest) ? OP_DEST : OP_SOURCE;
+ NextOperand = (OperandIsDest) ? OP_SOURCE : OP_DEST;
+
+ CStringCopy(Operands[TargetOperand], OperandName);
+ }
+
+
+ if(HasMode)
+ {
+ if(MemoryMode)
+ {
+ if(InsAt.OperandsCount == 1)
+ {
+ sprintf(Operands[NextOperand++], "%s [%s]", WBitSet ? "byte" : "word", DisplacementsNames[RMBits]);
+ }
+ else
+ {
+ sprintf(Operands[NextOperand++], "[%s]", DisplacementsNames[RMBits]);
+ }
+ }
+ else if(RegisterMode)
+ {
+ CStringCopy(Operands[NextOperand++], RegistersNames[RMBits][WBitSet]);
+ }
+ else if(HasDisplacement)
+ {
+ if(Displacement8Bit)
+ {
+ ReadBytesFromFile(File, &ByteAt, 1);
+ DisplacementValue = (s8)ByteAt[-1];
+ }
+ else if(Displacement16Bit)
+ {
+ ReadBytesFromFile(File, &ByteAt, 2);
+ DisplacementValue = ((s16)ByteAt[-1] << 8) | (s16)ByteAt[-2];
+ }
+ else
+ {
+ Assert(0);
+ }
+
+ if(DisplacementValue != 0)
+ {
+ if(InsAt.OperandsCount == 1)
+ {
+ b32 IsNegative = (DisplacementValue < 0);
+ sprintf(Operands[NextOperand++], "word [%s %c %d]",
+ DisplacementsNames[RMBits],
+ IsNegative ? '-' : '+',
+ IsNegative ? DisplacementValue * -1 : DisplacementValue);
+ }
+ else
+ {
+ b32 IsNegative = (DisplacementValue < 0);
+ sprintf(Operands[NextOperand++], "[%s %c %d]",
+ DisplacementsNames[RMBits],
+ IsNegative ? '-' : '+',
+ IsNegative ? DisplacementValue * -1 : DisplacementValue);
+ }
+ }
+ else
+ {
+ if(InsAt.OperandsCount == 1)
+ {
+ sprintf(Operands[OP_DEST], "%s [%s]", WBitSet ? "word" : "byte", DisplacementsNames[RMBits]);
+ }
+ else
+ {
+ sprintf(Operands[NextOperand++], "[%s]", DisplacementsNames[RMBits]);
+ }
+ }
+
+ }
+ else if(EffectiveAddressMode)
+ {
+ // NOTE(luca): Data is always 16-bit displacement, read 2 bytes.
+ ReadBytesFromFile(File, &ByteAt, 2);
+ DataValue = ((s16)ByteAt[-1] << 8) | (s16)ByteAt[-2];
+
+ if(InsAt.HasImmediate || InsAt.OperandsCount == 1)
+ {
+ sprintf(Operands[OP_DEST], "word [%d]", DataValue);
+ }
+ else
+ {
+ sprintf(Operands[NextOperand++], "[%d]", DataValue);
+ }
+
+ }
+ else
+ {
+ Assert(0);
+ }
+ }
+
+ if(InsAt.HasImmediate)
+ {
+ if(WBitSet && !SBitSet)
+ {
+ ReadBytesFromFile(File, &ByteAt, 2);
+ DataValue = (ByteAt[-1] << 8) | ByteAt[-2];
+ }
+ else
+ {
+ ReadBytesFromFile(File, &ByteAt, 1);
+ DataValue = ByteAt[-1];
+ }
+
+ if(MemoryMode || HasDisplacement)
+ {
+ sprintf(Operands[OP_SOURCE], "%s %d", WBitSet ? "word" : "byte", DataValue);
+ }
+ else
+ {
+ sprintf(Operands[OP_SOURCE], "%d", DataValue);
+ }
+ }
+
+ if(InsAt.ToAccumulator)
+ {
+ sprintf(Operands[OP_DEST], "%s", RegistersNames[ACCUMULATOR][WBitSet]);
+ }
+
+ if(InsAt.IsByteJump)
+ {
+ ReadBytesFromFile(File, &ByteAt, 1);
+ IncrementValue = (s8)ByteAt[-1];
+ IncrementValue += InsAt.BytesCount + 1;
+ b32 IsNegative = (IncrementValue < 0);
+ sprintf(Operands[NextOperand++], "$%c%d",
+ IsNegative ? '-' : '+',
+ IsNegative ? IncrementValue *= -1 : IncrementValue);
+ }
+
+ if(InsAt.FlipOperands)
+ {
+ Assert(InsAt.OperandsCount == 2);
+ Swap(char *, SourceOperand, DestOperand);
+ }
+
+ if(InsAt.OperandsCount == 2)
+ {
+ printf("%s %s, %s\n", InstructionName, DestOperand, SourceOperand);
+ }
+ else if(InsAt.OperandsCount == 1)
+ {
+ printf("%s %s\n", InstructionName, DestOperand);
+ }
+ else if(InsAt.OperandsCount == 0)
+ {
+ printf("%s\n", InstructionName);
+ }
+ else
+ {
+ Assert(0);
+ }
+
+ break;
+ } // if op
+ } // for ins
+ } // if bytesread
+ else if(BytesRead == -1)
+ {
+ fprintf(stderr, "Error while reading.\n");
+ KeepReading = false;
+ }
+ else if(BytesRead == 0)
+ {
+ KeepReading = false;
+ }
+ else
+ {
+ fprintf(stderr, "Read too many bytes.\n");
+ KeepReading = false;
+ }
+ } // while
+ } // if file
+ else
+ {
+ fprintf(stderr, "Could not open file.\n");
+ }
+ } // if argcount
+ else
+ {
+ fprintf(stderr, "Missing argument.\n"
+ "Usage: %s <assembly>\n", Args[0]);
+ }
+
+ return 0;
+} \ No newline at end of file
diff --git a/archived/less_old_sim8086/code/sim8086.h b/archived/less_old_sim8086/code/sim8086.h
new file mode 100644
index 0000000..136fcfe
--- /dev/null
+++ b/archived/less_old_sim8086/code/sim8086.h
@@ -0,0 +1,70 @@
+/* date = May 13th 2025 11:06 pm */
+
+#ifndef SIM8086_H
+#define SIM8086_H
+
+typedef uint64_t u64;
+typedef uint32_t u32;
+typedef uint16_t u16;
+typedef uint8_t u8;
+typedef int64_t s64;
+typedef int32_t s32;
+typedef int16_t s16;
+typedef int8_t s8;
+typedef s32 b32;
+typedef float r32;
+typedef double r64;
+#define false 0
+#define true 1
+
+#define global_variable static
+#define internal static
+#define local_persist static
+
+struct instruction_byte
+{
+ // NOTE(luca): All byte positions are 1-based so that 0 can mean that you do not have to test for this byte.
+ u8 Op;
+ u8 OpMask;
+ u8 SubOpMask;
+ u8 WBitAt;
+ u8 SBitAt;
+ u8 DBitAt;
+ u8 VBitAt;
+ u8 ModBitsAt;
+ u8 RegBitsAt;
+ u8 RMBitsAt;
+};
+struct sub_instruction
+{
+ u8 Op;
+ char *Name;
+};
+struct instruction
+{
+ char *Name;
+ char *Description;
+ u32 OperandsCount;
+ b32 HasSegmentRegister;
+ b32 HasImmediate;
+ b32 HasAddress;
+ b32 IsByteJump;
+ b32 ToAccumulator;
+ b32 FlipOperands;
+
+ u32 BytesCount;
+ instruction_byte Bytes[8];
+
+ // NOTE(luca): Sub instructions are instructions which do the same work but can have different names depending on a second opcode.
+ u32 SubInstructionsCount;
+ sub_instruction SubInstructions[8];
+};
+
+struct instruction_table
+{
+ instruction *Instructions;
+ u32 Count;
+ u32 Size;
+};
+
+#endif //SIM8086_H
diff --git a/archived/less_old_sim8086/listings/listing_0037_single_register_mov.asm b/archived/less_old_sim8086/listings/listing_0037_single_register_mov.asm
new file mode 100644
index 0000000..1b58e05
--- /dev/null
+++ b/archived/less_old_sim8086/listings/listing_0037_single_register_mov.asm
@@ -0,0 +1,19 @@
+; ========================================================================
+;
+; (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 37
+; ========================================================================
+
+bits 16
+
+mov cx, bx
diff --git a/archived/less_old_sim8086/listings/listing_0038_many_register_mov.asm b/archived/less_old_sim8086/listings/listing_0038_many_register_mov.asm
new file mode 100644
index 0000000..c157b91
--- /dev/null
+++ b/archived/less_old_sim8086/listings/listing_0038_many_register_mov.asm
@@ -0,0 +1,29 @@
+; ========================================================================
+;
+; (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 38
+; ========================================================================
+
+bits 16
+
+mov cx, bx
+mov ch, ah
+mov dx, bx
+mov si, bx
+mov bx, di
+mov al, cl
+mov ch, ch
+mov bx, ax
+mov bx, si
+mov sp, di
+mov bp, ax
diff --git a/archived/less_old_sim8086/listings/listing_0039_more_movs.asm b/archived/less_old_sim8086/listings/listing_0039_more_movs.asm
new file mode 100644
index 0000000..854fcb4
--- /dev/null
+++ b/archived/less_old_sim8086/listings/listing_0039_more_movs.asm
@@ -0,0 +1,47 @@
+; ========================================================================
+;
+; (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 39
+; ========================================================================
+
+bits 16
+
+; Register-to-register
+mov si, bx
+mov dh, al
+
+; 8-bit immediate-to-register
+mov cl, 12
+mov ch, -12
+
+; 16-bit immediate-to-register
+mov cx, 12
+mov cx, -12
+mov dx, 3948
+mov dx, -3948
+
+; Source address calculation
+mov al, [bx + si]
+mov bx, [bp + di]
+mov dx, [bp]
+
+; Source address calculation plus 8-bit displacement
+mov ah, [bx + si + 4]
+
+; Source address calculation plus 16-bit displacement
+mov al, [bx + si + 4999]
+
+; Dest address calculation
+mov [bx + di], cx
+mov [bp + si], cl
+mov [bp], ch
diff --git a/archived/less_old_sim8086/listings/listing_0040_challenge_movs.asm b/archived/less_old_sim8086/listings/listing_0040_challenge_movs.asm
new file mode 100644
index 0000000..966e47a
--- /dev/null
+++ b/archived/less_old_sim8086/listings/listing_0040_challenge_movs.asm
@@ -0,0 +1,38 @@
+; ========================================================================
+;
+; (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 40
+; ========================================================================
+
+bits 16
+
+; Signed displacements
+mov ax, [bx + di - 37]
+mov [si - 300], cx
+mov dx, [bx - 32]
+
+; Explicit sizes
+mov [bp + di], byte 7
+mov [di + 901], word 347
+
+; Direct address
+mov bp, [5]
+mov bx, [3458]
+
+; Memory-to-accumulator test
+mov ax, [2555]
+mov ax, [16]
+
+; Accumulator-to-memory test
+mov [2554], ax
+mov [15], ax
diff --git a/archived/less_old_sim8086/listings/listing_0041_add_sub_cmp_jnz.asm b/archived/less_old_sim8086/listings/listing_0041_add_sub_cmp_jnz.asm
new file mode 100644
index 0000000..6b79cf0
--- /dev/null
+++ b/archived/less_old_sim8086/listings/listing_0041_add_sub_cmp_jnz.asm
@@ -0,0 +1,121 @@
+; ========================================================================
+;
+; (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 41
+; ========================================================================
+
+bits 16
+
+add bx, [bx+si]
+add bx, [bp]
+add si, 2
+add bp, 2
+add cx, 8
+add bx, [bp + 0]
+add cx, [bx + 2]
+add bh, [bp + si + 4]
+add di, [bp + di + 6]
+add [bx+si], bx
+add [bp], bx
+add [bp + 0], bx
+add [bx + 2], cx
+add [bp + si + 4], bh
+add [bp + di + 6], di
+add byte [bx], 34
+add word [bp + si + 1000], 29
+add ax, [bp]
+add al, [bx + si]
+add ax, bx
+add al, ah
+add ax, 1000
+add al, -30
+add al, 9
+
+sub bx, [bx+si]
+sub bx, [bp]
+sub si, 2
+sub bp, 2
+sub cx, 8
+sub bx, [bp + 0]
+sub cx, [bx + 2]
+sub bh, [bp + si + 4]
+sub di, [bp + di + 6]
+sub [bx+si], bx
+sub [bp], bx
+sub [bp + 0], bx
+sub [bx + 2], cx
+sub [bp + si + 4], bh
+sub [bp + di + 6], di
+sub byte [bx], 34
+sub word [bx + di], 29
+sub ax, [bp]
+sub al, [bx + si]
+sub ax, bx
+sub al, ah
+sub ax, 1000
+sub al, -30
+sub al, 9
+
+cmp bx, [bx+si]
+cmp bx, [bp]
+cmp si, 2
+cmp bp, 2
+cmp cx, 8
+cmp bx, [bp + 0]
+cmp cx, [bx + 2]
+cmp bh, [bp + si + 4]
+cmp di, [bp + di + 6]
+cmp [bx+si], bx
+cmp [bp], bx
+cmp [bp + 0], bx
+cmp [bx + 2], cx
+cmp [bp + si + 4], bh
+cmp [bp + di + 6], di
+cmp byte [bx], 34
+cmp word [4834], 29
+cmp ax, [bp]
+cmp al, [bx + si]
+cmp ax, bx
+cmp al, ah
+cmp ax, 1000
+cmp al, -30
+cmp al, 9
+
+test_label0:
+jnz test_label1
+jnz test_label0
+test_label1:
+jnz test_label0
+jnz test_label1
+
+label:
+je label
+jl label
+jle label
+jb label
+jbe label
+jp label
+jo label
+js label
+jne label
+jnl label
+jg label
+jnb label
+ja label
+jnp label
+jno label
+jns label
+loop label
+loopz label
+loopnz label
+jcxz label
diff --git a/archived/less_old_sim8086/listings/listing_0042_completionist_decode.asm b/archived/less_old_sim8086/listings/listing_0042_completionist_decode.asm
new file mode 100644
index 0000000..86ed278
--- /dev/null
+++ b/archived/less_old_sim8086/listings/listing_0042_completionist_decode.asm
@@ -0,0 +1,451 @@
+; ========================================================================
+;
+; (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 42
+; ========================================================================
+
+;
+; NOTE(casey): This is not meant to be a real compliance test for 8086
+; disassemblers. It's just a reasonable selection of opcodes and patterns
+; to use as a first pass in making sure a disassembler handles a large
+; cross-section of the encoding. To be absolutely certain you haven't
+; missed something, you would need a more exhaustive listing!
+;
+
+bits 16
+
+mov si, bx
+mov dh, al
+mov cl, 12
+mov ch, -12
+mov cx, 12
+mov cx, -12
+mov dx, 3948
+mov dx, -3948
+mov al, [bx + si]
+mov bx, [bp + di]
+mov dx, [bp]
+mov ah, [bx + si + 4]
+mov al, [bx + si + 4999]
+mov [bx + di], cx
+mov [bp + si], cl
+mov [bp], ch
+mov ax, [bx + di - 37]
+mov [si - 300], cx
+mov dx, [bx - 32]
+mov [bp + di], byte 7
+mov [di + 901], word 347
+mov bp, [5]
+mov bx, [3458]
+mov ax, [2555]
+mov ax, [16]
+mov [2554], ax
+mov [15], ax
+
+push word [bp + si]
+push word [3000]
+push word [bx + di - 30]
+push cx
+push ax
+push dx
+push cs
+
+pop word [bp + si]
+pop word [3]
+pop word [bx + di - 3000]
+pop sp
+pop di
+pop si
+pop ds
+
+xchg ax, [bp - 1000]
+xchg [bx + 50], bp
+
+xchg ax, ax
+xchg ax, dx
+xchg ax, sp
+xchg ax, si
+xchg ax, di
+
+xchg cx, dx
+xchg si, cx
+xchg cl, ah
+
+in al, 200
+in al, dx
+in ax, dx
+
+out 44, ax
+out dx, al
+
+xlat
+lea ax, [bx + di + 1420]
+lea bx, [bp - 50]
+lea sp, [bp - 1003]
+lea di, [bx + si - 7]
+
+lds ax, [bx + di + 1420]
+lds bx, [bp - 50]
+lds sp, [bp - 1003]
+lds di, [bx + si - 7]
+
+les ax, [bx + di + 1420]
+les bx, [bp - 50]
+les sp, [bp - 1003]
+les di, [bx + si - 7]
+
+lahf
+sahf
+pushf
+popf
+
+add cx, [bp]
+add dx, [bx + si]
+add [bp + di + 5000], ah
+add [bx], al
+add sp, 392
+add si, 5
+add ax, 1000
+add ah, 30
+add al, 9
+add cx, bx
+add ch, al
+
+adc cx, [bp]
+adc dx, [bx + si]
+adc [bp + di + 5000], ah
+adc [bx], al
+adc sp, 392
+adc si, 5
+adc ax, 1000
+adc ah, 30
+adc al, 9
+adc cx, bx
+adc ch, al
+
+inc ax
+inc cx
+inc dh
+inc al
+inc ah
+inc sp
+inc di
+inc byte [bp + 1002]
+inc word [bx + 39]
+inc byte [bx + si + 5]
+inc word [bp + di - 10044]
+inc word [9349]
+inc byte [bp]
+
+aaa
+daa
+
+sub cx, [bp]
+sub dx, [bx + si]
+sub [bp + di + 5000], ah
+sub [bx], al
+sub sp, 392
+sub si, 5
+sub ax, 1000
+sub ah, 30
+sub al, 9
+sub cx, bx
+sub ch, al
+
+sbb cx, [bp]
+sbb dx, [bx + si]
+sbb [bp + di + 5000], ah
+sbb [bx], al
+sbb sp, 392
+sbb si, 5
+sbb ax, 1000
+sbb ah, 30
+sbb al, 9
+sbb cx, bx
+sbb ch, al
+
+dec ax
+dec cx
+dec dh
+dec al
+dec ah
+dec sp
+dec di
+dec byte [bp + 1002]
+dec word [bx + 39]
+dec byte [bx + si + 5]
+dec word [bp + di - 10044]
+dec word [9349]
+dec byte [bp]
+
+neg ax
+neg cx
+neg dh
+neg al
+neg ah
+neg sp
+neg di
+neg byte [bp + 1002]
+neg word [bx + 39]
+neg byte [bx + si + 5]
+neg word [bp + di - 10044]
+neg word [9349]
+neg byte [bp]
+
+cmp bx, cx
+cmp dh, [bp + 390]
+cmp [bp + 2], si
+cmp bl, 20
+cmp byte [bx], 34
+cmp ax, 23909
+
+aas
+das
+
+mul al
+mul cx
+mul word [bp]
+mul byte [bx + di + 500]
+
+imul ch
+imul dx
+imul byte [bx]
+imul word [9483]
+
+aam
+
+div bl
+div sp
+div byte [bx + si + 2990]
+div word [bp + di + 1000]
+
+idiv ax
+idiv si
+idiv byte [bp + si]
+idiv word [bx + 493]
+
+aad
+cbw
+cwd
+
+not ah
+not bl
+not sp
+not si
+not word [bp]
+not byte [bp + 9905]
+
+shl ah, 1
+shr ax, 1
+sar bx, 1
+rol cx, 1
+ror dh, 1
+rcl sp, 1
+rcr bp, 1
+
+shl word [bp + 5], 1
+shr byte [bx + si - 199], 1
+sar byte [bx + di - 300], 1
+rol word [bp], 1
+ror word [4938], 1
+rcl byte [3], 1
+rcr word [bx], 1
+
+shl ah, cl
+shr ax, cl
+sar bx, cl
+rol cx, cl
+ror dh, cl
+rcl sp, cl
+rcr bp, cl
+
+shl word [bp + 5], cl
+shr word [bx + si - 199], cl
+sar byte [bx + di - 300], cl
+rol byte [bp], cl
+ror byte [4938], cl
+rcl byte [3], cl
+rcr word [bx], cl
+
+and al, ah
+and ch, cl
+and bp, si
+and di, sp
+and al, 93
+and ax, 20392
+and [bp + si + 10], ch
+and [bx + di + 1000], dx
+and bx, [bp]
+and cx, [4384]
+and byte [bp - 39], 239
+and word [bx + si - 4332], 10328
+
+test bx, cx
+test dh, [bp + 390]
+test [bp + 2], si
+test bl, 20
+test byte [bx], 34
+test ax, 23909
+
+or al, ah
+or ch, cl
+or bp, si
+or di, sp
+or al, 93
+or ax, 20392
+or [bp + si + 10], ch
+or [bx + di + 1000], dx
+or bx, [bp]
+or cx, [4384]
+or byte [bp - 39], 239
+or word [bx + si - 4332], 10328
+
+xor al, ah
+xor ch, cl
+xor bp, si
+xor di, sp
+xor al, 93
+xor ax, 20392
+xor [bp + si + 10], ch
+xor [bx + di + 1000], dx
+xor bx, [bp]
+xor cx, [4384]
+xor byte [bp - 39], 239
+xor word [bx + si - 4332], 10328
+
+rep movsb
+rep cmpsb
+rep scasb
+rep lodsb
+rep movsw
+rep cmpsw
+rep scasw
+rep lodsw
+
+; NOTE(casey): Special thanks (as always!) to Mārtiņš Možeiko for figuring out why NASM
+; wouldn't compile "rep stds" instructions. It was because it was a misprint in the 8086
+; manual! It was really just "rep stos", which of course is still in x64, and NASM
+; assembles it just fine.
+rep stosb
+rep stosw
+
+call [39201]
+call [bp - 100]
+call sp
+call ax
+
+jmp ax
+jmp di
+jmp [12]
+jmp [4395]
+
+ret -7
+ret 500
+ret
+
+label:
+je label
+jl label
+jle label
+jb label
+jbe label
+jp label
+jo label
+js label
+jne label
+jnl label
+jg label
+jnb label
+ja label
+jnp label
+jno label
+jns label
+loop label
+loopz label
+loopnz label
+jcxz label
+
+int 13
+int3
+
+into
+iret
+
+clc
+cmc
+stc
+cld
+std
+cli
+sti
+hlt
+wait
+
+lock not byte [bp + 9905]
+lock xchg [100], al
+
+mov al, cs:[bx + si]
+mov bx, ds:[bp + di]
+mov dx, es:[bp]
+mov ah, ss:[bx + si + 4]
+
+and ss:[bp + si + 10], ch
+or ds:[bx + di + 1000], dx
+xor bx, es:[bp]
+cmp cx, es:[4384]
+test byte cs:[bp - 39], 239
+sbb word cs:[bx + si - 4332], 10328
+
+lock not byte CS:[bp + 9905]
+
+;
+; NOTE(casey): These were not in the original homework set, but have been added since, as people
+; found instruction encodings that were not previously covered. Thank you to everyone who
+; submitted test cases!
+;
+
+call 123:456
+jmp 789:34
+
+mov [bx+si+59],es
+
+jmp 2620
+call 11804
+
+retf 17556
+ret 17560
+retf
+ret
+
+call [bp+si-0x3a]
+call far [bp+si-0x3a]
+jmp [di]
+jmp far [di]
+
+jmp 21862:30600
+
+;
+; TODO(casey): I would like to uncomment this, but as far as I can tell, NASM doesn't recognize the ESC instruction :(
+; so even if I just force the assembler to output the bits here, our disasm will fail to assemble because it will (correctly!)
+; print the esc instruction and NASM will error because it doesn't know what that is.
+;
+; esc 938,ax
+;
+
+;
+; TODO(casey): According to NASM, "rep movsb" is "not lockable". However the 8086 manual seems to think it is, and
+; even describes what happens when you you lock a rep: the lock is held for the duration of the rep operation. So...
+; yeah. Not sure why this doesn't work in NASM:
+;
+; lock rep movsb
+; \ No newline at end of file
diff --git a/archived/less_old_sim8086/misc/test_listing b/archived/less_old_sim8086/misc/test_listing
new file mode 100755
index 0000000..472c0d2
--- /dev/null
+++ b/archived/less_old_sim8086/misc/test_listing
@@ -0,0 +1,50 @@
+#!/bin/sh
+
+NoColor=
+if [ "$1" = "--no-color" ]
+then
+ NoColor=1
+ shift
+fi
+
+ThisDir="$(dirname "$(readlink -f "$0")")"
+
+for File in $@
+do
+ File="$(readlink -f "$File")"
+ [ "$File" ] || exit 1
+
+ (
+ cd "$ThisDir"
+
+ SourceFile="$File"
+ SourceFile="${File%.asm}.asm"
+ [ -r "$SourceFile" ] || exit 1
+
+ ErrorFile="../build/error"
+ TestSource="../build/first"
+ OutFile="../build/$(basename "${SourceFile%.asm}")"
+ nasm -o "$OutFile" "$SourceFile" 2> "$ErrorFile"
+ ../build/sim8086 "$OutFile" > "$TestSource".asm 2>> "$ErrorFile"
+ nasm -o "${TestSource}" "$TestSource".asm 2>> "$ErrorFile"
+
+ RelPath="$(realpath --relative-to=. "$SourceFile")"
+ if diff -q "$TestSource" "$OutFile" > /dev/null 2>> "$ErrorFile"
+ then
+ if [ "$NoColor" ]
+ then
+ printf ' PASSED: '\''%s'\''\n' "$RelPath"
+ else
+ printf '\033[32m PASSED: '\''%s'\''\033[0m\n' "$RelPath"
+ fi
+ else
+ if [ "$NoColor" ]
+ then
+ printf ' FAILED: '\''%s'\''\n' "$RelPath"
+ else
+ printf '\033[31m FAILED: '\''%s'\''\033[0m\n' "$RelPath"
+ fi
+ cat "$ErrorFile" | sed 's/.*/ &/'
+ fi
+ )
+done
diff --git a/archived/less_old_sim8086/misc/test_source_line_by_line b/archived/less_old_sim8086/misc/test_source_line_by_line
new file mode 100755
index 0000000..dbf657c
--- /dev/null
+++ b/archived/less_old_sim8086/misc/test_source_line_by_line
@@ -0,0 +1,80 @@
+#!/bin/sh
+
+PauseOnFail=
+if [ "$1" = "--pause-on-fail" ]
+then
+ PauseOnFail=1
+ shift
+fi
+
+NoColor=
+if [ "$1" = "--no-color" ]
+then
+ NoColor=1
+ shift
+fi
+
+if [ -z "$1" ]
+then
+ >&2 printf 'Usage: single_tester.sh <source>\n'
+ return 1
+fi
+
+ThisDir="$(dirname "$(readlink -f "$0")")"
+
+for File in $@
+do
+ SourceFile="$(readlink -f "$File")"
+ [ "$SourceFile" ] || exit 1
+ SourceFile="${SourceFile%.asm}.asm"
+ [ -r "$SourceFile" ] || exit 1
+ >&2 printf 'File: %s\n' "$File"
+
+ (
+ cd "$ThisDir"
+
+ Stripped="${SourceFile%.asm}"
+ OutName="../build/$(basename "$Stripped")"
+
+ grep -v '^$\|^;\|^bits' "$SourceFile" |
+ while read -r line
+ do
+ first="${OutName}_first"
+ second="${OutName}_second"
+ error="${OutName}_error"
+
+ printf 'bits 16\n%s\n' "$line" > "$first".asm
+
+ nasm -o "$first" "$first".asm 2> "$error"
+ ../build/sim8086 "$first" > "$second".asm 2> "$error"
+ nasm -o "$second" "$second".asm 2>> "$error"
+
+ if diff -q "$first" "$second" > /dev/null 2>> "$error"
+ then
+ if [ "$NoColor" ]
+ then
+ printf ' PASSED: '\''%s'\''\n' "$line"
+ else
+ printf '\033[32m PASSED: '\''%s'\''\033[0m\n' "$line"
+ fi
+ else
+ if [ "$NoColor" ]
+ then
+ printf ' FAILED: '\''%s'\''\n' "$SourceFile"
+ else
+ printf '\033[31m FAILED: '\''%s'\''\033[0m\n' "$SourceFile"
+ fi
+ cat "$error" | sed 's/.*/ &/'
+ printf ' listing> %s\n' "$line"
+ printf ' sim8086> %s\n' "$(grep -v '^$\|^;\|bits' "$second".asm)"
+
+ if [ "$PauseOnFail" ]
+ then
+ exit
+ fi
+
+ fi
+ rm -f "$error" "$second" "$second".asm "$first" "$first".asm
+ done
+ )
+done
diff --git a/archived/less_old_sim8086/project.4coder b/archived/less_old_sim8086/project.4coder
new file mode 100644
index 0000000..0b2c2fb
--- /dev/null
+++ b/archived/less_old_sim8086/project.4coder
@@ -0,0 +1,43 @@
+version(2);
+project_name = "sim8086";
+patterns = {
+"*.c",
+"*.cpp",
+"*.h",
+"*.m",
+"*.bat",
+"*.sh",
+"*.4coder",
+};
+blacklist_patterns = {
+"_old.*",
+};
+load_paths_base = {
+ { ".", .relative = true, .recursive = true, },
+};
+load_paths = {
+ .win = load_paths_base,
+ .linux = load_paths_base,
+ .mac = load_paths_base,
+};
+
+commands = {
+ .build = { .out = "*compilation*", .footer_panel = true, .save_dirty_files = true,
+ .linux = "./code/build.sh",
+ .mac = "./code/build.sh", },
+ .build_release = { .out = "*compilation*", .footer_panel = false, .save_dirty_files = false,
+ .win = ".\code\build.bat release",
+ .linux = "./code/build.sh --release",
+ .mac = "./code/build.sh --release", },
+ .test_current = { .out = "*tests*", .footer_panel = false, .save_dirty_files = false,
+ .linux = "./misc/test_source_line_by_line --pause-on-fail --no-color ./listings/listing_0042_completionist_decode.asm" },
+ .test_all = { .out = "*tests*", .footer_panel = false, .save_dirty_files = false,
+ .linux = "./misc/test_listing --no-color ./listings/listing_0037_single_register_mov.asm ./listings/listing_0038_many_register_mov.asm ./listings/listing_0039_more_movs.asm ./listings/listing_0040_challenge_movs.asm ./listings/listing_0041_add_sub_cmp_jnz.asm ./listings/listing_0042*" },
+ .debug = { .linux = "gf2 ./build/sim8086", },
+};
+fkey_command = {
+.F1 = "build",
+.F2 = "build_release",
+.F3 = "test_current",
+.F4 = "test_all",
+};