diff --git a/decode.c b/decode.c index 7383142..c84e9f6 100644 --- a/decode.c +++ b/decode.c @@ -508,6 +508,8 @@ prefix_end: imm_size = 1; else if (UNLIKELY(instr->type == FDI_RET || instr->type == FDI_RETF)) imm_size = 2; + else if (UNLIKELY(desc->type == FDI_JMPF || desc->type == FDI_CALLF)) + imm_size = op_size + 2; else if (UNLIKELY(instr->type == FDI_ENTER)) imm_size = 3; else if (instr->type == FDI_MOVABS) @@ -526,6 +528,8 @@ prefix_end: instr->imm = LOAD_LE_3(&buffer[off]); else if (imm_size == 4) instr->imm = (int32_t) LOAD_LE_4(&buffer[off]); + else if (imm_size == 6) + instr->imm = LOAD_LE_4(&buffer[off]) | LOAD_LE_2(&buffer[off+4]) << 32; else if (imm_size == 8) instr->imm = (int64_t) LOAD_LE_8(&buffer[off]); off += imm_size; diff --git a/format.c b/format.c index a8e5ef0..1d197a6 100644 --- a/format.c +++ b/format.c @@ -178,7 +178,7 @@ fd_format_abs(const FdInstr* instr, uint64_t addr, char* buffer, size_t len) case 8: mnemonic = "jrcxz"; break; } break; - case FDI_ENTER: + case FDI_ENTER: { buf = fd_strplcpy(buf, mnemonic, end-buf); if (FD_OPSIZE(instr) == 2) buf = fd_strplcpy(buf, "w", end-buf); @@ -194,6 +194,28 @@ fd_format_abs(const FdInstr* instr, uint64_t addr, char* buffer, size_t len) *--fmt = ','; buf = fd_strplcpy(buf, fmt, end-buf); return; + } + case FDI_JMPF: + case FDI_CALLF: + if (FD_OP_TYPE(instr, 0) == FD_OT_IMM) { + buf = fd_strplcpy(buf, mnemonic, end-buf); + uint32_t tgt = FD_OP_IMM(instr, 0) & 0xffffffff; + if (FD_OP_SIZE(instr, 0) == 2) + tgt &= 0xffff; + unsigned seg = FD_OP_IMM(instr, 0) >> 8*FD_OP_SIZE(instr, 0); + char* fmt = fd_format_hex(seg & 0xffff, tmp + 3); + *--fmt = 'x'; + *--fmt = '0'; + *--fmt = ' '; + buf = fd_strplcpy(buf, fmt, end-buf); + fmt = fd_format_hex(tgt, tmp + 3); + *--fmt = 'x'; + *--fmt = '0'; + *--fmt = ':'; + buf = fd_strplcpy(buf, fmt, end-buf); + return; + } + break; case FDI_PUSH: if (FD_OP_SIZE(instr, 0) == 2 && FD_OP_TYPE(instr, 0) == FD_OT_IMM) sizesuffix[0] = 'w'; @@ -275,7 +297,7 @@ fd_format_abs(const FdInstr* instr, uint64_t addr, char* buffer, size_t len) case FDI_LFS: case FDI_LGS: case FDI_LSS: - size = 6; + size += 2; break; case FDI_FLD: case FDI_FSTP: diff --git a/instrs.txt b/instrs.txt index 95d1596..4c077b3 100644 --- a/instrs.txt +++ b/instrs.txt @@ -157,7 +157,8 @@ 90+ OA GP GP - - XCHG_NOP 98 NP - - - - C_EX INSTR_WIDTH 99 NP - - - - C_SEP INSTR_WIDTH -#9a CALLF TODO +# Far jmp/call immediate size adjusted in code +9a I IMM - - - CALLF ONLY32 9b NP - - - - FWAIT 9c NP - - - - PUSHF DEF64 INSTR_WIDTH 9d NP - - - - POPF DEF64 INSTR_WIDTH @@ -198,8 +199,8 @@ c1/7 MI GP IMM8 - - SAR # RET immediate size handled in code c2 I IMM16 - - - RET FORCE64 INSTR_WIDTH c3 NP - - - - RET FORCE64 INSTR_WIDTH -c4/m RM GP MEMZ - - LES ONLY32 -c5/m RM GP MEMZ - - LDS ONLY32 +c4/m RM GP MEM - - LES ONLY32 +c5/m RM GP MEM - - LDS ONLY32 c6/0 MI GP IMM - - MOV SIZE_8 c6f8 I IMM8 - - - XABORT c7/0 MI GP IMM - - MOV @@ -258,7 +259,8 @@ e6 IA GP IMM8 - - OUT SIZE_8 e7 IA GP IMM8 - - OUT e8 D IMM - - - CALL FORCE64 e9 D IMM - - - JMP FORCE64 -#ea JMPf TODO, ONLY32 +# Far jmp/call immediate size adjusted in code +ea I IMM - - - JMPF ONLY32 eb D IMM - - - JMP FORCE64 IMM_8 ec NP - - - - IN SIZE_8 INSTR_WIDTH ed NP - - - - IN INSTR_WIDTH @@ -295,9 +297,9 @@ fe/1 M GP - - - DEC SIZE_8 LOCK ff/0 M GP - - - INC LOCK ff/1 M GP - - - DEC LOCK ff/2 M GP - - - CALL FORCE64 -ff/3m M MEMZ - - - CALLF +ff/3m M MEM - - - CALLF ff/4 M GP - - - JMP FORCE64 -ff/5m M MEMZ - - - JMPF +ff/5m M MEM - - - JMPF ff/6 M GP - - - PUSH DEF64 0f00/0 M GP16 - - - SLDT 0f00/1 M GP16 - - - STR diff --git a/tests/test_decode.c b/tests/test_decode.c index acc63ed..b9f9cc0 100644 --- a/tests/test_decode.c +++ b/tests/test_decode.c @@ -311,7 +311,7 @@ main(int argc, char** argv) TEST32("\xc5\x00", "lds eax, fword ptr [eax]"); TEST32("\x0f\xb2\x00", "lss eax, fword ptr [eax]"); TEST64("\x0f\xb2\x00", "lss eax, fword ptr [rax]"); - TEST64("\x48\x0f\xb2\x00", "lss rax, fword ptr [rax]"); + TEST64("\x48\x0f\xb2\x00", "lss rax, tbyte ptr [rax]"); TEST("\xc5\xf2\x2a\xc0", "vcvtsi2ss xmm0, xmm1, eax"); TEST("\xf3\xc5\xf2\x2a\xc0", "UD"); // VEX+REP TEST("\xf2\xc5\xf2\x2a\xc0", "UD"); // VEX+REPNZ @@ -429,6 +429,19 @@ main(int argc, char** argv) TEST64("\xe3\xfe", "jrcxz 0x0"); TEST32("\x67\xe3\xfd", "jcxz 0x0"); TEST64("\x67\xe3\xfd", "jecxz 0x0"); + TEST32("\x66\x9a\x23\x01\x23\x00", "call far 0x23:0x123"); + TEST32("\x9a\x67\x45\x23\x01\x23\x00", "call far 0x23:0x1234567"); + TEST32("\x9a\xff\xff\xff\xff\xff\xff", "call far 0xffff:0xffffffff"); + TEST32("\x66\xff\x1f", "call far dword ptr [edi]"); + TEST64("\x66\xff\x1f", "call far dword ptr [rdi]"); + TEST32("\xff\x1f", "call far fword ptr [edi]"); + TEST64("\xff\x1f", "call far fword ptr [rdi]"); + TEST64("\x48\xff\x1f", "call far tbyte ptr [rdi]"); + TEST32("\x66\x0f\xb4\x07", "lfs ax, dword ptr [edi]"); + TEST64("\x66\x0f\xb4\x07", "lfs ax, dword ptr [rdi]"); + TEST32("\x0f\xb4\x07", "lfs eax, fword ptr [edi]"); + TEST64("\x0f\xb4\x07", "lfs eax, fword ptr [rdi]"); + TEST64("\x48\x0f\xb4\x07", "lfs rax, tbyte ptr [rdi]"); TEST("\xa5", "movsd"); TEST("\x64\xa5", "fs movsd"); TEST32("\x2e\xa5", "cs movsd");