232 lines
7.0 KiB
C

#include <stdio.h>
#include <stdlib.h>
#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");
}
}