#include <base/base_inc.c>
#include <OS/os_inc.c>
+global char* registers[] = {
+ "al", "cl", "dl", "bl",
+ "ah", "ch", "dh", "bh",
+ "ax", "cx", "dx", "bx",
+ "sp", "bp", "si", "di",
+};
+
+global char* eac[] = {
+ "bx + si",
+ "bx + di",
+ "bp + si",
+ "bp + di",
+ "si",
+ "di",
+ "bp",
+ "bx",
+};
+
+global u8 *code = 0;
+
+fn usize inst_move_regmem_tofrom_reg(void) {
+ u8 *lcode = code;
+ u8 d = (*lcode & 0b10) >> 1;
+ u8 w = *lcode & 0b1;
+ lcode += 1;
+ u8 mod = *lcode >> 6;
+ u8 reg = (*lcode >> 3) & (0b111);
+ u8 rm = *lcode & (0b111);
+ lcode += 1;
+
+ printf("mov ");
+ switch (mod) {
+ case 0b00: {
+ char *dest = registers[(w << 3) | reg];
+ if (rm == 0b110) {
+ if (d) {
+ if (w) {
+ printf("%s, [%u]\n", dest, (*lcode) | (*(lcode + 1) << 8));
+ lcode += 2;
+ } else {
+ printf("%s, [%u]\n", dest, *lcode);
+ lcode += 1;
+ }
+ } else {
+ if (w) {
+ printf("[%u], %s\n", (*lcode) | (*(lcode + 1) << 8), dest);
+ lcode += 2;
+ } else {
+ printf("[%u], %s\n", *lcode, dest);
+ lcode += 1;
+ }
+ }
+ } else {
+ if (d) {
+ printf("%s, [%s]\n", dest, eac[rm]);
+ } else {
+ printf("[%s], %s\n", eac[rm], dest);
+ }
+ }
+ } break;
+ case 0b01: {
+ char *dest = registers[(w << 3) | reg];
+ i8 disp = *lcode; // in displacement calculations values are signed
+ char sign = (disp < 0 ? '-' : '+');
+ disp = Abs(disp);
+ if (d) {
+ printf("%s, [%s %c %d]\n", dest, eac[rm], sign, disp);
+ } else {
+ printf("[%s %c %d], %s\n", eac[rm], sign, disp, dest);
+ }
+ lcode += 1;
+ } break;
+ case 0b10: {
+ char *dest = registers[(w << 3) | reg];
+ // in displacement calculations values are signed
+ i16 disp = *lcode | ((*(lcode + 1)) << 8);
+ char sign = (disp < 0 ? '-' : '+');
+ disp = Abs(disp);
+ if (d) {
+ printf("%s, [%s %c %u]\n", dest, eac[rm], sign, disp);
+ } else {
+ printf("[%s %c %u], %s\n", eac[rm], sign, disp, dest);
+ }
+ lcode += 2;
+ } break;
+ case 0b11: {
+ char *dest = d ? registers[(w << 3) | reg] : registers[(w << 3) | rm];
+ char *source = d ? registers[(w << 3) | rm] : registers[(w << 3) | reg];
+ printf("%s, %s\n", dest, source);
+ } break;
+ }
+
+ usize res = lcode - code;
+ code = lcode;
+ return res;
+}
+
+fn usize inst_move_imm_to_reg(void) {
+ u8 *lcode = code;
+ u8 w = (*lcode >> 3) & 0b1;
+ u8 reg = *lcode & 0b111;
+ lcode += 1;
+ printf("mov %s, ", registers[(w << 3) | reg]);
+ if (w) {
+ printf("%u\n", lcode[0] | (lcode[1] << 8));
+ lcode += 2;
+ } else {
+ printf("%u\n", *lcode++);
+ }
+ usize res = lcode - code;
+ code = lcode;
+ return res;
+}
+
+fn usize inst_move_imm_to_regmem(void) {
+ u8 *lcode = code;
+ u8 w = *lcode & 0b1;
+ lcode += 1;
+ u8 mod = *lcode >> 6;
+ u8 rm = *lcode & 0b111;
+ lcode += 1;
+
+ printf("mov ");
+ switch (mod) {
+ case 0b00: {
+ if (rm == 0b110) {
+ u8 *ofos_fset = lcode;
+ if (w) {
+ lcode += 1;
+ printf("[%u], word %u\n", *ofos_fset, *lcode | ((*(lcode + 1)) << 8));
+ } else {
+ printf("[%u], byte %u\n", *ofos_fset, *lcode);
+ }
+ } else {
+ if (w) {
+ printf("[%s], word %u\n", eac[rm], *lcode | ((*(lcode + 1)) << 8));
+ lcode += 2;
+ } else {
+ printf("[%s], byte %u\n", eac[rm], *lcode);
+ lcode += 1;
+ }
+ }
+ } break;
+ case 0b01: {
+ i8 disp = *lcode; // in displacement calculations values are signed
+ char sign = (disp < 0 ? '-' : '+');
+ disp = Abs(disp);
+ if (w) {
+ printf("[%s %c %d], word %d\n", eac[rm], sign, disp,
+ *lcode | ((*(lcode + 1)) << 8));
+ lcode += 2;
+ } else {
+ printf("[%s %c %d], byte %d\n", eac[rm], sign, disp, *lcode);
+ lcode += 1;
+ }
+ } break;
+ case 0b10: {
+ // in displacement calculations values are signed
+ i16 disp = *lcode | ((*(lcode + 1)) << 8);
+ lcode += 2;
+ char sign = (disp < 0 ? '-' : '+');
+ disp = Abs(disp);
+ if (w) {
+ printf("[%s %c %u], word %d\n", eac[rm], sign, disp,
+ *lcode | ((*(lcode + 1)) << 8));
+ lcode += 2;
+ } else {
+ printf("[%s %c %u], byte %d\n", eac[rm], sign, disp, *lcode);
+ lcode += 1;
+ }
+ } break;
+ case 0b11: {
+ if (w) {
+ printf("%s, %d\n", registers[(w << 3) | rm],
+ *lcode | ((*(lcode + 1)) << 8));
+ lcode += 2;
+ } else {
+ printf("%s, %d\n", registers[(w << 3) | rm], *lcode);
+ lcode += 1;
+ }
+ } break;
+ }
+ usize res = lcode - code;
+ code = lcode;
+ return res;
+}
+
+fn usize inst_move_mem_to_accum(u8 d) {
+ u8 *lcode = code;
+ u8 w = *lcode & 0b1;
+ lcode += 1;
+ if (d) {
+ if (w) {
+ printf("mov ax, [%u]\n", *lcode | (*(lcode + 1) << 8));
+ lcode += 2;
+ } else {
+ printf("mov al, [%u]\n", *lcode);
+ lcode += 1;
+ }
+ } else {
+ if (w) {
+ printf("mov [%u], ax\n", *lcode | (*(lcode + 1) << 8));
+ lcode += 2;
+ } else {
+ printf("mov [%u], al\n", *lcode);
+ lcode += 1;
+ }
+ }
+ usize res = lcode - code;
+ code = lcode;
+ return res;
+}
+
+inline fn i8 get_byte_displacement(void) {
+ code += 1;
+ i8 res = *code;
+ code += 1;
+ return res;
+}
+
fn void start(CmdLine *cli) {
-#if 1
- printf("Compiler GCC: %d\n", COMPILER_GCC);
- printf("Compiler CL: %d\n", COMPILER_CL);
- printf("Compiler CLANG: %d\n", COMPILER_CLANG);
-
- printf("OS GNU/Linux: %d\n", OS_LINUX);
- printf("OS BSD: %d\n", OS_BSD);
- printf("OS MAC: %d\n", OS_MAC);
- printf("OS Windows: %d\n", OS_WINDOWS);
-
- printf("Architecture x86 32bit: %d\n", ARCH_X86);
- printf("Architecture x64 64bit: %d\n", ARCH_X64);
- printf("Architecture ARM 32bit: %d\n", ARCH_ARM);
- printf("Architecture ARM 64bit: %d\n", ARCH_ARM64);
-#endif
+ Arena *arena = arena_build();
+ OS_Handle binary_file = os_fs_open(Strlit("asm/add_sub_cmp_jnz"), OS_AccessFlag_Read);
+ /* OS_Handle binary_file = os_fs_open(Strlit("asm/challenge_movs"), OS_AccessFlag_Read); */
+ /* OS_Handle binary_file = os_fs_open(Strlit("asm/more_movs"), OS_AccessFlag_Read); */
+ /* OS_Handle binary_file = os_fs_open(Strlit("asm/many_register_mov"), OS_AccessFlag_Read); */
+ /* OS_Handle binary_file = os_fs_open(Strlit("asm/single_register_mov"), OS_AccessFlag_Read); */
+ String8 content = os_fs_read(arena, binary_file);
+ code = content.str;
+ os_fs_close(binary_file);
+ for (usize i = 0; i < content.size;) {
+ if ((*code >> 2) == 0b100010) {
+ i += inst_move_regmem_tofrom_reg();
+ } else if ((*code >> 1) == 0b1100011) {
+ i += inst_move_imm_to_regmem();
+ } else if ((*code >> 4) == 0b1011) {
+ i += inst_move_imm_to_reg();
+ } else if ((*code >> 1) == 0b1010000) {
+ i += inst_move_mem_to_accum(1);
+ } else if ((*code >> 1) == 0b1010001) {
+ i += inst_move_mem_to_accum(0);
+ } else if (*code == 0b01110101) {
+ i += 2;
+ printf("jnz %d\n", get_byte_displacement());
+ } else if (*code == 0b01110100) {
+ i += 2;
+ printf("je %d\n", get_byte_displacement());
+ } else if (*code == 0b01111100) {
+ i += 2;
+ printf("jl %d\n", get_byte_displacement());
+ } else if (*code == 0b01111110) {
+ i += 2;
+ printf("jle %d\n", get_byte_displacement());
+ } else if (*code == 0b01110010) {
+ i += 2;
+ printf("jb %d\n", get_byte_displacement());
+ } else if (*code == 0b01110110) {
+ i += 2;
+ printf("jbe %d\n", get_byte_displacement());
+ } else if (*code == 0b01111010) {
+ i += 2;
+ printf("jp %d\n", get_byte_displacement());
+ } else if (*code == 0b01110000) {
+ i += 2;
+ printf("jo %d\n", get_byte_displacement());
+ } else if (*code == 0b01111000) {
+ i += 2;
+ printf("js %d\n", get_byte_displacement());
+ } else if (*code == 0b01110101) {
+ i += 2;
+ printf("jne %d\n", get_byte_displacement());
+ } else if (*code == 0b01111101) {
+ i += 2;
+ printf("jnl %d\n", get_byte_displacement());
+ } else if (*code == 0b01111111) {
+ i += 2;
+ printf("jg %d\n", get_byte_displacement());
+ } else if (*code == 0b01110011) {
+ i += 2;
+ printf("jnb %d\n", get_byte_displacement());
+ } else if (*code == 0b01110111) {
+ i += 2;
+ printf("ja %d\n", get_byte_displacement());
+ } else if (*code == 0b01111011) {
+ i += 2;
+ printf("jnp %d\n", get_byte_displacement());
+ } else if (*code == 0b01110001) {
+ i += 2;
+ printf("jno %d\n", get_byte_displacement());
+ } else if (*code == 0b01111001) {
+ i += 2;
+ printf("jns %d\n", get_byte_displacement());
+ } else if (*code == 0b11100010) {
+ i += 2;
+ printf("loop %d\n", get_byte_displacement());
+ } else if (*code == 0b11100001) {
+ i += 2;
+ printf("loopz %d\n", get_byte_displacement());
+ } else if (*code == 0b11100000) {
+ i += 2;
+ printf("loopnz %d\n", get_byte_displacement());
+ } else if (*code == 0b11100011) {
+ i += 2;
+ printf("jcxz %d\n", get_byte_displacement());
+ } else { Assert(false && "Invalid instruction"); }
+ }
}