From 620f9e0daa7f2d018c7a920309d2e14f95c5cb04 Mon Sep 17 00:00:00 2001 From: Abdelrahman Date: Sat, 11 Mar 2023 19:50:09 +0000 Subject: [PATCH] Completed decoding the challenging mov instructions --- 8086_assembly_02/.gitignore | 2 + 8086_assembly_02/dasm.cpp | 207 +++++++++++++----- .../listing_0040_challenge_movs.asm | 38 ++++ .../listing_0040_challenge_movs_out.asm | 13 ++ 4 files changed, 200 insertions(+), 60 deletions(-) create mode 100644 8086_assembly_02/listing_0040_challenge_movs.asm create mode 100644 8086_assembly_02/listing_0040_challenge_movs_out.asm diff --git a/8086_assembly_02/.gitignore b/8086_assembly_02/.gitignore index 8812d96..73cd3ec 100644 --- a/8086_assembly_02/.gitignore +++ b/8086_assembly_02/.gitignore @@ -1,3 +1,5 @@ dasm listing_0039_more_movs listing_0039_more_movs_out +listing_0040_challenge_movs +listing_0040_challenge_movs_out diff --git a/8086_assembly_02/dasm.cpp b/8086_assembly_02/dasm.cpp index 8aa1cb1..8c4aed6 100644 --- a/8086_assembly_02/dasm.cpp +++ b/8086_assembly_02/dasm.cpp @@ -1,11 +1,22 @@ #include +#include #include #include #include -enum class INST_MASKS { - IMM_TO_REG = 0xb0, +enum class INST_BITS { REG_MEM_REG = 0x88, + MEM_TO_ACC = 0xa0, + ACC_TO_MEM = 0xa2, + IMM_TO_REG = 0xb0, + IMM_TO_REG_MEM = 0xc6, +}; + +enum class INST_MASKS { + REG_MEM_REG = 0xfc, + IMM_TO_REG = 0xf0, + IMM_TO_REG_MEM = 0xfe, + ACCUMULATOR = 0xfe, }; enum class MODE { @@ -15,9 +26,13 @@ enum class MODE { REG = 0xc0, }; -bool mask_instruction(uint8_t instruction, uint8_t mask); +bool mask_instruction(uint8_t instruction, uint8_t inst_bits, uint8_t mask); void decode_register(uint8_t instruction, bool word, char *dest); void decode_rm(uint8_t instruction, char *dest); +void stringify_rm_and_disp(FILE *fp, uint8_t operands, char *rm, + uint32_t buff_size); +void handle_accumulator_mov_instructions(FILE *fp, uint8_t inst, bool reg_dest, + char *dest); int main(int argc, char *argv[]) { if (argc < 2) { @@ -42,30 +57,8 @@ int main(int argc, char *argv[]) { fprintf(out, "; Disassembled by DASM\n\nbits 16\n\n"); while (fread(&inst, sizeof(inst), 1, fp)) { - if (mask_instruction(inst, (uint8_t)INST_MASKS::IMM_TO_REG)) { - op = "mov"; - - // Bit pattern is: - // 7 6 5 4 3 2 1 0 - // ------------------------------- - // | 1 | 0 | 1 | 1 | w | reg | - // ------------------------------- - // - // So, we need to mask the fourth bit to check the w flag - bool word = mask_instruction(inst, 0x08); - - uint8_t next_bytes = word ? 2 : 1; - - char reg[3] = {0}; - - decode_register(inst, word, reg); - - int16_t data = 0; - - fread(&data, sizeof(next_bytes), next_bytes, fp); - - fprintf(out, "%s %s, %d\n", op, reg, word ? data : (int8_t)data); - } else if (mask_instruction(inst, (uint8_t)INST_MASKS::REG_MEM_REG)) { + if (mask_instruction(inst, (uint8_t)INST_BITS::REG_MEM_REG, + (uint8_t)INST_MASKS::REG_MEM_REG)) { op = "mov"; uint8_t operands = 0; @@ -83,14 +76,15 @@ int main(int argc, char *argv[]) { // | mod | reg | r/m | // ------------------------------- - bool reg_dest = mask_instruction(inst, 0x02); + bool reg_dest = mask_instruction(inst, 0x02, 0x02); - bool word = mask_instruction(inst, 0x01); + bool word = mask_instruction(inst, 0x01, 0x01); char reg[3] = {0}; decode_register(operands >> 3, word, reg); - if (mask_instruction(operands, (uint8_t)MODE::REG)) { + if (mask_instruction(operands, (uint8_t)MODE::REG, + (uint8_t)MODE::REG)) { char rm[3] = {0}; decode_register(operands, word, rm); @@ -98,38 +92,78 @@ int main(int argc, char *argv[]) { reg_dest ? rm : reg); } else { char rm[20] = {0}; - decode_rm(operands, rm); - - bool direct_address = false; - - uint8_t next_bytes = operands >> 6; - - if (next_bytes == 0 && mask_instruction(operands, 0x06)) { - // Handle case when MOD == 00 and R/M == 110 - next_bytes = 2; - - direct_address = true; - } - - int16_t data = 0; - fread(&data, sizeof(next_bytes), next_bytes, fp); - - if (data > 0) { - if (direct_address) { - memset(rm, 0, 20); - - sprintf(rm, "%d", data); - } else { - char data_out[20] = {0}; - sprintf(data_out, " + %d", data); - - strcat(rm, data_out); - } - } + stringify_rm_and_disp(fp, operands, rm, 20); fprintf(out, reg_dest ? "%s %s, [%s]\n" : "%s [%s], %s\n", op, reg_dest ? reg : rm, reg_dest ? rm : reg); } + } else if (mask_instruction(inst, (uint8_t)INST_BITS::IMM_TO_REG, + (uint8_t)INST_MASKS::IMM_TO_REG)) { + op = "mov"; + + // Bit pattern is: + // 7 6 5 4 3 2 1 0 + // ------------------------------- + // | 1 | 0 | 1 | 1 | w | reg | + // ------------------------------- + // + // So, we need to mask the fourth bit to check the w flag + bool word = mask_instruction(inst, 0x08, 0x08); + + uint8_t next_bytes = word ? 2 : 1; + + char reg[3] = {0}; + + decode_register(inst, word, reg); + + int16_t data = 0; + + fread(&data, sizeof(next_bytes), next_bytes, fp); + + fprintf(out, "%s %s, %d\n", op, reg, word ? data : (int8_t)data); + } else if (mask_instruction(inst, (uint8_t)INST_BITS::IMM_TO_REG_MEM, + (uint8_t)INST_MASKS::IMM_TO_REG_MEM)) { + op = "mov"; + + uint8_t operands = 0; + fread(&operands, sizeof(operands), 1, fp); + + // Instruction bit pattern is: + // 7 6 5 4 3 2 1 0 + // ------------------------------- + // | 1 | 1 | 0 | 0 | 0 | 1 | 1 | w | + // ------------------------------- + // + // Operands bit pattern is: + // 7 6 5 4 3 2 1 0 + // ------------------------------- + // | mod | 000 | r/m | + // ------------------------------- + + bool word = mask_instruction(inst, 0x01, 0x01); + + char rm[20] = {0}; + stringify_rm_and_disp(fp, operands, rm, 20); + + uint8_t next_bytes = word ? 2 : 1; + + int16_t data = 0; + fread(&data, sizeof(next_bytes), next_bytes, fp); + + fprintf(out, "%s [%s], %s %d\n", op, rm, word ? "word" : "byte", + word ? data : (int8_t)data); + } else if (mask_instruction(inst, (uint8_t)INST_BITS::MEM_TO_ACC, + (uint8_t)INST_MASKS::ACCUMULATOR)) { + char inst_out[256] = {0}; + handle_accumulator_mov_instructions(fp, inst, true, inst_out); + + fprintf(out, "%s\n", inst_out); + } else if (mask_instruction(inst, (uint8_t)INST_BITS::ACC_TO_MEM, + (uint8_t)INST_MASKS::ACCUMULATOR)) { + char inst_out[256] = {0}; + handle_accumulator_mov_instructions(fp, inst, false, inst_out); + + fprintf(out, "%s\n", inst_out); } else { printf("It's not a mov operation\n"); } @@ -148,8 +182,8 @@ int main(int argc, char *argv[]) { return 0; } -bool mask_instruction(uint8_t instruction, uint8_t mask) { - return (instruction & mask) == mask; +bool mask_instruction(uint8_t instruction, uint8_t inst_bits, uint8_t mask) { + return (instruction & mask) == inst_bits; } void decode_register(uint8_t instruction, bool word, char *dest) { @@ -196,3 +230,56 @@ void decode_rm(uint8_t instruction, char *dest) { strcpy(dest, table[index]); } + +void stringify_rm_and_disp(FILE *fp, uint8_t operands, char *rm, + uint32_t buff_size) { + decode_rm(operands, rm); + + bool direct_address = false; + + uint8_t next_bytes = operands >> 6; + + if (next_bytes == 0 && mask_instruction(operands, 0x06, 0x06)) { + // Handle case when MOD == 00 and R/M == 110 + next_bytes = 2; + + direct_address = true; + } + + int16_t disp = 0; + fread(&disp, sizeof(next_bytes), next_bytes, fp); + + if (disp != 0) { + if (direct_address) { + memset(rm, 0, buff_size); + + sprintf(rm, "%d", disp); + } else { + bool positive = next_bytes > 1 ? disp > 0 : (int8_t)disp > 0; + + char data_out[buff_size]; + memset(data_out, 0, buff_size); + + sprintf(data_out, " %c %d", positive ? '+' : '-', + next_bytes > 1 ? abs(disp) : abs((int8_t)disp)); + + strcat(rm, data_out); + } + } +} + +void handle_accumulator_mov_instructions(FILE *fp, uint8_t inst, bool reg_dest, + char *dest) { + bool word = mask_instruction(inst, 0x01, 0x01); + + uint8_t next_bytes = word ? 2 : 1; + + uint16_t addr = 0; + fread(&addr, sizeof(next_bytes), next_bytes, fp); + + char addr_out[64] = {0}; + sprintf(addr_out, "[%d]", word ? addr : (uint8_t)addr); + + sprintf(dest, "mov %s, %s", reg_dest ? "ax" : addr_out, + reg_dest ? addr_out : "ax"); +} diff --git a/8086_assembly_02/listing_0040_challenge_movs.asm b/8086_assembly_02/listing_0040_challenge_movs.asm new file mode 100644 index 0000000..966e47a --- /dev/null +++ b/8086_assembly_02/listing_0040_challenge_movs.asm @@ -0,0 +1,38 @@ +; ======================================================================== +; +; (C) Copyright 2023 by Molly Rocket, Inc., All Rights Reserved. +; +; This software is provided 'as-is', without any express or implied +; warranty. In no event will the authors be held liable for any damages +; arising from the use of this software. +; +; Please see https://computerenhance.com for further information +; +; ======================================================================== + +; ======================================================================== +; LISTING 40 +; ======================================================================== + +bits 16 + +; Signed displacements +mov ax, [bx + di - 37] +mov [si - 300], cx +mov dx, [bx - 32] + +; Explicit sizes +mov [bp + di], byte 7 +mov [di + 901], word 347 + +; Direct address +mov bp, [5] +mov bx, [3458] + +; Memory-to-accumulator test +mov ax, [2555] +mov ax, [16] + +; Accumulator-to-memory test +mov [2554], ax +mov [15], ax diff --git a/8086_assembly_02/listing_0040_challenge_movs_out.asm b/8086_assembly_02/listing_0040_challenge_movs_out.asm new file mode 100644 index 0000000..69ff2bc --- /dev/null +++ b/8086_assembly_02/listing_0040_challenge_movs_out.asm @@ -0,0 +1,13 @@ +bits 16 + +mov ax, [bx + di - 37] +mov [si - 300], cx +mov dx, [bx - 32] +mov [bp + di], byte 7 +mov [di + 901], word 347 +mov bp, [5] +mov bx, [3458] +mov ax, [2555] +mov ax, [16] +mov [2554], ax +mov [15], ax