#include #include #include #include #include // Bit patterns for the 8086 OPCODES enum class OPCODES { MOV = 0x88, }; enum class OPMASKS { MOV = 0xfc, }; enum class FLAGS { WORD = 0x01, REG_DEST = 0x02, }; enum class MODE { MEM = 0x00, MEM8 = 0x40, MEM16 = 0x80, REG = 0xc0, }; uint16_t decode_mode(uint16_t instruction); void decode_register(uint16_t instruction, bool word, char *dest); int main(int argc, char *argv[]) { if (argc < 2) { printf("Please provide a file to disassemble\n"); return 1; } const char *filename = argv[1]; FILE *fp = fopen(filename, "rb"); if (fp) { uint16_t inst = 0; const char *op = ""; char out_filename[4096] = {0}; sprintf(out_filename, "%s_out.asm", filename); FILE *out = fopen(out_filename, "w"); if (out) { fprintf(out, "; Disassembled by DASM\n\nbits 16\n\n"); while (fread(&inst, sizeof(inst), 1, fp)) { if ((inst & (uint16_t)OPMASKS::MOV) == (uint16_t)OPCODES::MOV) { op = "mov"; bool reg_dest = (inst & (uint16_t)FLAGS::REG_DEST) == (uint16_t)FLAGS::REG_DEST; bool word = (inst & (uint16_t)FLAGS::WORD) == (uint16_t)FLAGS::WORD; // NOTE: Using right shift will only work on little-endian CPUs uint16_t operands_info = inst >> 8; if (decode_mode(operands_info) == (uint16_t)MODE::REG) { char rm[3] = {0}; char reg[3] = {0}; decode_register(operands_info, word, rm); decode_register(operands_info >> 3, word, reg); fprintf(out, "%s %s, %s\n", op, reg_dest ? reg : rm, reg_dest ? rm : reg); } } else { printf("It's not a mov operation\n"); } } fclose(out); } else { printf("Failed to open output file\n"); } fclose(fp); } else { printf("Failed to open the selected file\n"); } return 0; } uint16_t decode_mode(uint16_t instruction) { uint16_t mode_mask = 0xc0; return instruction & mode_mask; } void decode_register(uint16_t instruction, bool word, char *dest) { uint16_t reg_mask = 0x07; switch (instruction & reg_mask) { case 0x00: if (word) { strcpy(dest, "ax"); } else { strcpy(dest, "al"); } break; case 0x01: if (word) { strcpy(dest, "cx"); } else { strcpy(dest, "cl"); } break; case 0x02: if (word) { strcpy(dest, "dx"); } else { strcpy(dest, "dl"); } break; case 0x03: if (word) { strcpy(dest, "bx"); } else { strcpy(dest, "bl"); } break; case 0x04: if (word) { strcpy(dest, "sp"); } else { strcpy(dest, "ah"); } break; case 0x05: if (word) { strcpy(dest, "bp"); } else { strcpy(dest, "ch"); } break; case 0x06: if (word) { strcpy(dest, "si"); } else { strcpy(dest, "dh"); } break; case 0x07: if (word) { strcpy(dest, "di"); } else { strcpy(dest, "bh"); } break; } }