#include #include #include enum DT_INSTRUCTIONS { MOV_RM_TF_R = 0b1000'10, //d w MOV_I_T_RM = 0b1100'011, // w MOV_I_T_R = 0b1011, // w reg MOV_M_T_A = 0b1010'000, // w MOV_A_T_M = 0b1010'001, // w MOV_RM_T_SR = 0b1000'1110, MOV_SR_T_RM = 0b1000'1100, }; enum MOV_REGISTER_MODE { MEM_NO_DISP = 0b00, MEM_8BIT_DISP = 0b01, MEM_16BIT_DISP = 0b010, REG_NO_DISP = 0b11 }; char REG_ENCODING_TXT[0b10000][3] = { "al", "cl", "dl", "bl", "ah", "ch", "dh", "bh", "ax", "cx", "dx", "bx", "sp", "bp", "si", "di"}; enum REG_ENCODING { R_AL = 0b000, R_CL = 0b001, R_DL = 0b010, R_BL = 0b011, R_AH = 0b100, R_CH = 0b101, R_DH = 0b110, R_BH = 0b111 }; enum WREG_ENCODING { WR_AX = 0b000, WR_CX = 0b001, WR_DX = 0b010, WR_BX = 0b011, WR_SP = 0b100, WR_BP = 0b101, WR_SI = 0b110, WR_DI = 0b111 }; typedef struct { FILE *binary; uint64_t size; } binary_data; FILE *output; void MOV_RM_TF_R_parse(uint8_t byte1, uint8_t byte2, uint8_t byte3, uint8_t byte4) { const uint8_t wide_mask = 0b0000'0001; const uint8_t dest_mask = 0b0000'0010; const uint8_t mod_mask = 0b1100'0000; const uint8_t regm_mask = 0b0011'1000; if ((byte2 & mod_mask) != mod_mask) return; //Since we're only doing register mode/register to register, both reg and r/m are affected by the W bit bool reg_is_dest = (byte1 & dest_mask); //if D=1, dest is retrieved from the reg field in byte2 and src from r/m uint8_t dest_value = (reg_is_dest) ? ((byte2 & regm_mask) >> 3) + ((byte1 & wide_mask) * 8) : (byte2 & (regm_mask >> 3)) + ((byte1 & wide_mask) * 8); uint8_t src_value = (reg_is_dest) ? (byte2 & (regm_mask >> 3)) + ((byte1 & wide_mask) * 8) : ((byte2 & regm_mask) >> 3) + ((byte1 & wide_mask) * 8); printf("%s %s, %s\n", "mov", REG_ENCODING_TXT[dest_value], REG_ENCODING_TXT[src_value]); fprintf(output, "%s %s, %s\n", "mov", REG_ENCODING_TXT[dest_value], REG_ENCODING_TXT[src_value]); return; } int main(int argc, char** argv) { if (argc != 2) return -1; if (CHAR_BIT != 8) return -2; binary_data bin; unsigned char byte[1]; bin.binary = fopen(argv[1], "rb"); fseek(bin.binary, 0, SEEK_END); bin.size = ftell(bin.binary); fseek(bin.binary, 0, SEEK_SET); output = fopen("output.asm", "w"); fprintf(output, "%s\n\n", "bits 16"); for (int bytes_read = 0; bytes_read < bin.size; bytes_read++) { fread(byte, sizeof(byte), 1, bin.binary); uint8_t manip_inst = (uint8_t)byte[0]; uint8_t inst = (uint8_t)byte[0]; //For now we're just checking for RM_TF_R manip_inst = (manip_inst >> 2); if (manip_inst != MOV_RM_TF_R) break; if (bytes_read >= bin.size) break; fread(byte, sizeof(byte), 1, bin.binary); bytes_read++; uint8_t inst_byte2 = (uint8_t)byte[0]; MOV_RM_TF_R_parse(inst, inst_byte2, 0, 0); } return 0; }