summaryrefslogtreecommitdiff
path: root/archived
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
checkpoint
Diffstat (limited to 'archived')
-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
-rwxr-xr-xarchived/old_sim8086/8086disassemblerbin0 -> 23272 bytes
-rw-r--r--archived/old_sim8086/8086disassembler.c157
-rwxr-xr-xarchived/old_sim8086/build.sh6
-rw-r--r--archived/old_sim8086/listing_0037_single_register_mov1
-rw-r--r--archived/old_sim8086/listing_0037_single_register_mov.asm19
-rw-r--r--archived/old_sim8086/listing_0038_many_register_mov1
-rw-r--r--archived/old_sim8086/listing_0038_many_register_mov.asm29
-rw-r--r--archived/sim8086_old.c596
42 files changed, 2719 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",
+};
diff --git a/archived/old_sim8086/8086disassembler b/archived/old_sim8086/8086disassembler
new file mode 100755
index 0000000..17185c7
--- /dev/null
+++ b/archived/old_sim8086/8086disassembler
Binary files differ
diff --git a/archived/old_sim8086/8086disassembler.c b/archived/old_sim8086/8086disassembler.c
new file mode 100644
index 0000000..91e1a59
--- /dev/null
+++ b/archived/old_sim8086/8086disassembler.c
@@ -0,0 +1,157 @@
+/*
+ 8086 asm disassembler
+ For now this assumes that instructions are two bytes long.
+*/
+
+#include <stdio.h>
+#include <string.h>
+
+#define INSTRUCTION_MASK 0b11111100
+#define D_MASK (1 << 1)
+#define W_MASK 1
+#define REG_MASK 0b00111000
+#define MOD_MASK 0b00000111
+#define INSTRUCTION_MOV 0b10001000
+
+void print_reg(unsigned char reg, int wide_flag);
+
+int main(int argc, char **argv)
+{
+ FILE *file;
+ char *filename = argv[1];
+
+ if (argc < 2)
+ {
+ printf("No argument provided.\n");
+ return 1;
+ }
+
+ file = fopen(filename ,"rb");
+
+ if (file == NULL)
+ {
+ printf("File, %s not found.\n", filename);
+ return 1;
+ }
+
+ char file_byte;
+ unsigned char reg, mod, c;
+
+ /* flags */
+ int is_reg_destination = 0;
+ int is_wide_operation = 0;
+ char instruction[4];
+
+ /* print useful header */
+ printf("; %s disassembly:\n", filename);
+ printf("bits 16\n");
+
+
+ while ((file_byte = fgetc(file)) != EOF)
+ {
+ /* get the six first instruction bits */
+ c = file_byte & INSTRUCTION_MASK;
+ if (c == INSTRUCTION_MOV)
+ strcpy(instruction, "mov\0");
+ else
+ strcpy(instruction, "ERR\0");
+
+ /* check D bit */
+ /* NOTE: This shift could be defined to show that this is the D-mask */
+ c = file_byte & D_MASK;
+ is_reg_destination = c ? 1 : 0;
+
+ /* check W bit */
+ c = file_byte & 1;
+ is_wide_operation = c ? 1 : 0;
+
+ file_byte = fgetc(file);
+
+ /* get REG */
+ c = file_byte & REG_MASK;
+ reg = c >> 3;
+
+ /* get R/M */
+ c = file_byte & MOD_MASK;
+ mod = c;
+
+ /* print the decoded instructions */
+ printf("%s ", instruction);
+
+ /* print operands */
+ if (is_reg_destination)
+ print_reg(reg, is_wide_operation);
+ else
+ print_reg(mod, is_wide_operation);
+ printf(", ");
+ if (is_reg_destination)
+ print_reg(mod, is_wide_operation);
+ else
+ print_reg(reg, is_wide_operation);
+
+ printf("\n");
+ }
+
+ fclose(file);
+
+ return 0;
+}
+
+void print_reg(unsigned char reg, int wide_flag)
+{
+ switch (reg)
+ {
+ case 0b000:
+ if (wide_flag)
+ printf("ax");
+ else
+ printf("al");
+ break;
+ case 0b001:
+ if (wide_flag)
+ printf("cx");
+ else
+ printf("cl");
+ break;
+ case 0b010:
+ if (wide_flag)
+ printf("dx");
+ else
+ printf("dl");
+ break;
+ case 0b011:
+ if (wide_flag)
+ printf("bx");
+ else
+ printf("bl");
+ break;
+ case 0b100:
+ if (wide_flag)
+ printf("sp");
+ else
+ printf("ah");
+ break;
+ case 0b101:
+ if (wide_flag)
+ printf("bp");
+ else
+ printf("ch");
+ break;
+ case 0b110:
+ if (wide_flag)
+ printf("si");
+ else
+ printf("dh");
+ break;
+ case 0b111:
+ if (wide_flag)
+ printf("di");
+ else
+ printf("dh");
+ break;
+ default:
+ /* unknown register */
+ printf("ER");
+ break;
+ }
+} \ No newline at end of file
diff --git a/archived/old_sim8086/build.sh b/archived/old_sim8086/build.sh
new file mode 100755
index 0000000..53d5835
--- /dev/null
+++ b/archived/old_sim8086/build.sh
@@ -0,0 +1,6 @@
+#!/bin/sh
+set -ex
+
+gcc -ggdb -Wall 8086disassembler.c -o 8086disassembler
+nasm -o listing_0037_single_register_mov listing_0037_single_register_mov.asm
+nasm -o listing_0038_many_register_mov listing_0038_many_register_mov.asm
diff --git a/archived/old_sim8086/listing_0037_single_register_mov b/archived/old_sim8086/listing_0037_single_register_mov
new file mode 100644
index 0000000..93b300d
--- /dev/null
+++ b/archived/old_sim8086/listing_0037_single_register_mov
@@ -0,0 +1 @@
+ \ No newline at end of file
diff --git a/archived/old_sim8086/listing_0037_single_register_mov.asm b/archived/old_sim8086/listing_0037_single_register_mov.asm
new file mode 100644
index 0000000..1b58e05
--- /dev/null
+++ b/archived/old_sim8086/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/old_sim8086/listing_0038_many_register_mov b/archived/old_sim8086/listing_0038_many_register_mov
new file mode 100644
index 0000000..5605230
--- /dev/null
+++ b/archived/old_sim8086/listing_0038_many_register_mov
@@ -0,0 +1 @@
+وډމȈÉ \ No newline at end of file
diff --git a/archived/old_sim8086/listing_0038_many_register_mov.asm b/archived/old_sim8086/listing_0038_many_register_mov.asm
new file mode 100644
index 0000000..c157b91
--- /dev/null
+++ b/archived/old_sim8086/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/sim8086_old.c b/archived/sim8086_old.c
new file mode 100644
index 0000000..fbc20dc
--- /dev/null
+++ b/archived/sim8086_old.c
@@ -0,0 +1,596 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+#include <fcntl.h>
+#include <stdint.h>
+#include <signal.h>
+
+#ifdef DEBUG
+#define Assert(Expr) \
+if (Expr) \
+{ \
+raise(SIGTRAP); \
+}
+#else
+#define Assert(Expr) ;
+#endif
+
+void
+print_binary(uint8_t Byte)
+{
+ printf(" ");
+ int Count = 8;
+ while (Count--)
+ {
+ printf("%d", Byte >> 7);
+ Byte <<= 1;
+ }
+ printf("\n");
+}
+
+int main(int ArgC, char *Args[])
+{
+ if (ArgC < 2)
+ {
+ fprintf(stderr, "No argument provided.\n");
+ }
+ else
+ {
+ char *Filename = Args[1];
+ int Ret = 0;
+ int FD = 0;
+ int Filesize = 0;
+ struct stat StatBuffer = {0};
+ uint8_t *Buffer = 0;
+
+ FD = open(Filename, O_RDONLY);
+ if (FD == -1)
+ {
+ fprintf(stderr, "Failed to open file '%s'.\n", Filename);
+ }
+ else
+ {
+ Ret = fstat(FD, &StatBuffer);
+ if (Ret == -1)
+ {
+ fprintf(stderr, "Failed to get file stats.\n");
+ return 1;
+ }
+ else
+ {
+ Filesize = StatBuffer.st_size;
+ if (!Filesize)
+ {
+ fprintf(stderr, "Cannot disassemble empty file.\n");
+ return 1;
+ }
+
+ Buffer = mmap(0, Filesize, PROT_READ, MAP_FILE | MAP_SHARED, FD, 0);
+ if (Buffer == (void*)-1)
+ {
+ fprintf(stderr, "Failed to allocate buffer for file.\n");
+ return 1;
+ }
+ else
+ {
+ printf("; %s:\n", Filename);
+ printf("bits 16\n");
+
+#define MOV_RM_REG(Byte) ((Byte & 0b11111100) == 0b10001000)
+#define MOV_IM_REG(Byte) ((Byte & 0b11110000) == 0b10110000)
+#define MOV_IM_RM(Byte) ((Byte & 0b11111110) == 0b11000110)
+#define MOV_MEM_ACC(Byte) ((Byte & 0b11111110) == 0b10100000)
+#define MOV_ACC_MEM(Byte) ((Byte & 0b11111110) == 0b10100010)
+#define ARITH_RM_RM(Byte) ((Byte & 0b11000100) == 0b00000000)
+#define ARITH_IM_RM(Byte) ((Byte & 0b11111100) == 0b10000000)
+#define ARITH_IM_ACC(Byte) ((Byte & 0b11000100) == 0b00000100)
+ // NOTE(luca): Arithmetic operations add, sub and cmp have an octal field to
+ // differentiate between them.
+ // 00 000 0 dw -> ADD
+ // 00 101 0 dw -> SUB
+ // 00 111 0 dw -> CMP
+
+#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
+ char *JumpOperations[] = {
+ [JE] = "je",
+ [JNZ] = "jnz",
+ [JL] = "jl",
+ [JLE] = "jle",
+ [JB] = "jb",
+ [JBE] = "jbe",
+ [JP] = "jp",
+ [JO] = "jo",
+ [JS] = "js",
+ [JNL] = "jnl",
+ [JG] = "jg",
+ [JNB] = "jnb",
+ [JA] = "ja",
+ [JNP] = "jnp",
+ [JNO] = "jno",
+ [JNS] = "jns",
+ [LOOP] = "loop",
+ [LOOPZ] = "loopz",
+ [LOOPNZ] = "loopnz",
+ [JCXZ] = "jcxz",
+ };
+
+ // NOTE(luca): See 4-20 in the manual
+ // The following arrays are in order such that hey can be indexed with the r/m or reg field.
+ char *Registers[][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
+ char *Displacements[] = {
+ [0b000] = "bx + si",
+ [0b001] = "bx + di",
+ [0b010] = "bp + si",
+ [0b011] = "bp + di",
+ [0b100] = "si",
+ [0b101] = "di",
+ [0b110] = "bp",
+ [0b111] = "bx"
+ };
+
+ for (int At = 0; At < Filesize; At++)
+ {
+ uint8_t Byte1 = Buffer[At];
+
+ if (MOV_RM_REG(Byte1))
+ {
+ // register/memory to/from register
+ // no displacement except when r/m is110
+
+#define MOD(Byte1, Mask) ((Byte1 & 0b11000000) == (Mask << 6))
+
+ int DSet = Byte1 & (1 << 1);
+ // NOTE(Luca): Truncated to a boolean so that it can index the Registers array.
+ int WSet = Byte1 & (1 << 0) ? 1 : 0;
+ uint8_t Byte2 = Buffer[++At];
+ int RM = Byte2 & 0b111;
+ int REG = (Byte2 >> 3) & 0b111;
+
+ if (MOD(Byte2, 0b00))
+ {
+ // memory mode no displacement
+
+ if (RM == 0b110)
+ {
+ // exception, 16 bit displacement
+ uint8_t DispL = Buffer[++At];
+ uint8_t DispH = Buffer[++At];
+ int Displacement = (DispH << 8) + DispL;
+
+ // NOTE(Luca): Since a 16 bit displacement follows, shouldn't W bit always be set?
+ printf("mov %s, [%d]\n", Registers[REG][WSet], Displacement);
+ }
+ else
+ {
+ if (DSet)
+ {
+ printf("mov %s, [%s]\n", Registers[REG][WSet], Displacements[RM]);
+ }
+ else
+ {
+ printf("mov [%s], %s\n", Displacements[RM], Registers[REG][WSet]);
+ }
+ }
+
+ }
+ else if (MOD(Byte2, 0b01))
+ {
+ // 8 bit displacement
+ uint8_t DispL = Buffer[++At];
+ int8_t Displacement = DispL;
+ char Sign = (Displacement < 0) ? '-' : '+';
+ Displacement = abs(Displacement);
+
+ if (DSet)
+ {
+ if (Displacement)
+ {
+ printf("mov %s, [%s %c %d]\n", Registers[REG][WSet], Displacements[RM], Sign, Displacement);
+ }
+ else
+ {
+ printf("mov %s, [%s]\n", Registers[REG][WSet], Displacements[RM]);
+ }
+ }
+ else
+ {
+ if (Displacement)
+ {
+ printf("mov [%s %c %d], %s\n", Displacements[RM], Sign, Displacement, Registers[REG][WSet]);
+ }
+ else
+ {
+ printf("mov [%s], %s\n", Displacements[RM], Registers[REG][WSet]);
+ }
+ }
+ }
+ else if (MOD(Byte2, 0b10))
+ {
+ // 16 bit displacement
+ uint8_t DispL = Buffer[++At];
+ uint8_t DispH = Buffer[++At];
+ int16_t Displacement = DispL + (DispH << 8);
+ char Sign = (Displacement < 0) ? '-' : '+';
+ Displacement = abs(Displacement);
+
+ if (DSet)
+ {
+ if (Displacement)
+ {
+ printf("mov %s, [%s %c %d]\n", Registers[REG][WSet], Displacements[RM], Sign, Displacement);
+ }
+ else
+ {
+ printf("mov %s, [%s]\n", Registers[REG][WSet], Displacements[RM]);
+ }
+ }
+ else
+ {
+ if (Displacement)
+ {
+ printf("mov [%s %c %d], %s\n", Displacements[RM], Sign, Displacement, Registers[REG][WSet]);
+ }
+ else
+ {
+ printf("mov [%s], %s\n", Displacements[RM], Registers[REG][WSet]);
+ }
+ }
+ }
+ else if (MOD(Byte2, 0b11))
+ {
+ // register mode
+ printf("mov %s, %s\n", Registers[RM][WSet], Registers[REG][WSet]);
+ }
+
+ }
+ else if (MOV_IM_REG(Byte1))
+ {
+ // Immediate to register
+ int WSet = Byte1 & (1 << 3) ? 1 : 0;
+ int REG = Byte1 & 0b111;
+ uint8_t DataL = Buffer[++At];
+
+ if (WSet)
+ {
+ uint8_t DataH = Buffer[++At];
+ uint16_t Immediate = (DataH << 8) + DataL;
+ printf("mov %s, %d\n", Registers[REG][WSet], Immediate);
+ }
+ else
+ {
+ uint16_t Immediate = DataL;
+ printf("mov %s, %d\n", Registers[REG][WSet], Immediate);
+ }
+
+ }
+ else if (MOV_IM_RM(Byte1))
+ {
+ // Immediate to register/memory
+ int WSet = Byte1 & 1;
+ uint8_t Byte2 = Buffer[++At];
+ int MOD = (Byte2 & 0b10000000) >> 6;
+ int RM = Byte2 & 0b111;
+ Assert(0);
+
+ if (MOD == 0b00)
+ {
+ // memory mode no displacement
+ uint8_t DataL = Buffer[++At];
+ char *OperationSize = 0;
+ uint8_t Immediate = DataL;
+
+ if (WSet)
+ {
+ uint8_t DataH = Buffer[++At];
+ OperationSize = "word" ;
+ Immediate += DataH << 8;
+ }
+ else
+ {
+ OperationSize = "byte";
+ }
+
+ printf("mov [%s], %s %d\n", Displacements[RM], OperationSize, Immediate);
+ }
+ else if (MOD == 0b01)
+ {
+ // memory mode 8 bit displacement
+ uint8_t DispL = Buffer[++At];
+ int8_t Displacement = DispL;
+ char Sign = (Displacement < 0) ? '-' : '+';
+
+ if (WSet)
+ {
+ uint8_t DataL = Buffer[++At];
+ uint8_t DataH = Buffer[++At];
+ uint16_t Immediate = DataL + (DataH << 8);
+ printf("mov [%s %c %d], %d", Displacements[RM], Sign, Displacement, Immediate);
+ }
+ else
+ {
+ uint8_t Immediate = Buffer[++At];
+ printf("mov [%s %c %d], %d", Displacements[RM], Sign, Displacement, Immediate);
+ }
+ }
+ else if (MOD == 0b10)
+ {
+ // memory mode 16 bit displacement
+
+ uint8_t Byte3 = Buffer[++At];
+ uint8_t Byte4 = Buffer[++At];
+
+ int16_t Displacement = Byte3 + (Byte4 << 8);
+ char Sign = (Displacement < 0) ? '-' : '+';
+
+ if (WSet)
+ {
+ uint8_t Byte5 = Buffer[++At];
+ uint8_t Byte6 = Buffer[++At];
+ uint16_t Immediate = Byte5 + (Byte6 << 8);
+ printf("mov [%s %c %d], word %d\n", Displacements[RM], Sign, abs(Displacement), Immediate);
+ }
+ else
+ {
+ uint8_t Immediate = Buffer[++At];
+ printf("mov [%s %c %d], byte %d\n", Displacements[RM], Sign, abs(Displacement), Immediate);
+ }
+ }
+ else if (MOD == 0b11)
+ {
+ printf("; register mode no displacement\n");
+ }
+
+ }
+ else if (MOV_MEM_ACC(Byte1))
+ {
+ // memory to accumulator
+ int WSet = Byte1 & (1 << 0);
+ uint8_t DataL = Buffer[++At];
+ int Immediate = DataL;
+
+ if (WSet)
+ {
+ uint8_t DataH = Buffer[++At];
+ Immediate += DataH << 8;
+ }
+ printf("mov ax, [%d]\n", Immediate);
+
+ }
+ else if (MOV_ACC_MEM(Byte1))
+ {
+ // accumulator to memory
+ int WSet = Byte1 & (1 << 0);
+ uint8_t DataL = Buffer[++At];
+ int Immediate = DataL;
+
+ if (WSet)
+ {
+ uint8_t DataH = Buffer[++At];
+ Immediate += DataH << 8;
+ }
+ printf("mov [%d], ax\n", Immediate);
+ }
+ else if (ARITH_RM_RM(Byte1))
+ {
+ int WSet = Byte1 & (1 << 0);
+ int DSet = Byte1 & (1 << 1);
+ char *Operation = 0;
+ int Displacement = 0;
+ int OP = (Byte1 & 0b00111000) >> 3;
+ uint8_t Byte2 = Buffer[++At];
+ int MOD = (Byte2 & 0b11000000) >> 6;
+ int REG = (Byte2 & 0b00111000) >> 3;
+ int RM = (Byte2 & 0b00000111);
+
+ switch (OP)
+ {
+ case 0b000: Operation = "add"; break;
+ case 0b101: Operation = "sub"; break;
+ case 0b111: Operation = "cmp"; break;
+ }
+
+ if (MOD == 0b01)
+ {
+ uint8_t DispL = Buffer[++At];
+ Displacement = DispL;
+ }
+ else if (MOD == 0b10)
+ {
+ uint8_t DispL = Buffer[++At];
+ uint8_t DispH = Buffer[++At];
+ Displacement = DispL + (DispH << 8);
+ }
+
+ if (MOD == 0b11)
+ {
+ char *Src = 0;
+ char *Dest = 0;
+ if (DSet)
+ {
+ Src = Registers[REG][WSet];
+ Dest = Registers[RM][WSet];
+ }
+ else
+ {
+ Dest = Registers[REG][WSet];
+ Src = Registers[RM][WSet];
+ }
+ printf("%s %s, %s\n", Operation, Src, Dest);
+ }
+ else
+ {
+ char *Src = 0;
+ char *Dest = 0;
+ if (DSet)
+ {
+ printf("%s %s, [%s + %d]\n", Operation, Registers[REG][WSet], Displacements[RM], Displacement);
+ }
+ else
+ {
+ printf("%s [%s + %d], %s\n", Operation, Displacements[RM], Displacement, Registers[REG][WSet]);
+ }
+ }
+
+ }
+ else if (ARITH_IM_RM(Byte1))
+ {
+ int WSet = Byte1 & (1 << 0);
+ int SSet = Byte1 & (1 << 1);
+ int Displacement = 0;
+ int Immediate = 0;
+ char *Operation = 0;
+ char *OperationSize = WSet ? "word" : "byte";
+ uint8_t Byte2 = Buffer[++At];
+ int MOD = (Byte2 & 0b11000000) >> 6;
+ int RM = (Byte2 & 0b00000111);
+ int OP = (Byte2 & 0b00111000) >> 3;
+
+ // TODO: sign extension
+
+ switch (OP)
+ {
+ case 0b000: Operation = "add"; break;
+ case 0b101: Operation = "sub"; break;
+ case 0b111: Operation = "cmp"; break;
+ }
+
+ if (MOD == 0b01)
+ {
+ uint8_t DispL = Buffer[++At];
+ Displacement = DispL;
+ }
+ else if (MOD == 0b10)
+ {
+ uint8_t DispL = Buffer[++At];
+ uint8_t DispH = Buffer[++At];
+ Displacement = DispL + (DispH << 8);
+ }
+
+ uint8_t DataL = Buffer[++At];
+ Immediate = DataL;
+ if (WSet)
+ {
+ uint8_t DataH = Buffer[++At];
+ Immediate += DataH << 8;
+ }
+
+ if (MOD == 0b00 && RM == 0b110)
+ {
+ int Memory = Immediate;
+ Immediate = Buffer[++At];
+ printf("%s %s [%d], %d\n", Operation, OperationSize, Memory, Immediate);
+ }
+ else if (MOD == 0b11)
+ {
+ printf("%s %s, %d\n", Operation, Registers[RM][WSet], Immediate);
+ }
+ else
+ {
+ // TODO(luca): Support signed displacements like in MOV
+ printf("%s %s [%s + %d], %d\n",
+ Operation,
+ OperationSize,
+ Displacements[RM],
+ Displacement,
+ Immediate);
+ }
+ }
+ else if (ARITH_IM_ACC(Byte1))
+ {
+ int WSet = Byte1 & (1 << 0);
+ uint8_t DataL = Buffer[++At];
+ int Immediate = DataL;
+ char *Operation = 0;
+
+ int OP = (Byte1 & 0b00111000) >> 3;
+ switch (OP)
+ {
+ case 0b000: Operation = "add"; break;
+ case 0b101: Operation = "sub"; break;
+ case 0b111: Operation = "cmp"; break;
+ }
+
+ if (WSet)
+ {
+ uint8_t DataH = Buffer[++At];
+ Immediate += DataH << 8;
+ }
+
+ printf("%s %s, %d\n", Operation, Registers[ACCUMULATOR][WSet], Immediate);
+ }
+ else
+ {
+ // Handles all jump instructions
+ // TODO: labels
+ switch (Byte1)
+ {
+ case JE:
+ case JL:
+ case JLE:
+ case JB:
+ case JBE:
+ case JP:
+ case JO:
+ case JS:
+ case JNL:
+ case JG:
+ case JNB:
+ case JA:
+ case JNP:
+ case JNO:
+ case JNS:
+ case JNZ:
+ case LOOP:
+ case LOOPZ:
+ case LOOPNZ:
+ case JCXZ:
+ {
+ uint8_t INC = Buffer[++At];
+ printf("%s %d\n", JumpOperations[Byte1], INC);
+ } break;
+ default:
+ {
+ fprintf(stderr, "Unrecognized Operation from byte:\n");
+ print_binary(Byte1);
+ return 1;
+ } break;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return 0;
+}