diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json index aa80fea..ac8a2a8 100644 --- a/.vscode/c_cpp_properties.json +++ b/.vscode/c_cpp_properties.json @@ -4,7 +4,8 @@ "name": "Win32", "includePath": [ "${workspaceFolder}/**", - "C:/MinGW/include/**" + "C:/MinGW/include/**", + "src/**" ], "defines": [ "_DEBUG", diff --git a/.vscode/settings.json b/.vscode/settings.json index baee89d..8535b32 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -6,6 +6,7 @@ "fcntl.h": "c", "io.h": "c", "errno.h": "c", - "stdbool.h": "c" + "stdbool.h": "c", + "sim8086.h": "c" } } \ No newline at end of file diff --git a/Makefile b/Makefile index 066b128..dbb713b 100644 --- a/Makefile +++ b/Makefile @@ -1,11 +1,10 @@ CC=gcc CFLAGS=-g -Wall -INCLUDES=./include .DEFAULT_GOAL := main %: src/%.c - $(CC) -o $@ $< $(CFLAGS) -I$(INCLUDES) + $(CC) -o $@ $< $(CFLAGS) clean: rm main.exe \ No newline at end of file diff --git a/src/main.c b/src/main.c index acfa32c..dfc9563 100644 --- a/src/main.c +++ b/src/main.c @@ -2,9 +2,14 @@ #include #include #include -#include "os.h" #include -#include "asm.c" + +#include "os.h" +#include "sim8086.h" + +#include "sim8086.c" +#include "sim8086_decoder.c" +#include "sim8086_simulator.c" #define strequal(a, b) strcmp(a, b) == 0 @@ -45,10 +50,6 @@ void get_tmp_file(char *filename, const char *prefix) { close(fd); } -void print_usage(const char *program) { - fprintf(stderr, "Usage: %s \n", program); -} - int compile_asm(const char *src, const char *dst) { char command[512] = { 0 }; snprintf(command, sizeof(command), "nasm \"%s\" -O0 -o \"%s\"", src, dst); @@ -72,7 +73,6 @@ int compare_files(const char *expected, const char *gotten) { } if (!feof(f1) || !feof(f2)) { - goto err; } @@ -83,87 +83,162 @@ err: return rc; } +int dissassemble(FILE *src, FILE *dst) { + fprintf(dst, "bits 16\n\n"); + + char buff[256]; + struct instruction inst; + int counter = 1; + while (true) { + enum decode_error err = decode_instruction(src, &inst); + if (err == DECODE_ERR_EOF) break; + if (err != DECODE_OK) { + fprintf(stderr, "ERROR: Failed to decode %d instruction: %s\n", counter, decode_error_to_str(err)); + return -1; + } + + instruction_to_str(buff, sizeof(buff), &inst); + fprintf(dst, buff); + fprintf(dst, "\n"); + counter += 1; + } + + return 0; +} + +int simulate(FILE *src) { + todo("simulate"); +} + +void print_usage(const char *program) { + fprintf(stderr, "Usage: %s \n", program); +} + +int test_decoder(const char *asm_file) { + if (!strendswith(asm_file, ".asm")) { + printf("ERROR: Expected *.asm file, gotten '%s'", asm_file); + return -1; + } + + char *bin_filename = "test-input.o"; + if (compile_asm(asm_file, bin_filename)) { + printf("ERROR: Failed to compile '%s'", asm_file); + return -1; + } + + FILE *bin_test = fopen(bin_filename, "rb"); + if (bin_test == NULL) { + printf("ERROR: Opening file '%s': %d\n", bin_filename, errno); + return -1; + } + + char *dissassembly_filename = "test-dump.asm"; + FILE *dissassembly = fopen(dissassembly_filename, "wb+"); + if (dissassembly == NULL) { + printf("ERROR: Opening file '%s': %d\n", dissassembly_filename, errno); + return -1; + } + dissassemble(bin_test, dissassembly); + fclose(dissassembly); + + char *dissassembly_dump_filename = "test-dump-asm.o"; + if (compile_asm(dissassembly_filename, dissassembly_dump_filename)) { + printf("ERROR: Failed to compile '%s'", dissassembly_filename); + return -1; + } + + if (!compare_files(bin_filename, dissassembly_dump_filename)) { + printf("Test success\n"); + } else { + printf("Test failed\n"); + } + + return 0; +} + +int dump_decompilation(const char *input) { + if (strendswith(input, ".asm")) { + char bin_filename[MAX_PATH_SIZE]; + get_tmp_file(bin_filename, "nasm_output"); + + if (compile_asm(input, bin_filename)) { + printf("ERROR: Failed to compile '%s'", input); + return -1; + } + + FILE *assembly = fopen(bin_filename, "rb"); + if (assembly == NULL) { + printf("ERROR: Opening file '%s': %d\n", bin_filename, errno); + remove(bin_filename); + return -1; + } + dissassemble(assembly, stdout); + fclose(assembly); + + remove(bin_filename); + } else { + FILE *assembly = fopen(input, "r"); + if (assembly == NULL) { + printf("ERROR: Opening file '%s': %d\n", input, errno); + return -1; + } + dissassemble(assembly, stdout); + fclose(assembly); + } + + return 0; +} + +int run_simulation(const char *input) { + if (strendswith(input, ".asm")) { + char bin_filename[MAX_PATH_SIZE]; + get_tmp_file(bin_filename, "nasm_output"); + + if (compile_asm(input, bin_filename)) { + printf("ERROR: Failed to compile '%s'", input); + return -1; + } + + FILE *assembly = fopen(bin_filename, "rb"); + if (assembly == NULL) { + printf("ERROR: Opening file '%s': %d\n", bin_filename, errno); + remove(bin_filename); + return -1; + } + simulate(assembly); + fclose(assembly); + + remove(bin_filename); + } else { + FILE *assembly = fopen(input, "r"); + if (assembly == NULL) { + printf("ERROR: Opening file '%s': %d\n", input, errno); + return -1; + } + simulate(assembly); + fclose(assembly); + } + + return 0; +} + int main(int argc, char **argv) { if (argc != 3) { print_usage(argv[0]); return -1; } - if (strequal(argv[1], "test")) { - char *asm_file = argv[2]; - if (!strendswith(asm_file, ".asm")) { - printf("ERROR: Expected *.asm file, gotten '%s'", asm_file); - return -1; - } - - char *bin_filename = "test-input.o"; - if (compile_asm(asm_file, bin_filename)) { - printf("ERROR: Failed to compile '%s'", asm_file); - return -1; - } - - FILE *bin_test = fopen(bin_filename, "rb"); - if (bin_test == NULL) { - printf("ERROR: Opening file '%s': %d\n", bin_filename, errno); - return -1; - } - - char *dissassembly_filename = "test-dump.asm"; - FILE *dissassembly = fopen(dissassembly_filename, "wb+"); - if (dissassembly == NULL) { - printf("ERROR: Opening file '%s': %d\n", dissassembly_filename, errno); - return -1; - } - dissassemble(bin_test, dissassembly); - fclose(dissassembly); - - char *dissassembly_dump_filename = "test-dump-asm.o"; - if (compile_asm(dissassembly_filename, dissassembly_dump_filename)) { - printf("ERROR: Failed to compile '%s'", dissassembly_filename); - return -1; - } - - if (!compare_files(bin_filename, dissassembly_dump_filename)) { - printf("Test success\n"); - } else { - printf("Test failed\n"); - } + if (strequal(argv[1], "test-dump")) { + return test_decoder(argv[2]); } else if (strequal(argv[1], "dump")) { - char *input_file = argv[2]; + return dump_decompilation(argv[2]); - if (strendswith(input_file, ".asm")) { - char bin_filename[MAX_PATH_SIZE]; - get_tmp_file(bin_filename, "nasm_output"); - - if (compile_asm(input_file, bin_filename)) { - printf("ERROR: Failed to compile '%s'", input_file); - return -1; - } - - FILE *assembly = fopen(bin_filename, "rb"); - if (assembly == NULL) { - printf("ERROR: Opening file '%s': %d\n", bin_filename, errno); - return -1; - } - dissassemble(assembly, stdout); - fclose(assembly); - - remove(bin_filename); - } else { - FILE *assembly = fopen(input_file, "r"); - if (assembly == NULL) { - printf("ERROR: Opening file '%s': %d\n", input_file, errno); - return -1; - } - dissassemble(assembly, stdout); - fclose(assembly); - } + } else if (strequal(argv[1], "run")) { + return run_simulation(argv[2]); } else { print_usage(argv[0]); return -1; } - - return 0; } diff --git a/include/os.h b/src/os.h similarity index 100% rename from include/os.h rename to src/os.h diff --git a/src/sim8086.c b/src/sim8086.c new file mode 100644 index 0000000..53a9cdc --- /dev/null +++ b/src/sim8086.c @@ -0,0 +1,128 @@ + +static const char *reg_to_str(enum reg_value reg) { + const char *reg_value_str[__REG_COUNT] = { + "al", "cl", "dl", "bl", "ah", "ch", "dh", "bh", + "ax", "cx", "dx", "bx", "sp", "bp", "si", "di" + }; + + assert(0 <= reg && reg <= __REG_COUNT); + return reg_value_str[reg]; +} + +static void mem_to_str(char *buff, size_t max_size, struct mem_value *mem) { + const char *mem_base_str[8] = { + "bx + si", + "bx + di", + "bp + si", + "bp + di", + "si", + "di", + "bp", + "bx" + }; + + assert(0 <= mem->base && mem->base <= __MEM_BASE_COUNT); + if (mem->base == MEM_BASE_DIRECT_ADDRESS) { + snprintf(buff, max_size, "[%d]", (u16)mem->disp); + } else if (mem->disp > 0) { + snprintf(buff, max_size, "[%s + %d]", mem_base_str[mem->base], mem->disp); + } else if (mem->disp < 0) { + snprintf(buff, max_size, "[%s - %d]", mem_base_str[mem->base], -mem->disp); + } else { + snprintf(buff, max_size, "[%s]", mem_base_str[mem->base]); + } +} + +static void reg_or_mem_to_str(char *buff, size_t max_size, struct reg_or_mem_value *value) { + if (value->is_reg) { + strncpy(buff, reg_to_str(value->reg), max_size); + } else { + mem_to_str(buff, max_size, &value->mem); + } +} + +static void src_to_str(char *buff, size_t max_size, struct src_value *value) { + switch (value->variant) + { + case SRC_VALUE_REG: + strncpy(buff, reg_to_str(value->reg), max_size); + break; + case SRC_VALUE_MEM: + mem_to_str(buff, max_size, &value->mem); + break; + case SRC_VALUE_IMMEDIATE16: + snprintf(buff, max_size, "%d", value->immediate); + break; + case SRC_VALUE_IMMEDIATE8: + snprintf(buff, max_size, "%d", (u8)value->immediate); + break; + } +} + +static const char *operation_to_str(enum operation op) { + const char *operation_str[__OP_COUNT] = { + "mov", "add", "sub", "cmp", "je", "jl", "jle", "jb", "jbe", "jp", "jo", + "js", "jne", "jnl","jnle", "jnb", "jnbe", "jnp", "jno", "jns", "loop", + "loopz", "loopnz", "jcxz" + }; + + assert(0 <= op && op <= __OP_COUNT); + return operation_str[op]; +} + +static void instruction_to_str(char *buff, size_t max_size, struct instruction *inst) { + switch (inst->op) + { + case OP_MOV: + case OP_CMP: + case OP_SUB: + case OP_ADD: { + char dest[32]; + char src[32]; + const char *opcode = operation_to_str(inst->op); + reg_or_mem_to_str(dest, sizeof(dest), &inst->dest); + src_to_str(src, sizeof(src), &inst->src); + + bool is_dest_mem = !inst->dest.is_reg; + if (is_dest_mem && inst->src.variant == SRC_VALUE_IMMEDIATE16) { + snprintf(buff, max_size, "%s %s, word %s", opcode, dest, src); + } else if (is_dest_mem && inst->src.variant == SRC_VALUE_IMMEDIATE8) { + snprintf(buff, max_size, "%s %s, byte %s", opcode, dest, src); + } else { + snprintf(buff, max_size, "%s %s, %s", opcode, dest, src); + } + break; + } + case OP_JE: + case OP_JL: + case OP_JLE: + case OP_JB: + case OP_JBE: + case OP_JP: + case OP_JO: + case OP_JS: + case OP_JNE: + case OP_JNL: + case OP_JNLE: + case OP_JNB: + case OP_JNBE: + case OP_JNP: + case OP_JNO: + case OP_LOOP: + case OP_LOOPZ: + case OP_LOOPNZ: + case OP_JCXZ: + case OP_JNS: { + const char *opcode = operation_to_str(inst->op); + i8 offset = inst->jmp_offset+2; + if (offset >= 0) { + snprintf(buff, max_size, "%s $+%d", opcode, offset); + } else { + snprintf(buff, max_size, "%s $%d", opcode, offset); + } + break; + } + default: + panic("Invalid instruction opcode %d\n", inst->op); + } +} diff --git a/src/sim8086.h b/src/sim8086.h new file mode 100644 index 0000000..571bf0a --- /dev/null +++ b/src/sim8086.h @@ -0,0 +1,102 @@ +#include +#include +#include + +#define u32 uint32_t +#define i32 int32_t +#define u16 uint16_t +#define i16 int16_t +#define u8 uint8_t +#define i8 int8_t + +#define panic(...) fprintf(stderr, "PANIC(%s:%d): ", __FILE__, __LINE__); fprintf(stderr, __VA_ARGS__); abort() +#define todo(...) fprintf(stderr, "TODO(%s:%d): ", __FILE__, __LINE__); fprintf(stderr, __VA_ARGS__); abort() +#define ARRAY_LEN(arr) sizeof(arr) / sizeof(arr[0]) + +enum operation { + OP_MOV, + OP_ADD, + OP_SUB, + OP_CMP, + OP_JE, + OP_JL, + OP_JLE, + OP_JB, + OP_JBE, + OP_JP, + OP_JO, + OP_JS, + OP_JNE, + OP_JNL, + OP_JNLE, + OP_JNB, + OP_JNBE, + OP_JNP, + OP_JNO, + OP_JNS, + OP_LOOP, + OP_LOOPZ, + OP_LOOPNZ, + OP_JCXZ, + __OP_COUNT +}; + +// Order and place of these `enum reg_value` enums is IMPORTANT! Don't rearrange! +enum reg_value { + REG_AL, REG_CL, REG_DL, REG_BL, REG_AH, REG_CH, REG_DH, REG_BH, + REG_AX, REG_CX, REG_DX, REG_BX, REG_SP, REG_BP, REG_SI, REG_DI, + __REG_COUNT +}; + +// Order and place of these `enum mem_base` enums is IMPORTANT! Don't rearrange! +enum mem_base { + MEM_BASE_BX_SI, + MEM_BASE_BX_DI, + MEM_BASE_BP_SI, + MEM_BASE_BP_DI, + MEM_BASE_SI, + MEM_BASE_DI, + MEM_BASE_BP, + MEM_BASE_BX, + MEM_BASE_DIRECT_ADDRESS, + __MEM_BASE_COUNT +}; + +struct mem_value { + enum mem_base base; + union { + i16 disp; + u16 direct_address; + }; +}; + +struct reg_or_mem_value { + bool is_reg; + union { + enum reg_value reg; + struct mem_value mem; + }; +}; + +enum src_value_variant { + SRC_VALUE_REG, + SRC_VALUE_MEM, + SRC_VALUE_IMMEDIATE8, + SRC_VALUE_IMMEDIATE16 +}; + +struct src_value { + enum src_value_variant variant; + union { + enum reg_value reg; + struct mem_value mem; + u16 immediate; + }; +}; + +struct instruction { + enum operation op; + struct reg_or_mem_value dest; + struct src_value src; + i8 jmp_offset; +}; \ No newline at end of file diff --git a/src/asm.c b/src/sim8086_decoder.c similarity index 58% rename from src/asm.c rename to src/sim8086_decoder.c index 03c37ec..b1d81c2 100644 --- a/src/asm.c +++ b/src/sim8086_decoder.c @@ -1,19 +1,6 @@ -#include #include -#include -#include -#define u32 uint32_t -#define i32 int32_t -#define u16 uint16_t -#define i16 int16_t -#define u8 uint8_t -#define i8 int8_t - -#define panic(...) fprintf(stderr, "ABORT(%s:%d): ", __FILE__, __LINE__); fprintf(stderr, __VA_ARGS__); abort() -#define todo(...) fprintf(stderr, "TODO(%s:%d): ", __FILE__, __LINE__); fprintf(stderr, __VA_ARGS__); abort() #define dbg(...) printf("; "); printf(__VA_ARGS__); printf("\n") -#define ARRAY_LEN(arr) sizeof(arr) / sizeof(arr[0]) // TODO: find a way to merge "to/from register" with "to/from accumulator" branches into a single code path @@ -24,30 +11,6 @@ enum decode_error { DECODE_ERR_UNKNOWN_OP, }; -enum operation { - OP_MOV, - OP_ADD, - OP_SUB, - OP_CMP, - OP_JE, OP_JL, OP_JLE, OP_JB, OP_JBE, - OP_JP, - OP_JO, - OP_JS, - OP_JNE, OP_JNL, OP_JNLE, OP_JNB, OP_JNBE, - OP_JNP, - OP_JNO, - OP_JNS, - OP_LOOP, - OP_LOOPZ, - OP_LOOPNZ, - OP_JCXZ, - __OP_COUNT -}; -const char *operation_str[__OP_COUNT] = { - "mov", "add", "sub", "cmp", "je", "jl", "jle", "jb", "jbe", "jp", "jo", - "js", "jne", "jnl","jnle", "jnb", "jnbe", "jnp", "jno", "jns", "loop", - "loopz", "loopnz", "jcxz" -}; const enum operation cond_jmp_lookup[16] = { [0b0100] = OP_JE, [0b1100] = OP_JL, @@ -73,184 +36,6 @@ const enum operation cond_loop_jmp_lookup[4] = { [0b11] = OP_JCXZ }; -// Order and place of these `enum reg_value` enums is IMPORTANT! Don't rearrange! -enum reg_value { - REG_AL, REG_CL, REG_DL, REG_BL, REG_AH, REG_CH, REG_DH, REG_BH, - REG_AX, REG_CX, REG_DX, REG_BX, REG_SP, REG_BP, REG_SI, REG_DI, - __REG_COUNT -}; -const char *reg_value_str[__REG_COUNT] = { - "al", "cl", "dl", "bl", "ah", "ch", "dh", "bh", - "ax", "cx", "dx", "bx", "sp", "bp", "si", "di" -}; - -// Order and place of these `enum mem_base` enums is IMPORTANT! Don't rearrange! -enum mem_base { - MEM_BASE_BX_SI, - MEM_BASE_BX_DI, - MEM_BASE_BP_SI, - MEM_BASE_BP_DI, - MEM_BASE_SI, - MEM_BASE_DI, - MEM_BASE_BP, - MEM_BASE_BX, - MEM_BASE_DIRECT_ADDRESS, - __MEM_BASE_COUNT -}; -const char *mem_base_str[8] = { - "bx + si", - "bx + di", - "bp + si", - "bp + di", - "si", - "di", - "bp", - "bx" -}; - -struct mem_value { - enum mem_base base; - i16 disp; - // IMPORTANT! Keep in mind that `disp` should be interpreted as `u16`, if `base == MEM_BASE_DIRECT_ADDRESS` -}; - -struct reg_or_mem_value { - bool is_reg; - union { - enum reg_value reg; - struct mem_value mem; - }; -}; - -enum src_value_variant { - SRC_VALUE_REG, - SRC_VALUE_MEM, - SRC_VALUE_immediate8, - SRC_VALUE_immediate16 -}; - -struct src_value { - enum src_value_variant variant; - union { - enum reg_value reg; - struct mem_value mem; - u16 immediate; - }; -}; - -struct instruction { - enum operation op; - struct reg_or_mem_value dest; - struct src_value src; - i8 jmp_offset; -}; - -static const char *reg_to_str(enum reg_value reg) { - assert(0 <= reg && reg <= __REG_COUNT); - return reg_value_str[reg]; -} - -static void mem_to_str(char *buff, size_t max_size, struct mem_value *mem) { - assert(0 <= mem->base && mem->base <= __MEM_BASE_COUNT); - if (mem->base == MEM_BASE_DIRECT_ADDRESS) { - snprintf(buff, max_size, "[%d]", (u16)mem->disp); - } else if (mem->disp > 0) { - snprintf(buff, max_size, "[%s + %d]", mem_base_str[mem->base], mem->disp); - } else if (mem->disp < 0) { - snprintf(buff, max_size, "[%s - %d]", mem_base_str[mem->base], -mem->disp); - } else { - snprintf(buff, max_size, "[%s]", mem_base_str[mem->base]); - } -} - -static void reg_or_mem_to_str(char *buff, size_t max_size, struct reg_or_mem_value *value) { - if (value->is_reg) { - strncpy(buff, reg_to_str(value->reg), max_size); - } else { - mem_to_str(buff, max_size, &value->mem); - } -} - -static void src_to_str(char *buff, size_t max_size, struct src_value *value) { - switch (value->variant) - { - case SRC_VALUE_REG: - strncpy(buff, reg_to_str(value->reg), max_size); - break; - case SRC_VALUE_MEM: - mem_to_str(buff, max_size, &value->mem); - break; - case SRC_VALUE_immediate16: - snprintf(buff, max_size, "%d", value->immediate); - break; - case SRC_VALUE_immediate8: - snprintf(buff, max_size, "%d", (u8)value->immediate); - break; - } -} - -static const char *operation_to_str(enum operation op) { - assert(0 <= op && op <= __OP_COUNT); - return operation_str[op]; -} - -static void instruction_to_str(char *buff, size_t max_size, struct instruction *inst) { - switch (inst->op) - { - case OP_MOV: - case OP_CMP: - case OP_SUB: - case OP_ADD: { - char dest[32]; - char src[32]; - const char *opcode = operation_to_str(inst->op); - reg_or_mem_to_str(dest, sizeof(dest), &inst->dest); - src_to_str(src, sizeof(src), &inst->src); - - bool is_dest_mem = !inst->dest.is_reg; - if (is_dest_mem && inst->src.variant == SRC_VALUE_immediate16) { - snprintf(buff, max_size, "%s %s, word %s", opcode, dest, src); - } else if (is_dest_mem && inst->src.variant == SRC_VALUE_immediate8) { - snprintf(buff, max_size, "%s %s, byte %s", opcode, dest, src); - } else { - snprintf(buff, max_size, "%s %s, %s", opcode, dest, src); - } - break; - } - case OP_JE: - case OP_JL: - case OP_JLE: - case OP_JB: - case OP_JBE: - case OP_JP: - case OP_JO: - case OP_JS: - case OP_JNE: - case OP_JNL: - case OP_JNLE: - case OP_JNB: - case OP_JNBE: - case OP_JNP: - case OP_JNO: - case OP_LOOP: - case OP_LOOPZ: - case OP_LOOPNZ: - case OP_JCXZ: - case OP_JNS: { - const char *opcode = operation_to_str(inst->op); - i8 offset = inst->jmp_offset+2; - if (offset >= 0) { - snprintf(buff, max_size, "%s $+%d", opcode, offset); - } else { - snprintf(buff, max_size, "%s $%d", opcode, offset); - } - break; - } - default: - panic("Invalid instruction opcode %d\n", inst->op); - } -} - static i16 extend_sign_bit(i8 number) { if (number & 0b10000000) { return number | (0b11111111 << 8); @@ -366,10 +151,10 @@ enum decode_error decode_instruction(FILE *src, struct instruction *output) { output->dest.reg = decode_reg(reg, wide); if (wide) { - output->src.variant = SRC_VALUE_immediate16; + output->src.variant = SRC_VALUE_IMMEDIATE16; output->src.immediate = fgetc(src) | (fgetc(src) << 8); } else { - output->src.variant = SRC_VALUE_immediate8; + output->src.variant = SRC_VALUE_IMMEDIATE8; output->src.immediate = fgetc(src); } @@ -385,10 +170,10 @@ enum decode_error decode_instruction(FILE *src, struct instruction *output) { decode_reg_or_mem(&output->dest, src, rm, mod, wide); if (wide) { - output->src.variant = SRC_VALUE_immediate16; + output->src.variant = SRC_VALUE_IMMEDIATE16; output->src.immediate = fgetc(src) | (fgetc(src) << 8); } else { - output->src.variant = SRC_VALUE_immediate8; + output->src.variant = SRC_VALUE_IMMEDIATE8; output->src.immediate = fgetc(src); } @@ -473,7 +258,7 @@ enum decode_error decode_instruction(FILE *src, struct instruction *output) { decode_reg_or_mem(&output->dest, src, rm, mod, wide); if (wide) { - output->src.variant = SRC_VALUE_immediate16; + output->src.variant = SRC_VALUE_IMMEDIATE16; if (sign_extend) { output->src.immediate = fgetc(src); output->src.immediate = extend_sign_bit(output->src.immediate); @@ -481,7 +266,7 @@ enum decode_error decode_instruction(FILE *src, struct instruction *output) { output->src.immediate = fgetc(src) | (fgetc(src) << 8); } } else { - output->src.variant = SRC_VALUE_immediate8; + output->src.variant = SRC_VALUE_IMMEDIATE8; output->src.immediate = fgetc(src); } @@ -502,10 +287,10 @@ enum decode_error decode_instruction(FILE *src, struct instruction *output) { } if (wide) { - output->src.variant = SRC_VALUE_immediate16; + output->src.variant = SRC_VALUE_IMMEDIATE16; output->src.immediate = fgetc(src) | (fgetc(src) << 8); } else { - output->src.variant = SRC_VALUE_immediate8; + output->src.variant = SRC_VALUE_IMMEDIATE8; output->src.immediate = fgetc(src); } @@ -516,7 +301,7 @@ enum decode_error decode_instruction(FILE *src, struct instruction *output) { output->op = cond_jmp_lookup[opcode]; output->jmp_offset = jmp_offset; - // Conditional jumps + // Conditional loop jumps } else if ((byte1 & 0b11111100) == 0b11100000) { i8 jmp_offset = fgetc(src); u8 opcode = byte1 & 0b00000011; @@ -529,26 +314,3 @@ enum decode_error decode_instruction(FILE *src, struct instruction *output) { return DECODE_OK; } - -int dissassemble(FILE *src, FILE *dst) { - fprintf(dst, "bits 16\n\n"); - - char buff[256]; - struct instruction inst; - int counter = 1; - while (true) { - enum decode_error err = decode_instruction(src, &inst); - if (err == DECODE_ERR_EOF) break; - if (err != DECODE_OK) { - fprintf(stderr, "ERROR: Failed to decode %d instruction: %s\n", counter, decode_error_to_str(err)); - return -1; - } - - instruction_to_str(buff, sizeof(buff), &inst); - fprintf(dst, buff); - fprintf(dst, "\n"); - counter += 1; - } - - return 0; -} \ No newline at end of file diff --git a/src/sim8086_simulator.c b/src/sim8086_simulator.c new file mode 100644 index 0000000..e69de29