diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/disasm.c | 656 |
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(¤t_byte, op->src_operand.type, effective_operand_size); + } + + if (op->dst_operand.src == TYPE_J) { + rel_offset = get_rel_offset(¤t_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(¤t_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(¤t_byte, op->src_operand.type, effective_operand_size); } + u64 dst_imm = 0U; if (op->dst_operand.src == Imm) { // Read immediate dst_imm = get_immediate(¤t_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; } |
