From ea20bd9b5bcff9db1d86d83188e1e899799f324b Mon Sep 17 00:00:00 2001 From: Raymaekers Luca Date: Sat, 23 Aug 2025 16:22:13 +0200 Subject: checkpoint --- archived/less_old_sim8086/build/error | 2 + archived/less_old_sim8086/build/first | 0 archived/less_old_sim8086/build/first.asm | 0 .../build/listing_0037_single_register_mov | 1 + .../build/listing_0038_many_register_mov | 1 + .../less_old_sim8086/build/listing_0039_more_movs | Bin 0 -> 41 bytes .../build/listing_0040_challenge_movs | Bin 0 -> 39 bytes .../build/listing_0041_add_sub_cmp_jnz | Bin 0 -> 247 bytes .../build/listing_0041_add_sub_cmp_jnz_error | 2 + .../build/listing_0041_add_sub_cmp_jnz_first.asm | 2 + .../build/listing_0041_add_sub_cmp_jnz_second | 0 .../build/listing_0041_add_sub_cmp_jnz_second.asm | 0 .../build/listing_0042_completionist_decode | Bin 0 -> 893 bytes .../build/listing_0042_completionist_decode_error | 0 .../build/listing_0042_completionist_decode_first | 1 + .../listing_0042_completionist_decode_first.asm | 2 + .../build/listing_0042_completionist_decode_second | Bin 0 -> 2 bytes .../listing_0042_completionist_decode_second.asm | 3 + archived/less_old_sim8086/build/sim8086 | Bin 0 -> 43848 bytes archived/less_old_sim8086/build/test | 1 + archived/less_old_sim8086/build/test.asm | 3 + archived/less_old_sim8086/code/build.sh | 26 + archived/less_old_sim8086/code/print_binary.c | 63 ++ archived/less_old_sim8086/code/sim8086.cpp | 855 +++++++++++++++++++++ archived/less_old_sim8086/code/sim8086.h | 70 ++ .../listings/listing_0037_single_register_mov.asm | 19 + .../listings/listing_0038_many_register_mov.asm | 29 + .../listings/listing_0039_more_movs.asm | 47 ++ .../listings/listing_0040_challenge_movs.asm | 38 + .../listings/listing_0041_add_sub_cmp_jnz.asm | 121 +++ .../listings/listing_0042_completionist_decode.asm | 451 +++++++++++ archived/less_old_sim8086/misc/test_listing | 50 ++ .../less_old_sim8086/misc/test_source_line_by_line | 80 ++ archived/less_old_sim8086/project.4coder | 43 ++ archived/old_sim8086/8086disassembler | Bin 0 -> 23272 bytes archived/old_sim8086/8086disassembler.c | 157 ++++ archived/old_sim8086/build.sh | 6 + .../old_sim8086/listing_0037_single_register_mov | 1 + .../listing_0037_single_register_mov.asm | 19 + .../old_sim8086/listing_0038_many_register_mov | 1 + .../old_sim8086/listing_0038_many_register_mov.asm | 29 + archived/sim8086_old.c | 596 ++++++++++++++ 42 files changed, 2719 insertions(+) create mode 100644 archived/less_old_sim8086/build/error create mode 100644 archived/less_old_sim8086/build/first create mode 100644 archived/less_old_sim8086/build/first.asm create mode 100644 archived/less_old_sim8086/build/listing_0037_single_register_mov create mode 100644 archived/less_old_sim8086/build/listing_0038_many_register_mov create mode 100644 archived/less_old_sim8086/build/listing_0039_more_movs create mode 100644 archived/less_old_sim8086/build/listing_0040_challenge_movs create mode 100644 archived/less_old_sim8086/build/listing_0041_add_sub_cmp_jnz create mode 100644 archived/less_old_sim8086/build/listing_0041_add_sub_cmp_jnz_error create mode 100644 archived/less_old_sim8086/build/listing_0041_add_sub_cmp_jnz_first.asm create mode 100644 archived/less_old_sim8086/build/listing_0041_add_sub_cmp_jnz_second create mode 100644 archived/less_old_sim8086/build/listing_0041_add_sub_cmp_jnz_second.asm create mode 100644 archived/less_old_sim8086/build/listing_0042_completionist_decode create mode 100644 archived/less_old_sim8086/build/listing_0042_completionist_decode_error create mode 100644 archived/less_old_sim8086/build/listing_0042_completionist_decode_first create mode 100644 archived/less_old_sim8086/build/listing_0042_completionist_decode_first.asm create mode 100644 archived/less_old_sim8086/build/listing_0042_completionist_decode_second create mode 100644 archived/less_old_sim8086/build/listing_0042_completionist_decode_second.asm create mode 100755 archived/less_old_sim8086/build/sim8086 create mode 100644 archived/less_old_sim8086/build/test create mode 100644 archived/less_old_sim8086/build/test.asm create mode 100755 archived/less_old_sim8086/code/build.sh create mode 100644 archived/less_old_sim8086/code/print_binary.c create mode 100644 archived/less_old_sim8086/code/sim8086.cpp create mode 100644 archived/less_old_sim8086/code/sim8086.h create mode 100644 archived/less_old_sim8086/listings/listing_0037_single_register_mov.asm create mode 100644 archived/less_old_sim8086/listings/listing_0038_many_register_mov.asm create mode 100644 archived/less_old_sim8086/listings/listing_0039_more_movs.asm create mode 100644 archived/less_old_sim8086/listings/listing_0040_challenge_movs.asm create mode 100644 archived/less_old_sim8086/listings/listing_0041_add_sub_cmp_jnz.asm create mode 100644 archived/less_old_sim8086/listings/listing_0042_completionist_decode.asm create mode 100755 archived/less_old_sim8086/misc/test_listing create mode 100755 archived/less_old_sim8086/misc/test_source_line_by_line create mode 100644 archived/less_old_sim8086/project.4coder create mode 100755 archived/old_sim8086/8086disassembler create mode 100644 archived/old_sim8086/8086disassembler.c create mode 100755 archived/old_sim8086/build.sh create mode 100644 archived/old_sim8086/listing_0037_single_register_mov create mode 100644 archived/old_sim8086/listing_0037_single_register_mov.asm create mode 100644 archived/old_sim8086/listing_0038_many_register_mov create mode 100644 archived/old_sim8086/listing_0038_many_register_mov.asm create mode 100644 archived/sim8086_old.c (limited to 'archived') 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 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 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 Binary files /dev/null and b/archived/less_old_sim8086/build/listing_0039_more_movs 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 Binary files /dev/null and b/archived/less_old_sim8086/build/listing_0040_challenge_movs 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 Binary files /dev/null and b/archived/less_old_sim8086/build/listing_0041_add_sub_cmp_jnz 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 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 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 Binary files /dev/null and b/archived/less_old_sim8086/build/listing_0042_completionist_decode 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 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 Binary files /dev/null and b/archived/less_old_sim8086/build/listing_0042_completionist_decode_second 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 Binary files /dev/null and b/archived/less_old_sim8086/build/sim8086 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 +#include +#include +#include +#include + +#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 \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 +#include +#include +#include + +#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 \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 \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 Binary files /dev/null and b/archived/old_sim8086/8086disassembler 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 +#include + +#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 +#include +#include +#include +#include +#include +#include + +#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; +} -- cgit v1.2.3-70-g09d2