complete challenge homework 2
This commit is contained in:
parent
8e4f7419a1
commit
5b67cb4e25
107
src/asm.c
107
src/asm.c
@ -6,6 +6,8 @@
|
||||
#define u32 uint32_t
|
||||
#define u16 uint16_t
|
||||
#define u8 uint8_t
|
||||
#define i16 int16_t
|
||||
#define i8 int8_t
|
||||
|
||||
#define todo(...) fprintf(stderr, "TODO(%s:%d): ", __FILE__, __LINE__); fprintf(stderr, __VA_ARGS__); abort()
|
||||
#define dbg(...) printf("; "); printf(__VA_ARGS__); printf("\n")
|
||||
@ -13,7 +15,8 @@
|
||||
const char *wide_reg_names[8] = { "ax", "cx", "dx", "bx", "sp", "bp", "si", "di" };
|
||||
const char *non_wide_reg_names[8] = { "al", "cl", "dl", "bl", "ah", "ch", "dh", "bh" };
|
||||
|
||||
const char *mod_lookup_names[8] = {
|
||||
// eac - Effective address calculation
|
||||
const char *eac_names[8] = {
|
||||
"bx + si",
|
||||
"bx + di",
|
||||
"bp + si",
|
||||
@ -33,6 +36,37 @@ const char *lookup_reg_name(u8 idx, bool wide) {
|
||||
}
|
||||
}
|
||||
|
||||
void snprintf_mod_with_disp(char *rm_name, size_t size, u8 rm, i16 displacement) {
|
||||
if (displacement < 0) {
|
||||
snprintf(rm_name, size, "[%s - %d]", eac_names[rm], -displacement);
|
||||
} else {
|
||||
snprintf(rm_name, size, "[%s + %d]", eac_names[rm], displacement);
|
||||
}
|
||||
}
|
||||
|
||||
void get_rm_name(char *rm_name, size_t size, FILE *src, u8 rm, u8 mod, bool wide) {
|
||||
if (mod == 0b11000000) { // Mod = 0b11
|
||||
strcpy(rm_name, lookup_reg_name(rm, wide));
|
||||
} else if (mod == 0b10000000) { // Mod = 0b10
|
||||
i16 displacement = fgetc(src) | (fgetc(src) << 8);
|
||||
snprintf_mod_with_disp(rm_name, size, rm, displacement);
|
||||
} else if (mod == 0b01000000) { // Mod = 0b01
|
||||
i16 displacement = fgetc(src);
|
||||
if (displacement & 0b10000000) {
|
||||
displacement |= (0b11111111 << 8);
|
||||
}
|
||||
snprintf_mod_with_disp(rm_name, size, rm, displacement);
|
||||
} else if (mod == 0b00000000) { // Mod = 0b00
|
||||
if (rm == 0b110) { // Direct address
|
||||
u16 displacement = fgetc(src) | (fgetc(src) << 8);
|
||||
snprintf(rm_name, size, "[%d]", displacement);
|
||||
} else {
|
||||
snprintf(rm_name, size, "[%s]", eac_names[rm]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Handy reference: Table 4-12. 8086 Instruction Encoding
|
||||
void dissassemble(FILE *src, FILE *dst) {
|
||||
fprintf(dst, "bits 16\n\n");
|
||||
while (true) {
|
||||
@ -50,40 +84,73 @@ void dissassemble(FILE *src, FILE *dst) {
|
||||
u8 rm = byte2 & 0b00000111;
|
||||
const char *reg_name = lookup_reg_name(reg, wide);
|
||||
char rm_name[24] = { 0 };
|
||||
if (mod == 0b11000000) { // Mod = 0b11
|
||||
strcpy(rm_name, lookup_reg_name(rm, wide));
|
||||
} else if (mod == 0b10000000) { // Mod = 0b10
|
||||
u16 immidiate = fgetc(src) | (fgetc(src) << 8);
|
||||
snprintf(rm_name, sizeof(rm_name), "[%s + %d]", mod_lookup_names[rm], immidiate);
|
||||
} else if (mod == 0b01000000) { // Mod = 0b01
|
||||
u8 immidiate = fgetc(src);
|
||||
snprintf(rm_name, sizeof(rm_name), "[%s + %d]", mod_lookup_names[rm], immidiate);
|
||||
} else if (mod == 0b00000000) { // Mod = 0b00
|
||||
if (rm == 0b110) { // Direct address
|
||||
todo("direct address");
|
||||
} else {
|
||||
snprintf(rm_name, sizeof(rm_name), "[%s]", mod_lookup_names[rm]);
|
||||
}
|
||||
}
|
||||
get_rm_name(rm_name, sizeof(rm_name), src, rm, mod, wide);
|
||||
|
||||
if (direction) {
|
||||
fprintf(dst, "mov %s, %s\n", reg_name, rm_name);
|
||||
} else {
|
||||
fprintf(dst, "mov %s, %s\n", rm_name, reg_name);
|
||||
}
|
||||
|
||||
// Immediate to register
|
||||
} else if ((byte1 & 0b11110000) == 0b10110000) {
|
||||
bool wide = (byte1 & 0b1000) >> 3;
|
||||
u8 reg = byte1 & 0b111;
|
||||
|
||||
u16 immidiate;
|
||||
u16 immediate;
|
||||
if (wide) {
|
||||
immidiate = fgetc(src) | (fgetc(src) << 8);
|
||||
immediate = fgetc(src) | (fgetc(src) << 8);
|
||||
} else {
|
||||
immidiate = fgetc(src);
|
||||
immediate = fgetc(src);
|
||||
}
|
||||
|
||||
fprintf(dst, "mov %s, %d\n", lookup_reg_name(reg, wide), immidiate);
|
||||
fprintf(dst, "mov %s, %d\n", lookup_reg_name(reg, wide), immediate);
|
||||
|
||||
// Immediate to memory
|
||||
} else if ((byte1 & 0b11111110) == 0b11000110) {
|
||||
u8 byte2 = fgetc(src);
|
||||
|
||||
bool wide = byte1 & 0b1;
|
||||
u8 mod = byte2 & 0b11000000;
|
||||
u8 rm = byte2 & 0b00000111;
|
||||
char rm_name[24] = { 0 };
|
||||
get_rm_name(rm_name, sizeof(rm_name), src, rm, mod, wide);
|
||||
|
||||
u16 immediate;
|
||||
if (wide) {
|
||||
immediate = fgetc(src) | (fgetc(src) << 8);
|
||||
fprintf(dst, "mov %s, word %d\n", rm_name, immediate);
|
||||
} else {
|
||||
immediate = fgetc(src);
|
||||
fprintf(dst, "mov %s, byte %d\n", rm_name, immediate);
|
||||
}
|
||||
|
||||
// Memory to accumulator
|
||||
} else if ((byte1 & 0b11111110) == 0b10100000) {
|
||||
bool wide = byte1 & 0b1;
|
||||
|
||||
u16 immediate;
|
||||
if (wide) {
|
||||
immediate = fgetc(src) | (fgetc(src) << 8);
|
||||
} else {
|
||||
immediate = fgetc(src);
|
||||
}
|
||||
|
||||
fprintf(dst, "mov ax, [%d]\n", immediate);
|
||||
|
||||
// Accumulator to memory
|
||||
} else if ((byte1 & 0b11111110) == 0b10100010) {
|
||||
bool wide = byte1 & 0b1;
|
||||
|
||||
u16 immediate;
|
||||
if (wide) {
|
||||
immediate = fgetc(src) | (fgetc(src) << 8);
|
||||
} else {
|
||||
immediate = fgetc(src);
|
||||
}
|
||||
|
||||
fprintf(dst, "mov [%d], ax\n", immediate);
|
||||
|
||||
} else {
|
||||
todo("unhandled byte %d", byte1);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user