#include #include #include "lib.h" #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) enum Instruction { INST_MOV_REG_REG = 0b10001000, // INST_MOV_REG_REG = 0b10001000, // INST_MOV_REG_REG = 0b10001000, }; enum Mode { MODE_MEM_NO_DIS = 0b00, MODE_MEM_DIS_08 = 0b01, MODE_MEM_DIS_16 = 0b10, MODE_RGSTR_MODE = 0b11, }; typedef struct Register { char code; char* fullname; char* bytename; union { struct { char low; char high; }; u16 full; } value; } Register; Register registers[8] = { {.code = 0b000, .fullname = "ax", .bytename = "al"}, {.code = 0b001, .fullname = "cx", .bytename = "cl"}, {.code = 0b010, .fullname = "dx", .bytename = "dl"}, {.code = 0b011, .fullname = "bx", .bytename = "bl"}, {.code = 0b100, .fullname = "sp", .bytename = "ah"}, {.code = 0b101, .fullname = "bp", .bytename = "ch"}, {.code = 0b110, .fullname = "si", .bytename = "dh"}, {.code = 0b111, .fullname = "di", .bytename = "bh"}, }; char* memory[65536]; // void inst_mov_rgmm_reg() int main(int argc, char** argv) { if (argc < 2) { printf("Usage: Please provide assembled instructions as input\n"); exit(0); } unsigned char buf[256]; FILE *f = fopen(argv[1], "r"); if (!f) { perror("fopen\n"); return EXIT_FAILURE; } size_t bytes_read; printf("; Decoded 8086 Assembly Instructions\n\n"); printf("bits 16\n\n"); while ((bytes_read = fread(buf, sizeof(char), 1, f)) > 0) { char inst = buf[0]; // Instruction instruction = 0; // Register/memory to/from register if ((inst & ~0x3) == (char)0b10001000) { // TODO: We should add some form of error handling here bytes_read = fread(buf, sizeof(char), 1, f); char next_byte = buf[0]; char w = inst & 0b00000001; char d = inst & 0b00000010; char mod = (next_byte & 0b11000000) >> 6; char reg = (next_byte & 0b00111000) >> 3; char rm = (next_byte & 0b00000111); size_t reg_idx = reg; size_t rm_idx = rm; Register src_reg = d == 0 ? registers[reg_idx] : registers[rm_idx]; Register dst_reg = d == 0 ? registers[rm_idx] : registers[reg_idx]; if (mod == MODE_RGSTR_MODE) { char* src_name = w == 1 ? src_reg.fullname : src_reg.bytename; char* dst_name = w == 1 ? dst_reg.fullname : dst_reg.bytename; printf("mov %s, %s", dst_name, src_name); } else { // char* src_name = w == 1 ? src_reg.fullname : src_reg.bytename; char *dst_name; if (d) { dst_name = w == 1 ? dst_reg.fullname : dst_reg.bytename; } else { dst_name = w == 1 ? src_reg.fullname : src_reg.bytename; } char* src_name; switch (rm) { case 0b000: src_name = "bx + si"; break; case 0b001: src_name = "bx + di"; break; case 0b010: src_name = "bp + si"; break; case 0b011: src_name = "bp + di"; break; case 0b100: src_name = "si"; break; case 0b101: src_name = "di"; break; case 0b110: src_name = "bp"; break; case 0b111: src_name = "bx"; break; } if (mod == MODE_MEM_DIS_16) { bytes_read = fread(buf, sizeof(char), 2, f); i16 data = (i16)buf[1] << 8 | buf[0]; if (d) { printf("mov %s, [%s + %d] ;(mod %d, w %d, d %d)", dst_name, src_name, data, mod, d, w); } else { printf("mov [%s], %s ;(mod %d, w %d, d %d)", src_name, dst_name, mod, d, w); } char disp_lo = buf[0]; char disp_hi = buf[1]; (void)disp_lo; (void)disp_hi; } else if (mod == MODE_MEM_DIS_08) { bytes_read = fread(buf, sizeof(char), 1, f); if (d) { printf("mov %s, [%s + %d] ;(mod %d, w %d, d %d)", dst_name, src_name, buf[0], mod, d, w); } else { printf("mov [%s], %s ;(mod %d, w %d, d %d)", src_name, dst_name, mod, d, w); } } else if (mod == MODE_MEM_NO_DIS) { if (d) { printf("mov %s, [%s] ;(mod %d, w %d, d %d)", dst_name, src_name, mod, d, w); } else { printf("mov [%s], %s ;(mod %d, w %d, d %d)", src_name, dst_name, mod, d, w); } } } } // Immediate to register/memory else if ((inst & ~0x1) == (char)0b11000110) { printf("mov imm to reg/mem"); } // Immediate to register else if ((inst & ~0xF) == (char)0b10110000) { char w = inst & 0b00001000; Register reg = registers[(size_t)inst & 0b00000111]; char *reg_name = w == 0 ? reg.bytename : reg.fullname; if (w) { bytes_read = fread(buf, sizeof(char), 2, f); i16 data = (i16)buf[1] << 8 | buf[0]; printf("mov %s, %hd ; Immediate to register", reg_name, data); } else { bytes_read = fread(buf, sizeof(char), 1, f); printf("mov %s, %d ; Immediate to register", reg_name, (sbyte)buf[0]); } } // Memory to accumulator else if ((inst & ~0x1) == (char)0b10100000) { printf("mov mem to acc"); } // Accumulator to memory else if ((inst & ~0x1) == (char)0b10100010) { printf("mov acc to mem"); } // Register/memory to segment register else if (inst == (char)0b10001110) { printf("mov regmem to segreg"); } // Segment register to register/memory else if (inst == (char)0b10001100) { printf("mov segreg to regmem"); } else { fprintf(stderr, "Unrecognized Instruction"); } printf("\n"); } }