package decoder_8086 import "core:os" import "core:fmt" Register :: struct { fullname: string, bytename: string, value: struct #raw_union { using _: struct { low, high: byte, }, full: u16, }, code: u8, } RegMemMode :: enum { Memory00 = 0b00, Memory08 = 0b01, Memory16 = 0b10, Register = 0b11, }; registers := [8]Register { {fullname = "ax", bytename = "al", code = 0b000}, {fullname = "cx", bytename = "cl", code = 0b001}, {fullname = "dx", bytename = "dl", code = 0b010}, {fullname = "bx", bytename = "bl", code = 0b011}, {fullname = "sp", bytename = "ah", code = 0b100}, {fullname = "bp", bytename = "ch", code = 0b101}, {fullname = "si", bytename = "dh", code = 0b110}, {fullname = "di", bytename = "bh", code = 0b111}, } Instruction :: struct { mask: u8, encoding: u8, name: string, desc: string, } instructions := [?]Instruction { { mask = 0b11111100, encoding = 0b10001000, name = "mov", desc = "Register/memory to/from register" }, { mask = 0b11111110, encoding = 0b11000110, name = "mov", desc = "Immediate to register/memory" }, { mask = 0b11110000, encoding = 0b10110000, name = "mov", desc = "Immediate to register" }, { mask = 0b11111110, encoding = 0b10100000, name = "mov", desc = "Memory to accumulator" }, { mask = 0b11111110, encoding = 0b10100010, name = "mov", desc = "Accumulator to memory" }, { mask = 0b11111111, encoding = 0b10001110, name = "mov", desc = "Register/memory to segment register" }, { mask = 0b11111111, encoding = 0b10001100, name = "mov", desc = "Segment register to register/memory" }, } inst_map := make(map[u8]Instruction) RIGHT_ALIGN_AMOUNT := 30 get_instruction :: proc(bytes: []u8) -> (Instruction, u8) { return {}, 0 } calculate_effective_address :: proc(r_m: u8) -> string { val: string switch r_m { case 0b000: val = "bx + si" case 0b001: val = "bx + di" case 0b010: val = "bp + si" case 0b011: val = "bp + di" case 0b100: val = "si" case 0b101: val = "di" case 0b110: val = "bp" case 0b111: val = "bx" } return val } main :: proc() { ax := registers[0] ax.value.full = 52428 f,err := os.open(len(os.args) > 1 ? os.args[1] : "./asm_files/01-02-39.bin") if err != os.ERROR_NONE { os.exit(1) } defer os.close(f) data := make([]u8, 512) bytes_read, err2 := os.read(f, data) if err2 != nil { // ... os.exit(1) } for inst in instructions { inst_map[inst.encoding] = inst } if false { for i in 0..> 6 reg := (next_byte & 0b00111000) >> 3 rm := next_byte & 0b00000111 dst_reg := registers[rm] disp: string if mod == 1 { disp_byte := (i16)(data[processed + 2]) disp_amount = 1 disp = disp_byte == 0 ? "" : fmt.aprintf(" + %d", disp_byte) } else if mod == 2 { disp_byte := (i16)(data[processed + 3]) << 8 | (i16)(data[processed + 2]) disp_amount = 2 disp = disp_byte == 0 ? "" : fmt.aprintf(" + %d", disp_byte) } else { disp = "" } src_name: string if mod == 3 { // Register-to-register src_name = is_word ? registers[rm].fullname : registers[rm].bytename } else { src_name = fmt.aprintf("[%s%s]", calculate_effective_address(rm), disp) } dst_name := is_word ? registers[reg].fullname : registers[reg].bytename if flip_src { src_name, dst_name = dst_name, src_name } processed += 1 + ((int)(mod) % 3) inst_string := fmt.aprintf("mov %s, %s", src_name, dst_name) fmt.printfln("%s %*[1]s %08b %08b", inst_string, RIGHT_ALIGN_AMOUNT - len(inst_string), ";; 1", curr_byte, next_byte) } else if curr_byte & 0b1111_0000 == 0b10110000 { is_word := curr_byte & 0b0000_1000 != 0 reg := curr_byte & 0b00000111 dst_name: string imm: i16 if is_word { dst_name = registers[reg].fullname imm = (i16)(data[processed+2]) << 8 | (i16)(data[processed+1]) processed += 2 } else { dst_name = registers[reg].bytename imm = (i16)(data[processed+1]) processed += 1 } inst_string := fmt.aprintf("mov %s, %d", dst_name, imm) fmt.printfln("%s %*[1]s %08b %08b", inst_string, RIGHT_ALIGN_AMOUNT - len(inst_string), ";; 2", curr_byte, data[processed + 1]) } else { fmt.printfln("unknown instruction ;; %b", curr_byte) } processed += 1 } }