summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/disasm.c656
1 files changed, 462 insertions, 194 deletions
diff --git a/src/disasm.c b/src/disasm.c
index e38a6db..c312348 100644
--- a/src/disasm.c
+++ b/src/disasm.c
@@ -109,34 +109,93 @@ const u8 REX_prefixes[] = {
};
const char* registers[] = {
+ "AL",
+ "AH",
+ "AX",
+ "EAX",
"RAX",
+ "BL",
+ "BH",
+ "BX",
+ "EBX",
"RBX",
+ "CL",
+ "CH",
+ "CX",
+ "ECX",
"RCX",
+ "DL",
+ "DH",
+ "DX",
+ "EDX",
"RDX",
+ "SIL",
+ "SI",
+ "ESI",
"RSI",
+ "DIL",
+ "DI",
+ "EDI",
"RDI",
+ "BPL",
+ "BP",
+ "EBP",
"RBP",
+ "SPL",
+ "SP",
+ "ESP",
"RSP",
+ "R8B",
+ "R8W",
+ "R8D",
"R8",
+ "R9B",
+ "R9W",
+ "R9D",
"R9",
+ "R10B",
+ "R10W",
+ "R10D",
"R10",
+ "R11B",
+ "R11W",
+ "R11D",
"R11",
+ "R12B",
+ "R12W",
+ "R12D",
"R12",
+ "R13B",
+ "R13W",
+ "R13D",
"R13",
+ "R14B",
+ "R14W",
+ "R14D",
"R14",
+ "R15B",
+ "R15W",
+ "R15D",
"R15",
"RIP",
+ // Segments
+ "CS",
+ "DS", // Ignored in 64 mode
+ "ES", // Ignored in 64 mode
+ "FS",
+ "GS",
+ "SS", // Ignored in 64 mode
};
const char* ModRM_registers[8U][5U] = {
- { "YMM0", "XMM0", "MMX0", "RAX" },
- { "YMM1", "XMM1", "MMX1", "RCX" },
- { "YMM2", "XMM2", "MMX2", "RDX" },
- { "YMM3", "XMM3", "MMX3", "RBX" },
- { "YMM4", "XMM4", "MMX4", "RSP", "AH" },
- { "YMM5", "XMM5", "MMX5", "RBP", "CH" },
- { "YMM6", "XMM6", "MMX6", "RSI", "DH" },
- { "YMM7", "XMM7", "MMX7", "RDI", "BH" }
+ { NULL, "RAX", "MMX0", "XMM0", "YMM0" },
+ { NULL, "RCX", "MMX1", "XMM1", "YMM1" },
+ { NULL, "RDX", "MMX2", "XMM2", "YMM2" },
+ { NULL, "RBX", "MMX3", "XMM3", "YMM3" },
+ { "AH", "RSP", "MMX4", "XMM4", "YMM4" },
+ { "CH", "RBP", "MMX5", "XMM5", "YMM5" },
+ { "DH", "RSI", "MMX6", "XMM6", "YMM6" },
+ { "BH", "RDI", "MMX7", "XMM7", "YMM7" }
};
const char* SIB_index_registers[8U] = {
@@ -168,14 +227,17 @@ struct operand {
// In some cases instruction forces 64bit operand size
enum OPERAND_TYPE {
None,
- Inst_FAR, // A
- TYPE_E, // E
- ModRM_Reg, // G
- Imm, // I
- ModRM_MEM, // M, mod != 0b11
- Vector_REG, // L
- DS_rSI, // X
- ES_rSI, // Y
+ Inst_FAR, // A
+ TYPE_E, // E
+ ModRM_Reg, // G
+ Imm, // I
+ TYPE_J, // Relative offset added to RIP
+ ModRM_MEM, // M, mod != 0b11
+ Vector_REG, // L
+ ModRM_Seg_Reg, // S
+ TYPE_R, // R mod != 0b11
+ DS_rSI, // X
+ ES_rSI, // Y
Reg,
} src; // Handle eventual SIB byte following ModRM byte
@@ -183,7 +245,7 @@ struct operand {
enum DATA_TYPE {
TYPE_NONE = 0x0,
TYPE_BYTE = 0x1, // b
- TYPE_WORD = 0x2,
+ TYPE_WORD = 0x2, // w
TYPE_DWORD = 0x4,
TYPE_QWORD = 0x8,
TYPE_FP = 0x10,
@@ -193,23 +255,82 @@ struct operand {
TYPE_1 = 0x2000, // Hardcoded 1
} type;
enum REGISTER {
+ AL,
+ AH,
+ AX,
+ EAX,
RAX,
+ BL,
+ BH,
+ BX,
+ EBX,
RBX,
+ CL,
+ CH,
+ CX,
+ ECX,
RCX,
+ DL,
+ DH,
+ DX,
+ EDX,
RDX,
+ SIL,
+ SI,
+ ESI,
RSI,
+ DIL,
+ DI,
+ EDI,
RDI,
+ BPL,
+ BP,
+ EBP,
RBP,
+ SPL,
+ SP,
+ ESP,
RSP,
+ R8B,
+ R8W,
+ R8D,
R8,
+ R9B,
+ R9W,
+ R9D,
R9,
+ R10B,
+ R10W,
+ R10D,
R10,
+ R11B,
+ R11W,
+ R11D,
R11,
+ R12B,
+ R12W,
+ R12D,
R12,
+ R13B,
+ R13W,
+ R13D,
R13,
+ R14B,
+ R14W,
+ R14D,
R14,
+ R15B,
+ R15W,
+ R15D,
R15,
RIP,
+ // Segments
+ CS,
+ DS, // Ignored in 64 mode
+ ES, // Ignored in 64 mode
+ FS,
+ GS,
+ SS, // Ignored in 64 mode
} reg;
};
// SSE stuff
@@ -230,90 +351,90 @@ const struct opcode primary_opcode_map[256U] = {
{ "ADD", { .src = TYPE_E, .type = TYPE_v}, { .src = ModRM_Reg, .type = TYPE_v }},
{ "ADD", { .src = ModRM_Reg, .type = TYPE_BYTE }, { .src = TYPE_E, .type = TYPE_BYTE }},
{ "ADD", { .src = ModRM_Reg, .type = TYPE_v }, { .src = TYPE_E, .type = TYPE_v }},
- { "ADD", { .src = ModRM_Reg, .type = TYPE_v }, { .src = Imm, .type = TYPE_BYTE }}, // AL, need to understand and handle
- { "ADD", { .src = ModRM_Reg, .type = TYPE_v }, { .src = TYPE_E, .type = TYPE_v }},
- { "PUSH", { .src = ModRM_Reg, .type = TYPE_v }, { .src = Imm, .type = TYPE_BYTE }}, // TODO
- { "POP", { .src = ModRM_Reg, .type = TYPE_v }, { .src = TYPE_E, .type = TYPE_v }}, // TODO
+ { "ADD", { .src = Reg, .reg = AL }, { .src = Imm, .type = TYPE_BYTE }},
+ { "ADD", { .src = Reg, .reg = RAX }, { .src = Imm, .type = TYPE_z }},
+ { "PUSH", { .src = Reg, .reg = ES }, { .src = None }},
+ { "POP", { .src = Reg, .reg = ES }, { .src = None, }},
{ "OR", { .src = TYPE_E, .type = TYPE_BYTE }, { .src = ModRM_Reg, .type = TYPE_BYTE }},
{ "OR", { .src = TYPE_E, .type = TYPE_v}, { .src = ModRM_Reg, .type = TYPE_v }},
{ "OR", { .src = ModRM_Reg, .type = TYPE_BYTE }, { .src = TYPE_E, .type = TYPE_BYTE }},
{ "OR", { .src = ModRM_Reg, .type = TYPE_v }, { .src = TYPE_E, .type = TYPE_v }},
- { "OR", { .src = ModRM_Reg, .type = TYPE_v }, { .src = Imm, .type = TYPE_BYTE }}, // AL, need to understand and handle
- { "OR", { .src = ModRM_Reg, .type = TYPE_v }, { .src = TYPE_E, .type = TYPE_v }},
- { "PUSH", { .src = ModRM_Reg, .type = TYPE_v }, { .src = Imm, .type = TYPE_BYTE }}, // TODO
- { "INVALID", { .src = None }, { .src = None }}, // Escape to secondary op code map
+ { "OR", { .src = Reg, .reg = AL }, { .src = Imm, .type = TYPE_BYTE }},
+ { "OR", { .src = Reg, .reg = RAX }, { .src = Imm, .type = TYPE_z }},
+ { "PUSH", { .src = Reg, .reg = CS }, { .src = None }},
+ { "INVALID", { .src = None }, { .src = None }}, // Escape to secondary op code map
{ "ADC", { .src = TYPE_E, .type = TYPE_BYTE }, { .src = ModRM_Reg, .type = TYPE_BYTE }},
{ "ADC", { .src = TYPE_E, .type = TYPE_v}, { .src = ModRM_Reg, .type = TYPE_v }},
{ "ADC", { .src = ModRM_Reg, .type = TYPE_BYTE }, { .src = TYPE_E, .type = TYPE_BYTE }},
{ "ADC", { .src = ModRM_Reg, .type = TYPE_v }, { .src = TYPE_E, .type = TYPE_v }},
- { "ADC", { .src = ModRM_Reg, .type = TYPE_v }, { .src = Imm, .type = TYPE_BYTE }}, // AL, need to understand and handle
- { "ADC", { .src = ModRM_Reg, .type = TYPE_v }, { .src = TYPE_E, .type = TYPE_v }},
- { "PUSH", { .src = ModRM_Reg, .type = TYPE_v }, { .src = Imm, .type = TYPE_BYTE }}, // TODO
- { "POP", { .src = ModRM_Reg, .type = TYPE_v }, { .src = TYPE_E, .type = TYPE_v }}, // TODO
+ { "ADC", { .src = Reg, .reg = AL }, { .src = Imm, .type = TYPE_BYTE }},
+ { "ADC", { .src = Reg, .reg = RAX }, { .src = Imm, .type = TYPE_z }},
+ { "PUSH", { .src = Reg, .reg = SS }, { .src = None }},
+ { "POP", { .src = Reg, .reg = SS }, { .src = None }},
{ "SBB", { .src = TYPE_E, .type = TYPE_BYTE }, { .src = ModRM_Reg, .type = TYPE_BYTE }},
{ "SBB", { .src = TYPE_E, .type = TYPE_v}, { .src = ModRM_Reg, .type = TYPE_v }},
{ "SBB", { .src = ModRM_Reg, .type = TYPE_BYTE }, { .src = TYPE_E, .type = TYPE_BYTE }},
{ "SBB", { .src = ModRM_Reg, .type = TYPE_v }, { .src = TYPE_E, .type = TYPE_v }},
- { "SBB", { .src = ModRM_Reg, .type = TYPE_v }, { .src = Imm, .type = TYPE_BYTE }}, // AL, need to understand and handle
- { "ADC", { .src = ModRM_Reg, .type = TYPE_v }, { .src = TYPE_E, .type = TYPE_v }},
- { "PUSH", { .src = ModRM_Reg, .type = TYPE_v }, { .src = Imm, .type = TYPE_BYTE }}, // TODO
- { "POP", { .src = ModRM_Reg, .type = TYPE_v }, { .src = TYPE_E, .type = TYPE_v }}, // TODO
+ { "SBB", { .src = Reg, .reg = AL }, { .src = Imm, .type = TYPE_BYTE }},
+ { "SBB", { .src = Reg, .reg = RAX }, { .src = Imm, .type = TYPE_z }},
+ { "PUSH", { .src = Reg, .reg = DS }, { .src = None }},
+ { "POP", { .src = Reg, .reg = DS }, { .src = None }},
{ "AND", { .src = TYPE_E, .type = TYPE_BYTE }, { .src = ModRM_Reg, .type = TYPE_BYTE }},
{ "AND", { .src = TYPE_E, .type = TYPE_v}, { .src = ModRM_Reg, .type = TYPE_v }},
{ "AND", { .src = ModRM_Reg, .type = TYPE_BYTE }, { .src = TYPE_E, .type = TYPE_BYTE }},
{ "AND", { .src = ModRM_Reg, .type = TYPE_v }, { .src = TYPE_E, .type = TYPE_v }},
- { "AND", { .src = ModRM_Reg, .type = TYPE_v }, { .src = Imm, .type = TYPE_BYTE }}, // AL, need to understand and handle
- { "AND", { .src = ModRM_Reg, .type = TYPE_v }, { .src = TYPE_E, .type = TYPE_v }},
- { "seg", { .src = ModRM_Reg, .type = TYPE_v }, { .src = Imm, .type = TYPE_BYTE }}, // TODO
- { "DAA", { .src = ModRM_Reg, .type = TYPE_v }, { .src = TYPE_E, .type = TYPE_v }}, // TODO
+ { "AND", { .src = Reg, .reg = AL }, { .src = Imm, .type = TYPE_BYTE }},
+ { "AND", { .src = Reg, .reg = RAX }, { .src = Imm, .type = TYPE_z }},
+ { "seg", { .src = Reg, .reg = ES }, { .src = None }},
+ { "DAA", { .src = None }, { .src = None }},
{ "SUB", { .src = TYPE_E, .type = TYPE_BYTE }, { .src = ModRM_Reg, .type = TYPE_BYTE }},
{ "SUB", { .src = TYPE_E, .type = TYPE_v}, { .src = ModRM_Reg, .type = TYPE_v }},
{ "SUB", { .src = ModRM_Reg, .type = TYPE_BYTE }, { .src = TYPE_E, .type = TYPE_BYTE }},
{ "SUB", { .src = ModRM_Reg, .type = TYPE_v }, { .src = TYPE_E, .type = TYPE_v }},
- { "SUB", { .src = ModRM_Reg, .type = TYPE_v }, { .src = Imm, .type = TYPE_BYTE }}, // AL, need to understand and handle
- { "SUB", { .src = ModRM_Reg, .type = TYPE_v }, { .src = TYPE_E, .type = TYPE_v }},
- { "seg", { .src = ModRM_Reg, .type = TYPE_v }, { .src = Imm, .type = TYPE_BYTE }}, // TODO
- { "DAS", { .src = ModRM_Reg, .type = TYPE_v }, { .src = TYPE_E, .type = TYPE_v }}, // TODO
+ { "SUB", { .src = Reg, .reg = AL }, { .src = Imm, .type = TYPE_BYTE }},
+ { "SUB", { .src = Reg, .reg = RAX }, { .src = Imm, .type = TYPE_z }},
+ { "seg", { .src = Reg, .reg = CS }, { .src = None }},
+ { "DAS", { .src = None }, { .src = None }},
{ "XOR", { .src = TYPE_E, .type = TYPE_BYTE }, { .src = ModRM_Reg, .type = TYPE_BYTE }},
{ "XOR", { .src = TYPE_E, .type = TYPE_v}, { .src = ModRM_Reg, .type = TYPE_v }},
{ "XOR", { .src = ModRM_Reg, .type = TYPE_BYTE }, { .src = TYPE_E, .type = TYPE_BYTE }},
{ "XOR", { .src = ModRM_Reg, .type = TYPE_v }, { .src = TYPE_E, .type = TYPE_v }},
- { "XOR", { .src = ModRM_Reg, .type = TYPE_v }, { .src = Imm, .type = TYPE_BYTE }}, // AL, need to understand and handle
- { "XOR", { .src = ModRM_Reg, .type = TYPE_v }, { .src = TYPE_E, .type = TYPE_v }},
- { "seg", { .src = ModRM_Reg, .type = TYPE_v }, { .src = Imm, .type = TYPE_BYTE }}, // TODO
- { "AAA", { .src = ModRM_Reg, .type = TYPE_v }, { .src = TYPE_E, .type = TYPE_v }}, // TODO
+ { "XOR", { .src = Reg, .reg = AL }, { .src = Imm, .type = TYPE_BYTE }},
+ { "XOR", { .src = Reg, .reg = RAX }, { .src = Imm, .type = TYPE_z }},
+ { "seg", { .src = Reg, .reg = SS }, { .src = None }},
+ { "AAA", { .src = None }, { .src = None }},
{ "CMP", { .src = TYPE_E, .type = TYPE_BYTE }, { .src = ModRM_Reg, .type = TYPE_BYTE }},
{ "CMP", { .src = TYPE_E, .type = TYPE_v}, { .src = ModRM_Reg, .type = TYPE_v }},
{ "CMP", { .src = ModRM_Reg, .type = TYPE_BYTE }, { .src = TYPE_E, .type = TYPE_BYTE }},
{ "CMP", { .src = ModRM_Reg, .type = TYPE_v }, { .src = TYPE_E, .type = TYPE_v }},
- { "CMP", { .src = ModRM_Reg, .type = TYPE_v }, { .src = Imm, .type = TYPE_BYTE }}, // AL, need to understand and handle
- { "CMP", { .src = ModRM_Reg, .type = TYPE_v }, { .src = TYPE_E, .type = TYPE_v }},
- { "seg", { .src = ModRM_Reg, .type = TYPE_v }, { .src = Imm, .type = TYPE_BYTE }}, // TODO
- { "AAS", { .src = ModRM_Reg, .type = TYPE_v }, { .src = TYPE_E, .type = TYPE_v }}, // TODO
- { "INC", { .src = TYPE_E, .type = TYPE_BYTE }, { .src = ModRM_Reg, .type = TYPE_BYTE }}, // TODO
- { "INC", { .src = TYPE_E, .type = TYPE_v}, { .src = ModRM_Reg, .type = TYPE_v }}, // TODO
- { "INC", { .src = ModRM_Reg, .type = TYPE_BYTE }, { .src = TYPE_E, .type = TYPE_BYTE }}, // TODO
- { "INC", { .src = ModRM_Reg, .type = TYPE_v }, { .src = TYPE_E, .type = TYPE_v }}, // TODO
- { "INC", { .src = ModRM_Reg, .type = TYPE_v }, { .src = Imm, .type = TYPE_BYTE }}, // AL, need to understand and handle
- { "INC", { .src = ModRM_Reg, .type = TYPE_v }, { .src = TYPE_E, .type = TYPE_v }}, // TODO
- { "INC", { .src = ModRM_Reg, .type = TYPE_v }, { .src = Imm, .type = TYPE_BYTE }}, // TODO
- { "INC", { .src = ModRM_Reg, .type = TYPE_v }, { .src = TYPE_E, .type = TYPE_v }}, // TODO
- { "DEC", { .src = TYPE_E, .type = TYPE_BYTE }, { .src = ModRM_Reg, .type = TYPE_BYTE }}, // TODO
- { "DEC", { .src = TYPE_E, .type = TYPE_v}, { .src = ModRM_Reg, .type = TYPE_v }}, // TODO
- { "DEC", { .src = ModRM_Reg, .type = TYPE_BYTE }, { .src = TYPE_E, .type = TYPE_BYTE }}, // TODO
- { "DEC", { .src = ModRM_Reg, .type = TYPE_v }, { .src = TYPE_E, .type = TYPE_v }}, // TODO
- { "DEC", { .src = ModRM_Reg, .type = TYPE_v }, { .src = Imm, .type = TYPE_BYTE }}, // AL, need to understand and handle
- { "DEC", { .src = ModRM_Reg, .type = TYPE_v }, { .src = TYPE_E, .type = TYPE_v }}, // TODO
- { "DEC", { .src = ModRM_Reg, .type = TYPE_v }, { .src = Imm, .type = TYPE_BYTE }}, // TODO
- { "DEC", { .src = ModRM_Reg, .type = TYPE_v }, { .src = TYPE_E, .type = TYPE_v }}, // TODO
- { "PUSH", { .src = Reg, .reg = RAX }, { .src = None, .type = TYPE_NONE }},
- { "PUSH", { .src = Reg, .reg = RCX }, { .src = None, .type = TYPE_NONE }},
- { "PUSH", { .src = Reg, .reg = RDX }, { .src = None, .type = TYPE_NONE }},
- { "PUSH", { .src = Reg, .reg = RBX }, { .src = None, .type = TYPE_NONE }},
- { "PUSH", { .src = Reg, .reg = RSP }, { .src = None, .type = TYPE_NONE }},
- { "PUSH", { .src = Reg, .reg = RBP }, { .src = None, .type = TYPE_NONE }},
- { "PUSH", { .src = Reg, .reg = RSI }, { .src = None, .type = TYPE_NONE }},
- { "PUSH", { .src = Reg, .reg = RDI }, { .src = None, .type = TYPE_NONE }},
+ { "CMP", { .src = Reg, .reg = AL }, { .src = Imm, .type = TYPE_BYTE }},
+ { "CMP", { .src = Reg, .reg = RAX }, { .src = Imm, .type = TYPE_z }},
+ { "seg", { .src = Reg, .reg = DS }, { .src = None }},
+ { "AAS", { .src = None }, { .src = None }},
+ { "INC", { .src = Reg, .reg = EAX }, { .src = None }},
+ { "INC", { .src = Reg, .reg = ECX}, { .src = None }},
+ { "INC", { .src = Reg, .reg = EDX }, { .src = None }},
+ { "INC", { .src = Reg, .reg = EBX }, { .src = None }},
+ { "INC", { .src = Reg, .reg = ESP }, { .src = None }},
+ { "INC", { .src = Reg, .reg = EBP }, { .src = None }},
+ { "INC", { .src = Reg, .reg = ESI }, { .src = None }},
+ { "INC", { .src = Reg, .reg = EDI }, { .src = None }},
+ { "DEC", { .src = Reg, .reg = EAX }, { .src = None }},
+ { "DEC", { .src = Reg, .reg = ECX }, { .src = None }},
+ { "DEC", { .src = Reg, .reg = EDX }, { .src = None }},
+ { "DEC", { .src = Reg, .reg = EBX }, { .src = None }},
+ { "DEC", { .src = Reg, .reg = ESP }, { .src = None }},
+ { "DEC", { .src = Reg, .reg = EBP }, { .src = None }},
+ { "DEC", { .src = Reg, .reg = ESI }, { .src = None }},
+ { "DEC", { .src = Reg, .reg = EDI }, { .src = None }},
+ { "PUSH", { .src = Reg, .reg = RAX }, { .src = None, .type = TYPE_NONE }}, // TODO: RAX/r8
+ { "PUSH", { .src = Reg, .reg = RCX }, { .src = None, .type = TYPE_NONE }}, // TODO: RCX/r9
+ { "PUSH", { .src = Reg, .reg = RDX }, { .src = None, .type = TYPE_NONE }}, // TODO: RDX/r10k
+ { "PUSH", { .src = Reg, .reg = RBX }, { .src = None, .type = TYPE_NONE }}, // TODO: RBX/r11
+ { "PUSH", { .src = Reg, .reg = RSP }, { .src = None, .type = TYPE_NONE }}, // TODO: RSP/r12
+ { "PUSH", { .src = Reg, .reg = RBP }, { .src = None, .type = TYPE_NONE }}, // TODO: RBP/r13
+ { "PUSH", { .src = Reg, .reg = RSI }, { .src = None, .type = TYPE_NONE }}, // TODO: RSI/r14
+ { "PUSH", { .src = Reg, .reg = RDI }, { .src = None, .type = TYPE_NONE }}, // TODO: RDI/r15
{ "POP", { .src = TYPE_E, .type = TYPE_BYTE }, { .src = ModRM_Reg, .type = TYPE_BYTE }}, // TODO
{ "POP", { .src = TYPE_E, .type = TYPE_v}, { .src = ModRM_Reg, .type = TYPE_v }}, // TODO
{ "POP", { .src = ModRM_Reg, .type = TYPE_BYTE }, { .src = TYPE_E, .type = TYPE_BYTE }}, // TODO
@@ -322,14 +443,14 @@ const struct opcode primary_opcode_map[256U] = {
{ "POP", { .src = ModRM_Reg, .type = TYPE_v }, { .src = TYPE_E, .type = TYPE_v }}, // TODO
{ "POP", { .src = ModRM_Reg, .type = TYPE_v }, { .src = Imm, .type = TYPE_BYTE }}, // TODO
{ "POP", { .src = ModRM_Reg, .type = TYPE_v }, { .src = TYPE_E, .type = TYPE_v }}, // TODO
- { "PUSHA", { .src = TYPE_E, .type = TYPE_BYTE }, { .src = ModRM_Reg, .type = TYPE_BYTE }}, // TODO
- { "POPA", { .src = TYPE_E, .type = TYPE_v}, { .src = ModRM_Reg, .type = TYPE_v }}, // TODO
+ { "PUSHA/D", { .src = None }, { .src = None}},
+ { "POPA/D", { .src = None }, { .src = None }},
{ "BOUND", { .src = ModRM_Reg, .type = TYPE_BYTE }, { .src = TYPE_E, .type = TYPE_BYTE }}, // TODO
{ "ARPL", { .src = ModRM_Reg, .type = TYPE_v }, { .src = TYPE_E, .type = TYPE_v }}, // TODO
{ "seg", { .src = ModRM_Reg, .type = TYPE_v }, { .src = Imm, .type = TYPE_BYTE }}, // TODO
{ "seg", { .src = ModRM_Reg, .type = TYPE_v }, { .src = TYPE_E, .type = TYPE_v }}, // TODO
- { "INVALID", { .src = None }, { .src = None }}, // Operand size overide prefix
- { "INVALID", { .src = None }, { .src = None }}, // Address size override prefix
+ { "INVALID", { .src = None }, { .src = None }}, // Operand size overide prefix
+ { "INVALID", { .src = None }, { .src = None }}, // Address size override prefix
{ "PUSH", { .src = TYPE_E, .type = TYPE_BYTE }, { .src = ModRM_Reg, .type = TYPE_BYTE }}, // TODO
{ "IMUL", { .src = TYPE_E, .type = TYPE_v}, { .src = ModRM_Reg, .type = TYPE_v }}, // TODO
{ "PUSH", { .src = ModRM_Reg, .type = TYPE_BYTE }, { .src = TYPE_E, .type = TYPE_BYTE }}, // TODO
@@ -338,14 +459,14 @@ const struct opcode primary_opcode_map[256U] = {
{ "INSW/D", { .src = ModRM_Reg, .type = TYPE_v }, { .src = TYPE_E, .type = TYPE_v }}, // TODO
{ "OUTS/B", { .src = ModRM_Reg, .type = TYPE_v }, { .src = Imm, .type = TYPE_BYTE }}, // TODO
{ "OUTS/W/D", { .src = ModRM_Reg, .type = TYPE_v }, { .src = TYPE_E, .type = TYPE_v }}, // TODO
- { "JO", { .src = TYPE_E, .type = TYPE_BYTE }, { .src = ModRM_Reg, .type = TYPE_BYTE }}, // TODO
- { "JNO", { .src = TYPE_E, .type = TYPE_v}, { .src = ModRM_Reg, .type = TYPE_v }}, // TODO
- { "JB", { .src = ModRM_Reg, .type = TYPE_BYTE }, { .src = TYPE_E, .type = TYPE_BYTE }}, // TODO
- { "JNB", { .src = ModRM_Reg, .type = TYPE_v }, { .src = TYPE_E, .type = TYPE_v }}, // TODO
- { "JZ", { .src = ModRM_Reg, .type = TYPE_v }, { .src = Imm, .type = TYPE_BYTE }}, // TODO
- { "JNZ", { .src = ModRM_Reg, .type = TYPE_v }, { .src = TYPE_E, .type = TYPE_v }}, // TODO
- { "JBE", { .src = ModRM_Reg, .type = TYPE_v }, { .src = Imm, .type = TYPE_BYTE }}, // TODO
- { "JNBE", { .src = ModRM_Reg, .type = TYPE_v }, { .src = TYPE_E, .type = TYPE_v }}, // TODO
+ { "JO", { .src = TYPE_J, .type = TYPE_BYTE }, { .src = None }},
+ { "JNO", { .src = TYPE_J, .type = TYPE_BYTE}, { .src = None }},
+ { "JB", { .src = TYPE_J, .type = TYPE_BYTE }, { .src = None }},
+ { "JNB", { .src = TYPE_J, .type = TYPE_BYTE }, { .src = None }},
+ { "JZ", { .src = TYPE_J, .type = TYPE_BYTE }, { .src = None }},
+ { "JNZ", { .src = TYPE_J, .type = TYPE_BYTE }, { .src = None }},
+ { "JBE", { .src = TYPE_J, .type = TYPE_BYTE }, { .src = None }},
+ { "JNBE", { .src = TYPE_J, .type = TYPE_BYTE }, { .src = None }},
{ "JS", { .src = TYPE_E, .type = TYPE_BYTE }, { .src = ModRM_Reg, .type = TYPE_BYTE }}, // TODO
{ "JNS", { .src = TYPE_E, .type = TYPE_v}, { .src = ModRM_Reg, .type = TYPE_v }}, // TODO
{ "JP", { .src = ModRM_Reg, .type = TYPE_BYTE }, { .src = TYPE_E, .type = TYPE_BYTE }}, // TODO
@@ -354,22 +475,22 @@ const struct opcode primary_opcode_map[256U] = {
{ "JNL", { .src = ModRM_Reg, .type = TYPE_v }, { .src = TYPE_E, .type = TYPE_v }}, // TODO
{ "JLE", { .src = ModRM_Reg, .type = TYPE_v }, { .src = Imm, .type = TYPE_BYTE }}, // TODO
{ "JNLE", { .src = ModRM_Reg, .type = TYPE_v }, { .src = TYPE_E, .type = TYPE_v }}, // TODO
- { "INVALID", { .src = None }, { .src = None }}, // Group 1 Opcode
- { "INVALID", { .src = None }, { .src = None }}, // Group 1 Opcode
- { "INVALID", { .src = None }, { .src = None }}, // Group 1 Opcode
- { "INVALID", { .src = None }, { .src = None }}, // Group 1 Opcode
- { "TEST", { .src = ModRM_Reg, .type = TYPE_v }, { .src = Imm, .type = TYPE_BYTE }}, // TODO
- { "TEST", { .src = ModRM_Reg, .type = TYPE_v }, { .src = TYPE_E, .type = TYPE_v }}, // TODO
- { "XCHG", { .src = ModRM_Reg, .type = TYPE_v }, { .src = Imm, .type = TYPE_BYTE }}, // TODO
- { "XCHG", { .src = ModRM_Reg, .type = TYPE_v }, { .src = TYPE_E, .type = TYPE_v }}, // TODO
- { "MOV", { .src = TYPE_E, .type = TYPE_BYTE }, { .src = ModRM_Reg, .type = TYPE_BYTE }}, // TODO
- { "MOV", { .src = TYPE_E, .type = TYPE_v}, { .src = ModRM_Reg, .type = TYPE_v }}, // TODO
- { "MOV", { .src = ModRM_Reg, .type = TYPE_BYTE }, { .src = TYPE_E, .type = TYPE_BYTE }}, // TODO
- { "MOV", { .src = ModRM_Reg, .type = TYPE_v }, { .src = TYPE_E, .type = TYPE_v }}, // TODO
+ { "INVALID", { .src = None }, { .src = None }}, // Group 1 Opcode
+ { "INVALID", { .src = None }, { .src = None }}, // Group 1 Opcode
+ { "INVALID", { .src = None }, { .src = None }}, // Group 1 Opcode
+ { "INVALID", { .src = None }, { .src = None }}, // Group 1 Opcode
+ { "TEST", { .src = TYPE_E, .type = TYPE_BYTE }, { .src = ModRM_Reg, .type = TYPE_BYTE }},
+ { "TEST", { .src = TYPE_E, .type = TYPE_v }, { .src = ModRM_Reg, .type = TYPE_v }},
+ { "XCHG", { .src = TYPE_E, .type = TYPE_BYTE }, { .src = ModRM_Reg, .type = TYPE_BYTE }},
+ { "XCHG", { .src = TYPE_E, .type = TYPE_v }, { .src = ModRM_Reg, .type = TYPE_v }},
+ { "MOV", { .src = TYPE_E, .type = TYPE_BYTE }, { .src = ModRM_Reg, .type = TYPE_BYTE }},
+ { "MOV", { .src = TYPE_E, .type = TYPE_v}, { .src = ModRM_Reg, .type = TYPE_v }},
+ { "MOV", { .src = ModRM_Reg, .type = TYPE_BYTE }, { .src = TYPE_E, .type = TYPE_BYTE }},
+ { "MOV", { .src = ModRM_Reg, .type = TYPE_v }, { .src = TYPE_E, .type = TYPE_v }},
{ "MOV", { .src = ModRM_Reg, .type = TYPE_v }, { .src = Imm, .type = TYPE_BYTE }}, // TODO
- { "LEA", { .src = ModRM_Reg, .type = TYPE_v }, { .src = TYPE_E, .type = TYPE_v }}, // TODO
- { "MOV", { .src = ModRM_Reg, .type = TYPE_v }, { .src = Imm, .type = TYPE_BYTE }}, // TODO
- { "INVALID", { .src = None }, { .src = None }}, // Group 1 Opcode
+ { "LEA", { .src = ModRM_Reg, .type = TYPE_v }, { .src = ModRM_MEM }},
+ { "MOV", { .src = ModRM_Seg_Reg, .type = TYPE_WORD }, { .src = TYPE_E, .type = TYPE_WORD }},
+ { "INVALID", { .src = None }, { .src = None }}, // Group 1 Opcode
{ "NOP", { .src = ModRM_Reg, .type = TYPE_v }, { .src = TYPE_E, .type = TYPE_v }}, // TODO
{ "XCHG", { .src = ModRM_Reg, .type = TYPE_v }, { .src = TYPE_E, .type = TYPE_v }}, // TODO
{ "XCHG", { .src = ModRM_Reg, .type = TYPE_v }, { .src = TYPE_E, .type = TYPE_v }}, // TODO
@@ -418,30 +539,30 @@ const struct opcode primary_opcode_map[256U] = {
{ "MOV", { .src = ModRM_Reg, .type = TYPE_v }, { .src = TYPE_E, .type = TYPE_v }}, // TODO
{ "MOV", { .src = ModRM_Reg, .type = TYPE_v }, { .src = TYPE_E, .type = TYPE_v }}, // TODO
{ "MOV", { .src = ModRM_Reg, .type = TYPE_v }, { .src = TYPE_E, .type = TYPE_v }}, // TODO
- { "INVALID", { .src = None }, { .src = None }}, // Group 2 opcode
- { "INVALID", { .src = None }, { .src = None }}, // Group 2 opcode
+ { "INVALID", { .src = None }, { .src = None }}, // Group 2 opcode
+ { "INVALID", { .src = None }, { .src = None }}, // Group 2 opcode
{ "RET", { .src = ModRM_Reg, .type = TYPE_BYTE }, { .src = TYPE_E, .type = TYPE_BYTE }}, // TODO
{ "RET", { .src = ModRM_Reg, .type = TYPE_v }, { .src = TYPE_E, .type = TYPE_v }}, // TODO
{ "LES", { .src = ModRM_Reg, .type = TYPE_v }, { .src = Imm, .type = TYPE_BYTE }}, // TODO
{ "LDS", { .src = ModRM_Reg, .type = TYPE_v }, { .src = TYPE_E, .type = TYPE_v }}, // TODO
- { "INVALID", { .src = None }, { .src = None }}, // Group 11 opcode
- { "INVALID", { .src = None }, { .src = None }}, // Group 11 opcode
+ { "INVALID", { .src = None }, { .src = None }}, // Group 11 opcode
+ { "INVALID", { .src = None }, { .src = None }}, // Group 11 opcode
{ "ENTER", { .src = ModRM_Reg, .type = TYPE_WORD }, { .src = Imm, .type = TYPE_BYTE }},
{ "LEAVE", { .src = None }, { .src = None }},
{ "RET far", { .src = Imm, .type = TYPE_WORD }, { .src = None }},
{ "RET far", { .src = None }, { .src = None }},
{ "INT 3", { .src = None }, { .src = None }},
{ "INT", { .src = Imm, .type = TYPE_BYTE }, { .src = None }},
- { "INTO", { .src = None }, { .src = None }}, // Invalid in 64bit mode
+ { "INTO", { .src = None }, { .src = None }}, // Invalid in 64bit mode
{ "IRET/D/Q", { .src = ModRM_Reg, .type = TYPE_v }, { .src = TYPE_E, .type = TYPE_v }}, // TODO
- { "INVALID", { .src = None }, { .src = None }}, // Group 2 Opcode
- { "INVALID", { .src = None }, { .src = None }}, // Group 2 Opcode
- { "INVALID", { .src = None }, { .src = None }}, // Group 2 Opcode
- { "INVALID", { .src = None }, { .src = None }}, // Group 2 Opcode
- { "AAM", { .src = TYPE_E, .type = TYPE_BYTE }, { .src = ModRM_Reg, .type = TYPE_BYTE }}, // TODO
- { "AAD", { .src = TYPE_E, .type = TYPE_v}, { .src = ModRM_Reg, .type = TYPE_v }}, // TODO
- { "INVALID", { .src = None }, { .src = None }}, // invalid
- { "XLAT", { .src = TYPE_E, .type = TYPE_v}, { .src = ModRM_Reg, .type = TYPE_v }}, // TODO
+ { "INVALID", { .src = None }, { .src = None }}, // Group 2 Opcode
+ { "INVALID", { .src = None }, { .src = None }}, // Group 2 Opcode
+ { "INVALID", { .src = None }, { .src = None }}, // Group 2 Opcode
+ { "INVALID", { .src = None }, { .src = None }}, // Group 2 Opcode
+ { "AAM", { .src = Imm, .type = TYPE_BYTE }, { .src = None }},
+ { "AAD", { .src = Imm, .type = TYPE_BYTE}, { .src = None }},
+ { "INVALID", { .src = None }, { .src = None }}, // invalid
+ { "XLAT", { .src = None }, { .src = None }}, // TODO
{ "INVALID", { .src = None }, { .src = None }}, // TODO x87 instructions
{ "INVALID", { .src = None }, { .src = None }}, // TODO x87 instructions
{ "INVALID", { .src = None }, { .src = None }}, // TODO x87 instructions
@@ -452,36 +573,36 @@ const struct opcode primary_opcode_map[256U] = {
{ "INVALID", { .src = None }, { .src = None }}, // TODO x87 instructions
{ "LOOPNE/NZ", { .src = ModRM_Reg, .type = TYPE_v }, { .src = TYPE_E, .type = TYPE_v }}, // TODO
{ "LOOPE/Z", { .src = ModRM_Reg, .type = TYPE_v }, { .src = TYPE_E, .type = TYPE_v }}, // TODO
- { "LOOP", { .src = ModRM_Reg, .type = TYPE_v }, { .src = TYPE_E, .type = TYPE_v }}, // TODO
+ { "LOOP", { .src = TYPE_J, .type = TYPE_BYTE }, { .src = None }},
{ "JrCXZ", { .src = ModRM_Reg, .type = TYPE_v }, { .src = TYPE_E, .type = TYPE_v }}, // TODO
- { "IN", { .src = ModRM_Reg, .type = TYPE_v }, { .src = TYPE_E, .type = TYPE_v }}, // TODO
- { "IN", { .src = ModRM_Reg, .type = TYPE_v }, { .src = TYPE_E, .type = TYPE_v }}, // TODO
- { "OUT", { .src = ModRM_Reg, .type = TYPE_v }, { .src = TYPE_E, .type = TYPE_v }}, // TODO
- { "OUT", { .src = ModRM_Reg, .type = TYPE_v }, { .src = TYPE_E, .type = TYPE_v }}, // TODO
- { "CALL", { .src = ModRM_Reg, .type = TYPE_v }, { .src = TYPE_E, .type = TYPE_v }}, // TODO
- { "JMP", { .src = TYPE_E, .type = TYPE_v}, { .src = ModRM_Reg, .type = TYPE_v }}, // TODO
- { "JMP", { .src = TYPE_E, .type = TYPE_BYTE }, { .src = ModRM_Reg, .type = TYPE_BYTE }}, // TODO
- { "JMP", { .src = TYPE_E, .type = TYPE_v}, { .src = ModRM_Reg, .type = TYPE_v }}, // TODO
- { "IN", { .src = ModRM_Reg, .type = TYPE_v }, { .src = TYPE_E, .type = TYPE_v }}, // TODO
- { "IN", { .src = ModRM_Reg, .type = TYPE_v }, { .src = TYPE_E, .type = TYPE_v }}, // TODO
- { "OUT", { .src = ModRM_Reg, .type = TYPE_v }, { .src = TYPE_E, .type = TYPE_v }}, // TODO
- { "OUT", { .src = ModRM_Reg, .type = TYPE_v }, { .src = TYPE_E, .type = TYPE_v }}, // TODO
+ { "IN", { .src = Reg, .reg = AL }, { .src = Imm, .type = TYPE_BYTE }},
+ { "IN", { .src = Reg, .reg = EAX }, { .src = Imm, .type = TYPE_BYTE }},
+ { "OUT", { .src = Imm, .type = TYPE_BYTE }, { .src = Reg, .reg = AL }},
+ { "OUT", { .src = Imm, .type = TYPE_BYTE }, { .src = Reg, .reg = EAX }},
+ { "CALL", { .src = TYPE_J, .type = TYPE_z }, { .src = None }},
+ { "JMP", { .src = TYPE_J, .type = TYPE_z}, { .src = None }},
+ { "JMP", { .src = Inst_FAR, .type = TYPE_p }, { .src = None }},
+ { "JMP", { .src = TYPE_J, .type = TYPE_BYTE }, { .src = None }},
+ { "IN", { .src = Reg, .reg = AL }, { .src = Reg, .reg = DX }},
+ { "IN", { .src = Reg, .reg = EAX }, { .src = Reg, .reg = DX }},
+ { "OUT", { .src = Reg, .reg = DX }, { .src = Reg, .reg = AL }},
+ { "OUT", { .src = Reg, .reg = DX }, { .src = Reg, .reg = EAX }},
{ "LOCK", { .src = ModRM_Reg, .type = TYPE_v }, { .src = TYPE_E, .type = TYPE_v }}, // TODO
- { "INT1", { .src = TYPE_E, .type = TYPE_v}, { .src = ModRM_Reg, .type = TYPE_v }}, // TODO
+ { "INT1", { .src = None }, { .src = None }},
{ "REPNE", { .src = TYPE_E, .type = TYPE_BYTE }, { .src = ModRM_Reg, .type = TYPE_BYTE }}, // TODO
{ "REP/E", { .src = TYPE_E, .type = TYPE_v}, { .src = ModRM_Reg, .type = TYPE_v }}, // TODO
- { "HLT", { .src = ModRM_Reg, .type = TYPE_v }, { .src = TYPE_E, .type = TYPE_v }}, // TODO
- { "CMC", { .src = ModRM_Reg, .type = TYPE_v }, { .src = TYPE_E, .type = TYPE_v }}, // TODO
- { "INVALID", { .src = None }, { .src = None }}, // Group 3 opcode
- { "INVALID", { .src = None }, { .src = None }}, // Group 3 opcode
- { "CLC", { .src = ModRM_Reg, .type = TYPE_v }, { .src = TYPE_E, .type = TYPE_v }}, // TODO
- { "STC", { .src = TYPE_E, .type = TYPE_v}, { .src = ModRM_Reg, .type = TYPE_v }}, // TODO
- { "CLI", { .src = TYPE_E, .type = TYPE_BYTE }, { .src = ModRM_Reg, .type = TYPE_BYTE }}, // TODO
- { "STI", { .src = TYPE_E, .type = TYPE_v}, { .src = ModRM_Reg, .type = TYPE_v }}, // TODO
- { "CLD", { .src = ModRM_Reg, .type = TYPE_v }, { .src = TYPE_E, .type = TYPE_v }}, // TODO
- { "STD", { .src = ModRM_Reg, .type = TYPE_v }, { .src = TYPE_E, .type = TYPE_v }}, // TODO
- { "INVALID", { .src = None }, { .src = None }}, // Group 4 opcode
- { "INVALID", { .src = None }, { .src = None }}, // Group 5 opcode
+ { "HLT", { .src = None }, { .src = None }},
+ { "CMC", { .src = None }, { .src = None }},
+ { "INVALID", { .src = None }, { .src = None }}, // Group 3 opcode
+ { "INVALID", { .src = None }, { .src = None }}, // Group 3 opcode
+ { "CLC", { .src = None }, { .src = None }},
+ { "STC", { .src = None }, { .src = None }},
+ { "CLI", { .src = None }, { .src = None }},
+ { "STI", { .src = None }, { .src = None }},
+ { "CLD", { .src = None }, { .src = None }},
+ { "STD", { .src = None }, { .src = None }},
+ { "INVALID", { .src = None }, { .src = None }}, // Group 4 opcode
+ { "INVALID", { .src = None }, { .src = None }}, // Group 5 opcode
};
// TODO: Think about a smart way to retrieve groups opcodes
@@ -525,7 +646,7 @@ const struct opcode group_1[32U] = {
};
const struct opcode group_1a[8U] = {
- { "POP", { .src = TYPE_E, .type = TYPE_v }, { .src = TYPE_E, .type = TYPE_v }}, // TODO
+ { "POP", { .src = TYPE_E, .type = TYPE_v }, { .src = None }},
{ "XOP", { .src = TYPE_E, .type = TYPE_v }, { .src = TYPE_E, .type = TYPE_v }}, // TODO
{ "XOP", { .src = TYPE_E, .type = TYPE_v }, { .src = TYPE_E, .type = TYPE_v }}, // TODO
{ "XOP", { .src = TYPE_E, .type = TYPE_v }, { .src = TYPE_E, .type = TYPE_v }}, // TODO
@@ -656,6 +777,30 @@ u8 is_REX_prefix(u8 byte) {
return FALSE;
}
+// TODO: Rework this messy function and params
+const char* get_ModRM_reg(u8 val, u8 operand_size, u8 use_3DNow, u8 use_SSE) {
+ assert(val < 8U);
+ u8 reg_index = 0U;
+ if (operand_size == 16U) {
+ reg_index = 0U;
+ } else if (operand_size == 32U) {
+ assert(FALSE);
+ } else if (operand_size == 64U) {
+ reg_index = 1U;
+ }
+
+ if (use_3DNow) {
+ reg_index = 2U;
+ } else if (use_SSE) {
+ reg_index = 3U;
+ }
+
+ assert(reg_index < 5U);
+ const char* reg = ModRM_registers[val][reg_index];
+ assert(reg);
+ return reg;
+}
+
u8 has_ModRM_byte(const enum OPERAND_TYPE op_type) {
switch (op_type) {
case None:
@@ -668,10 +813,16 @@ u8 has_ModRM_byte(const enum OPERAND_TYPE op_type) {
return TRUE;
case Imm:
return FALSE;
+ case TYPE_J:
+ return FALSE;
case ModRM_MEM:
return TRUE;
case Vector_REG:
return FALSE;
+ case ModRM_Seg_Reg:
+ return TRUE;
+ case TYPE_R:
+ return TRUE;
case DS_rSI:
return FALSE;
case ES_rSI:
@@ -712,26 +863,69 @@ const struct opcode* primary_map_group(u8 opcode, u8 ModRM) {
u64 get_immediate(u8** bytes, enum DATA_TYPE type, u8 operand_effective_size) {
u64 imm = 0U;
if (type == TYPE_BYTE) {
- imm = (u8)**bytes;
+ imm = **(u8**)bytes;
+ *bytes += 1U;
+ } else if (type == TYPE_WORD) {
+ imm = **(u16**)bytes;
+ *bytes += 2U;
+ } else if (type == TYPE_DWORD) {
+ imm = **(u32**)bytes;
+ *bytes += 4U;
+ } else if (type == TYPE_QWORD) {
+ imm = **(u64**)bytes;
+ *bytes += 8U;
+ } else if (type == TYPE_v) {
+ if (operand_effective_size == 16U) {
+ imm = **(u16**)bytes;
+ *bytes += 2U;
+ } else if (operand_effective_size == 32U) {
+ imm = **(u32**)bytes;
+ *bytes += 4U;
+ } else if (operand_effective_size == 64U) {
+ imm = **(u64**)bytes;
+ *bytes += 8U;
+ } else {
+ print("ERROR: Unhandled operand type\n");
+ }
+
+ *bytes += operand_effective_size / 8U;
+ } else if (type == TYPE_z) {
+ if (operand_effective_size == 16U) {
+ imm = **(u16**)bytes;
+ *bytes += 2U;
+ } else {
+ imm = **(u32**)bytes;
+ *bytes += 4U;
+ }
+ } else {
+ print("ERROR: Unhandled operand type\n");
+ }
+ return imm;
+}
+
+i64 get_rel_offset(u8** bytes, enum DATA_TYPE type, u8 operand_effective_size) {
+ i64 imm = 0U;
+ if (type == TYPE_BYTE) {
+ imm = **(i8**)bytes;
*bytes += 1U;
} else if (type == TYPE_WORD) {
- imm = (u16)**bytes;
+ imm = **(i16**)bytes;
*bytes += 2U;
} else if (type == TYPE_DWORD) {
- imm = (u32)**bytes;
+ imm = **(i32**)bytes;
*bytes += 4U;
} else if (type == TYPE_QWORD) {
- imm = (u64)**bytes;
+ imm = **(i64**)bytes;
*bytes += 8U;
} else if (type == TYPE_v) {
if (operand_effective_size == 16U) {
- imm = (u16)**bytes;
+ imm = **(i16**)bytes;
*bytes += 2U;
} else if (operand_effective_size == 32U) {
- imm = (u32)**bytes;
+ imm = **(i32**)bytes;
*bytes += 4U;
} else if (operand_effective_size == 64U) {
- imm = (u64)**bytes;
+ imm = **(i64**)bytes;
*bytes += 8U;
} else {
print("ERROR: Unhandled operand type\n");
@@ -740,10 +934,10 @@ u64 get_immediate(u8** bytes, enum DATA_TYPE type, u8 operand_effective_size) {
*bytes += operand_effective_size / 8U;
} else if (type == TYPE_z) {
if (operand_effective_size == 16U) {
- imm = (u16)**bytes;
+ imm = **(i16**)bytes;
*bytes += 2U;
} else {
- imm = (u32)**bytes;
+ imm = **(i32**)bytes;
*bytes += 4U;
}
} else {
@@ -795,14 +989,14 @@ void unassemble(u8* start, u64 size) {
u8* inst_start = current_byte;
u8 legacy_prefixes_count = 0U;
u8 effective_operand_size = 32U; // 32 by default in 64bit mode
- i32 effective_address = -1;
- (void)effective_address; // Not used yet
- u8 operand_size_override_REX = FALSE;
- (void)operand_size_override_REX; // Not used yet
+ u8 effective_address_size = 64U; // 64 by default in 64bit mode
+ UNUSED_VAR(effective_address_size);
u8 REX = 0U;
while (is_legacy_prefix(*current_byte) && legacy_prefixes_count < MAX_LEGACY_PREFIXES) {
if (*current_byte == 0x66) { // Override effective operand size
effective_operand_size = 16U;
+ } else if (*current_byte == 0x67) { // Override effect address size
+ effective_address_size = 32U;
}
legacy_prefixes_count++;
current_byte++;
@@ -813,7 +1007,6 @@ void unassemble(u8* start, u64 size) {
if (REXW(REX)) {
effective_operand_size = 64U;
- operand_size_override_REX = TRUE;
}
current_byte++;
@@ -823,11 +1016,15 @@ void unassemble(u8* start, u64 size) {
u8 has_ModRM = FALSE;
u8 ModRM = 0U;
+ u8 use_3DNow_reg = FALSE;
+ u8 use_SSE_reg = FALSE;
const struct opcode* op = NULL;
if (current_byte[0U] == 0x0F && current_byte[1U] == 0x0F) { // 3DNow!
assert(FALSE);
+ use_3DNow_reg = TRUE;
current_byte += 2U;
} else if (current_byte[0U] == 0x0F && (current_byte[1U] == 0x38 || current_byte[1U] == 0x3A)) { // SSE
+ use_SSE_reg = TRUE;
assert(FALSE);
current_byte += 2U;
} else if (current_byte[0U] == 0x0F) { // Secondary op code map needed
@@ -850,32 +1047,40 @@ void unassemble(u8* start, u64 size) {
}
}
+ i64 rel_offset = 0;
+ if (op->src_operand.src == TYPE_J) {
+ rel_offset = get_rel_offset(&current_byte, op->src_operand.type, effective_operand_size);
+ }
+
+ if (op->dst_operand.src == TYPE_J) {
+ rel_offset = get_rel_offset(&current_byte, op->dst_operand.type, effective_operand_size);
+ }
u8 disp_bytes_count = 0U;
u8 has_src_SIB = FALSE;
u8 has_dst_SIB = FALSE;
- // NOTE: could we test has_ModRM instead ?
- if (op->src_operand.src == TYPE_E || op->src_operand.src == ModRM_Reg || op->dst_operand.src == TYPE_E || op->dst_operand.src == ModRM_Reg) {
+ if (has_ModRM) {
u8 Mod = MODRM_MOD(ModRM);
u8 RM = MODRM_RM(ModRM);
// Table 1-14
- // Displacement detection
- if (Mod == 0b00 && RM == 0b101) {
+ // Displacement detection
+ if (Mod == 0b00 && RM == 0b101) { // Displacement in 32 mode, RIP relative addressing in 64 mode
disp_bytes_count = mod_to_disp_size[Mod];
- } else if (Mod == 0b01 || Mod == 0b10) {
+ // rel_offset = get_rel_offset(&current_byte, op->dst_operand.type, effective_operand_size);
+ } else if (Mod == 0b01 || Mod == 0b10) { // RBP + offset
disp_bytes_count = mod_to_disp_size[Mod];
}
// 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)) {
+ if (Mod != 0b11 && RM == 0b100) { // Indexed register indirect addressing mode
+ if (op->src_operand.src == TYPE_E) {
has_src_SIB = TRUE;
}
- if (op->dst_operand.src & (TYPE_E | ModRM_Reg)) {
+ if (op->dst_operand.src == TYPE_E) {
has_dst_SIB = TRUE;
}
- // NOTE: We probably can't have both operand needing an SIB byte
+ // We shouldn't have both operand needing an SIB byte
assert(!(has_src_SIB == has_dst_SIB == TRUE));
}
}
@@ -891,23 +1096,23 @@ void unassemble(u8* start, u64 size) {
}
// Displacement bits
- u32 disp = 0U;
+ i32 disp = 0U;
if (disp_bytes_count) {
if (disp_bytes_count == 1U) {
- disp = *current_byte;
+ disp = *(i8*)current_byte;
} else if (disp_bytes_count == 4U) {
- disp = *((u32*)current_byte);
+ disp = *((i32*)current_byte);
}
current_byte += disp_bytes_count;
}
u64 src_imm = 0U;
- u64 dst_imm = 0U;
if (op->src_operand.src == Imm) {
// Read immediate
src_imm = get_immediate(&current_byte, op->src_operand.type, effective_operand_size);
}
+ u64 dst_imm = 0U;
if (op->dst_operand.src == Imm) {
// Read immediate
dst_imm = get_immediate(&current_byte, op->dst_operand.type, effective_operand_size);
@@ -926,19 +1131,36 @@ void unassemble(u8* start, u64 size) {
// 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]);
+ switch(op->src_operand.src) {
+ case None:
+ break;
+ case TYPE_E:
+ case ModRM_MEM: {
+ u8 Mod = MODRM_MOD(ModRM);
+ u8 RM = MODRM_RM(ModRM);
+ if (Mod == 0b11) { // Register direct addressing mode
+ print(" %s", get_ModRM_reg(RM, effective_operand_size, use_3DNow_reg, use_SSE_reg));
+ } else if (RM == 0b101) {
+ print(" RIP + %d", disp);
+ } else if(RM != 0b100) { // Register indirect addressing mode
+ print(" %s", get_ModRM_reg(RM, effective_operand_size, use_3DNow_reg, use_SSE_reg));
+ }
+ break;
}
- } else if (op->src_operand.src == Reg) {
- print(" %s", registers[op->src_operand.reg]);
+ case ModRM_Reg:
+ print(" %s", get_ModRM_reg(MODRM_REG(ModRM), effective_operand_size, use_3DNow_reg, use_SSE_reg));
+ break;
+ case Imm:
+ print(" 0x%x", src_imm);
+ break;
+ case TYPE_J:
+ print(" RIP + %d", rel_offset);
+ break;
+ case Reg:
+ print(" %s", registers[op->src_operand.reg]);
+ break;
+ default:
+ assert(FALSE);
}
if (has_src_SIB) {
@@ -946,17 +1168,62 @@ void unassemble(u8* start, u64 size) {
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;
+
+ u8 index = SIB_INDEX(SIB);
+ if (index != 0b100) {
+ print(" scale(0x%x) * [index(%s)]", scale_factors[SIB_SCALE(SIB)], SIB_index_registers[index]);
+ }
+
+ u8 base = SIB_BASE(SIB);
+ if (base != 0b101 || MODRM_MOD(ModRM) != 0U) {
+ if (index != 0b100) {
+ print(" +");
+ }
+ print(" [base(%s)]", SIB_base_registers[base]);
+ }
+
+ if (disp_bytes_count) {
+ print(" + offset(0x%x)", disp);
+ }
}
}
+ if (op->dst_operand.src != None) {
+ print(",");
+ }
+
// Dst operand
{
- if (op->dst_operand.src == Imm) {
- print(" %x", dst_imm);
- } else if (op->dst_operand.src == Reg) {
- print(", %s", registers[op->dst_operand.reg]);
+ switch(op->dst_operand.src) {
+ case None:
+ break;
+ case TYPE_E:
+ case ModRM_MEM: {
+ u8 Mod = MODRM_MOD(ModRM);
+ u8 RM = MODRM_RM(ModRM);
+ if (Mod == 0b11) { // Register direct addressing mode
+ print(" %s", get_ModRM_reg(RM, effective_operand_size, use_3DNow_reg, use_SSE_reg));
+ } else if (RM == 0b101) {
+ print(" RIP + %d", disp);
+ } else if(RM != 0b100) { // Register indirect addressing mode
+ print(" %s", get_ModRM_reg(RM, effective_operand_size, use_3DNow_reg, use_SSE_reg));
+ }
+ break;
+ }
+ case ModRM_Reg:
+ print(" %s", get_ModRM_reg(MODRM_REG(ModRM), effective_operand_size, use_3DNow_reg, use_SSE_reg));
+ break;
+ case Imm:
+ print(" 0x%x", dst_imm);
+ break;
+ case TYPE_J:
+ print("RIP + %d", rel_offset);
+ break;
+ case Reg:
+ print(" %s", registers[op->src_operand.reg]);
+ break;
+ default:
+ assert(FALSE);
}
if (has_dst_SIB) {
@@ -967,25 +1234,26 @@ void unassemble(u8* start, u64 size) {
u8 index = SIB_INDEX(SIB);
if (index != 0b100) {
- print(" [%d * %s", scale_factors[SIB_SCALE(SIB)], SIB_index_registers[index]);
+ print(" scale(0x%x) * [index(%s)]", scale_factors[SIB_SCALE(SIB)], SIB_index_registers[index]);
}
u8 base = SIB_BASE(SIB);
- if (base != 0b101 && MODRM_MOD(ModRM) != 0U) {
- print(" + %s", SIB_base_registers[base]);
+ if (base != 0b101 || MODRM_MOD(ModRM) != 0U) {
+ if (index != 0b100) {
+ print(" +");
+ }
+ print(" [base(%s)]", SIB_base_registers[base]);
}
if (disp_bytes_count) {
- print("+ %d]", disp);
- } else {
- print("]");
+ print(" + offset(0x%x)", disp);
}
}
}
print("\n");
-
- // u8 low_nibble = current_byte & 0xf;
- // u8 high_nibble = (current_byte >> 4U) & 0xf;
}
+
+ // u8 low_nibble = current_byte & 0xf;
+ // u8 high_nibble = (current_byte >> 4U) & 0xf;
}