summaryrefslogtreecommitdiffstats
path: root/src/disasm.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/disasm.c')
-rw-r--r--src/disasm.c147
1 files changed, 93 insertions, 54 deletions
diff --git a/src/disasm.c b/src/disasm.c
index 62f3fab..2f59dfe 100644
--- a/src/disasm.c
+++ b/src/disasm.c
@@ -1,3 +1,8 @@
+#include <Windows.h>
+
+#include "disasm.h"
+#include "utils.h"
+
const u8 MAX_LEGACY_PREFIXES = 4U;
const u8 legacy_prefixes[] = {
// Operand-size override
@@ -108,7 +113,7 @@ struct opcode {
const struct opcode rep_f3_opcode_map[] = {
{ "PAUSE", { .src = None }, { .src = None }}, // 0x90
-}
+};
const struct opcode primary_opcode_map[256U] = {
{ "ADD", { .src = TYPE_E, .type = TYPE_BYTE }, { .src = ModRM_Reg, .type = TYPE_BYTE }},
@@ -516,6 +521,13 @@ const struct opcode group_11[2U] = {
{ "MOV", { .src = TYPE_E, .type = TYPE_v }, { .src = Imm, .type = TYPE_z }},
};
+const u8 mod_to_disp_size[4U] = {
+ 4U,
+ 1U,
+ 4U,
+ 0U,
+};
+
u8 is_legacy_prefix(u8 byte) {
for (u8 index = 0U; index < sizeof(legacy_prefixes); index++) {
if (byte == legacy_prefixes[index]) {
@@ -599,7 +611,7 @@ u64 get_immediate(u8** bytes, enum DATA_TYPE type, u8 operand_effective_size) {
return imm;
}
-u8 get_immediate_size(enum OPERAND_TYPE type, u8 operand_effective_size) {
+u8 get_immediate_size(enum DATA_TYPE type, u8 operand_effective_size) {
if (type == TYPE_BYTE) {
return 1U;
} else if (type == TYPE_WORD) {
@@ -617,16 +629,16 @@ u8 get_immediate_size(enum OPERAND_TYPE type, u8 operand_effective_size) {
}
#define MODRM_MOD(ModRM) (ModRM >> 6U)
-#define MODRM_REG(ModRM) (ModRM & 0b00111000) >> 0x3
+#define MODRM_REG(ModRM) ((ModRM & 0b00111000) >> 0x3)
#define MODRM_RM(ModRM) (ModRM & 0b00000111)
#define SIB_SCALE(SIB) (SIB >> 6U)
-#define SIB_INDEX(SIB) (SIB & 0b00111000) >> 0x3
+#define SIB_INDEX(SIB) ((SIB & 0b00111000) >> 0x3)
#define SIB_BASE(SIB) (SIB & 0b00000111)
-#define REXW(REX) (REX & 0b00001000) >> 3U
-#define REXR(REX) (REX & 0b00000100) >> 2U
-#define REXX(REX) (REX & 0b00000010) >> 1U
+#define REXW(REX) ((REX & 0b00001000) >> 3U)
+#define REXR(REX) ((REX & 0b00000100) >> 2U)
+#define REXX(REX) ((REX & 0b00000010) >> 1U)
#define REXB(REX) (REX & 0b00000001)
// void unassemble(CONTEXT* ctx, u32 count) {
@@ -679,24 +691,31 @@ void unassemble(u8* start, u64 size) {
op = &primary_opcode_map[op_byte];
}
- u8 has_displacement = FALSE;
+ u8 disp_bytes_count = 0U;
u8 has_src_SIB = FALSE;
u8 has_dst_SIB = FALSE;
if (op->src_operand.src & (TYPE_E | ModRM_Reg) || op->dst_operand.src & (TYPE_E | ModRM_Reg)) {
u8 Mod = MODRM_MOD(ModRM);
u8 RM = MODRM_RM(ModRM);
- if (Mod == 0b10 || Mod == 0b01) {
- has_displacement = TRUE;
+ // Table 1-14
+ // Displacement detection
+ if (Mod == 0b00 && RM == 0b101) {
+ disp_bytes_count = mod_to_disp_size[Mod];
+ } else if (Mod != 0b11) {
+ disp_bytes_count = mod_to_disp_size[Mod];
}
- if (Mod != 0b11 && RM == 0b100) { // This may not be the only way to has an SIB byte
+ // SIB detection
+ if (Mod != 0b11 && RM == 0b100) { // This may not be the only way to have an SIB byte
if (op->src_operand.src & (TYPE_E | ModRM_Reg)) {
has_src_SIB = TRUE;
}
if (op->dst_operand.src & (TYPE_E | ModRM_Reg)) {
has_dst_SIB = TRUE;
}
+ // NOTE: We probably can't have both operand needing an SIB byte
+ assert(!(has_src_SIB == has_dst_SIB == TRUE));
}
current_byte++;
@@ -704,14 +723,23 @@ void unassemble(u8* start, u64 size) {
// SIB
u8 SIB = *current_byte;
- if (has_SIB) {
+ if (has_src_SIB || has_dst_SIB) {
+ u8 Mod = MODRM_MOD(ModRM);
+ if (SIB_BASE(SIB)) {
+ disp_bytes_count = mod_to_disp_size[Mod];
+ }
current_byte++;
}
// Displacement bits
- if (has_displacement) {
- // Read displacement bits
- current_byte++;
+ u32 disp = 0U;
+ if (disp_bytes_count) {
+ if (disp_bytes_count == 1U) {
+ disp = *current_byte;
+ } else if (disp_bytes_count == 4U) {
+ disp = *((u32*)current_byte);
+ }
+ current_byte += disp_bytes_count;
}
u64 src_imm = 0U;
@@ -728,56 +756,67 @@ void unassemble(u8* start, u64 size) {
u8 inst_size = (u8)(current_byte - inst_start);
- for (u8 index = 0U; index < inst_size; index++) {
- print("%2xb ", inst_start[index]);
- }
- print("\t\t%s", op->name);
-
- if (op->src_operand.src == Imm) {
- print(" %u", src_imm);
- } else if (op->src_operand.src == ModRM_Reg) {
- u8 Reg = MODRM_REG(ModRM);
- print(" %s", ModRM_registers[Reg][3U]);
- } else if (op->src_operand.src == TYPE_E) {
- u8 Mod = MODRM_MOD(ModRM);
- u8 RM = MODRM_RM(ModRM);
- if (Mod == 0b11) {
- print(" %s", ModRM_registers[RM][3U]);
+ for (u8 index = 0U; index < 6U; index++) {
+ if (index < inst_size) {
+ print("%.2x ", inst_start[index]);
+ } else {
+ print(" ");
}
}
+ print("%s", op->name);
- if (has_src_SIB) {
- // Read SIB
- i32 scale_factors[4U] = {
- 1, 2, 4, 8,
+ // Src operand
+ {
+ if (op->src_operand.src == Imm) {
+ print(" %u", src_imm);
+ } else if (op->src_operand.src == ModRM_Reg) {
+ u8 Reg = MODRM_REG(ModRM);
+ print(" %s", ModRM_registers[Reg][3U]);
+ } else if (op->src_operand.src == TYPE_E) {
+ u8 Mod = MODRM_MOD(ModRM);
+ u8 RM = MODRM_RM(ModRM);
+ if (Mod == 0b11) {
+ print(" %s", ModRM_registers[RM][3U]);
+ }
}
- effective_address = scale_factors[SIB_SCALE(SIB)] * SIB_INDEX(SIB) + SIB_BASE(SIB) + off;
- }
- if (op->dst_operand.src == Imm) {
- print(" %xu", dst_imm);
+ if (has_src_SIB) {
+ // Read SIB
+ i32 scale_factors[4U] = {
+ 1, 2, 4, 8,
+ };
+ i32 off = 0; // displacement bytes
+ effective_address = scale_factors[SIB_SCALE(SIB)] * SIB_INDEX(SIB) + SIB_BASE(SIB) + off;
+ }
}
- if (has_dst_SIB) {
- // Read SIB
- i32 scale_factors[4U] = {
- 1, 2, 4, 8,
+ // Dst operand
+ {
+ if (op->dst_operand.src == Imm) {
+ print(" %x", dst_imm);
}
- u8 index = SIB_INDEX(SIB);
- if (index != 0b100) {
- print(" [%d * %s", scale_factors[SIB_SCALE(SIB)], SIB_index_registers[index]);
- }
+ if (has_dst_SIB) {
+ // Read SIB
+ i32 scale_factors[4U] = {
+ 1, 2, 4, 8,
+ };
- u8 base = SIB_BASE(SIB);
- if (base != 0b101 && MODRM_MOD(ModRM) != 0U) {
- print(" + %s", SIB_base_registers[base]);
- }
+ u8 index = SIB_INDEX(SIB);
+ if (index != 0b100) {
+ print(" [%d * %s", scale_factors[SIB_SCALE(SIB)], SIB_index_registers[index]);
+ }
- if (has_displacement) {
- print("+ %d]", );
- } else {
- print("]");
+ u8 base = SIB_BASE(SIB);
+ if (base != 0b101 && MODRM_MOD(ModRM) != 0U) {
+ print(" + %s", SIB_base_registers[base]);
+ }
+
+ if (disp_bytes_count) {
+ print("+ %d]", disp);
+ } else {
+ print("]");
+ }
}
}