From 5b67cb4e2565c5a38cbf18110a0bb4523d0a9dc9 Mon Sep 17 00:00:00 2001 From: Rokas Puzonas Date: Sun, 9 Apr 2023 21:19:30 +0300 Subject: [PATCH] complete challenge homework 2 --- src/asm.c | 107 ++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 87 insertions(+), 20 deletions(-) diff --git a/src/asm.c b/src/asm.c index 38bb483..b2c7387 100644 --- a/src/asm.c +++ b/src/asm.c @@ -6,6 +6,8 @@ #define u32 uint32_t #define u16 uint16_t #define u8 uint8_t +#define i16 int16_t +#define i8 int8_t #define todo(...) fprintf(stderr, "TODO(%s:%d): ", __FILE__, __LINE__); fprintf(stderr, __VA_ARGS__); abort() #define dbg(...) printf("; "); printf(__VA_ARGS__); printf("\n") @@ -13,7 +15,8 @@ const char *wide_reg_names[8] = { "ax", "cx", "dx", "bx", "sp", "bp", "si", "di" }; const char *non_wide_reg_names[8] = { "al", "cl", "dl", "bl", "ah", "ch", "dh", "bh" }; -const char *mod_lookup_names[8] = { +// eac - Effective address calculation +const char *eac_names[8] = { "bx + si", "bx + di", "bp + si", @@ -33,6 +36,37 @@ const char *lookup_reg_name(u8 idx, bool wide) { } } +void snprintf_mod_with_disp(char *rm_name, size_t size, u8 rm, i16 displacement) { + if (displacement < 0) { + snprintf(rm_name, size, "[%s - %d]", eac_names[rm], -displacement); + } else { + snprintf(rm_name, size, "[%s + %d]", eac_names[rm], displacement); + } +} + +void get_rm_name(char *rm_name, size_t size, FILE *src, u8 rm, u8 mod, bool wide) { + if (mod == 0b11000000) { // Mod = 0b11 + strcpy(rm_name, lookup_reg_name(rm, wide)); + } else if (mod == 0b10000000) { // Mod = 0b10 + i16 displacement = fgetc(src) | (fgetc(src) << 8); + snprintf_mod_with_disp(rm_name, size, rm, displacement); + } else if (mod == 0b01000000) { // Mod = 0b01 + i16 displacement = fgetc(src); + if (displacement & 0b10000000) { + displacement |= (0b11111111 << 8); + } + snprintf_mod_with_disp(rm_name, size, rm, displacement); + } else if (mod == 0b00000000) { // Mod = 0b00 + if (rm == 0b110) { // Direct address + u16 displacement = fgetc(src) | (fgetc(src) << 8); + snprintf(rm_name, size, "[%d]", displacement); + } else { + snprintf(rm_name, size, "[%s]", eac_names[rm]); + } + } +} + +// Handy reference: Table 4-12. 8086 Instruction Encoding void dissassemble(FILE *src, FILE *dst) { fprintf(dst, "bits 16\n\n"); while (true) { @@ -50,40 +84,73 @@ void dissassemble(FILE *src, FILE *dst) { u8 rm = byte2 & 0b00000111; const char *reg_name = lookup_reg_name(reg, wide); char rm_name[24] = { 0 }; - if (mod == 0b11000000) { // Mod = 0b11 - strcpy(rm_name, lookup_reg_name(rm, wide)); - } else if (mod == 0b10000000) { // Mod = 0b10 - u16 immidiate = fgetc(src) | (fgetc(src) << 8); - snprintf(rm_name, sizeof(rm_name), "[%s + %d]", mod_lookup_names[rm], immidiate); - } else if (mod == 0b01000000) { // Mod = 0b01 - u8 immidiate = fgetc(src); - snprintf(rm_name, sizeof(rm_name), "[%s + %d]", mod_lookup_names[rm], immidiate); - } else if (mod == 0b00000000) { // Mod = 0b00 - if (rm == 0b110) { // Direct address - todo("direct address"); - } else { - snprintf(rm_name, sizeof(rm_name), "[%s]", mod_lookup_names[rm]); - } - } + get_rm_name(rm_name, sizeof(rm_name), src, rm, mod, wide); if (direction) { fprintf(dst, "mov %s, %s\n", reg_name, rm_name); } else { fprintf(dst, "mov %s, %s\n", rm_name, reg_name); } + // Immediate to register } else if ((byte1 & 0b11110000) == 0b10110000) { bool wide = (byte1 & 0b1000) >> 3; u8 reg = byte1 & 0b111; - u16 immidiate; + u16 immediate; if (wide) { - immidiate = fgetc(src) | (fgetc(src) << 8); + immediate = fgetc(src) | (fgetc(src) << 8); } else { - immidiate = fgetc(src); + immediate = fgetc(src); } - fprintf(dst, "mov %s, %d\n", lookup_reg_name(reg, wide), immidiate); + fprintf(dst, "mov %s, %d\n", lookup_reg_name(reg, wide), immediate); + + // Immediate to memory + } else if ((byte1 & 0b11111110) == 0b11000110) { + u8 byte2 = fgetc(src); + + bool wide = byte1 & 0b1; + u8 mod = byte2 & 0b11000000; + u8 rm = byte2 & 0b00000111; + char rm_name[24] = { 0 }; + get_rm_name(rm_name, sizeof(rm_name), src, rm, mod, wide); + + u16 immediate; + if (wide) { + immediate = fgetc(src) | (fgetc(src) << 8); + fprintf(dst, "mov %s, word %d\n", rm_name, immediate); + } else { + immediate = fgetc(src); + fprintf(dst, "mov %s, byte %d\n", rm_name, immediate); + } + + // Memory to accumulator + } else if ((byte1 & 0b11111110) == 0b10100000) { + bool wide = byte1 & 0b1; + + u16 immediate; + if (wide) { + immediate = fgetc(src) | (fgetc(src) << 8); + } else { + immediate = fgetc(src); + } + + fprintf(dst, "mov ax, [%d]\n", immediate); + + // Accumulator to memory + } else if ((byte1 & 0b11111110) == 0b10100010) { + bool wide = byte1 & 0b1; + + u16 immediate; + if (wide) { + immediate = fgetc(src) | (fgetc(src) << 8); + } else { + immediate = fgetc(src); + } + + fprintf(dst, "mov [%d], ax\n", immediate); + } else { todo("unhandled byte %d", byte1); }