performance-aware-programming/8086_assembly_01/dasm.cc
2024-06-22 13:54:45 +01:00

120 lines
2.5 KiB
C++

#include <bits/types/FILE.h>
#include <cstdint>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
// 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;
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) {
static uint16_t reg_mask = 0x07;
// clang-format off
static const char *table[16] = {
"al", "ax",
"cl", "cx",
"dl", "dx",
"bl", "bx",
"ah", "sp",
"ch", "bp",
"dh", "si",
"bh", "di"
};
// clang-format on
static const uint16_t ROW_WIDTH = 2;
uint16_t offset = instruction & reg_mask;
// Multiply offset by 2 since each row has 2 columns
strcpy(dest, table[offset * ROW_WIDTH + (uint16_t)word]);
}