mirror of
https://github.com/DxWnd/DxWnd.reloaded
synced 2024-12-30 09:25:35 +01:00
672 lines
40 KiB
C
672 lines
40 KiB
C
////////////////////////////////////////////////////////////////////////////////
|
|
// //
|
|
// OllyDbg Disassembling Engine v2.01 //
|
|
// //
|
|
// Copyright (c) 2007-2013 Oleh Yuschuk, ollydbg@t-online.de //
|
|
// //
|
|
// This code is part of the OllyDbg Disassembler v2.01 //
|
|
// //
|
|
// Disassembling engine is free software; you can redistribute it and/or //
|
|
// modify it under the terms of the GNU General Public License as published //
|
|
// by the Free Software Foundation; either version 3 of the License, or (at //
|
|
// your option) any later version. //
|
|
// //
|
|
// This code is distributed in the hope that it will be useful, but WITHOUT //
|
|
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or //
|
|
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for //
|
|
// more details. //
|
|
// //
|
|
// You should have received a copy of the GNU General Public License along //
|
|
// with this program. If not, see <http://www.gnu.org/licenses/>. //
|
|
// //
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
// //
|
|
// This is a fast disassembler that can be used to determine the length of //
|
|
// the binary 80x86 32-bit command and its attributes, to convert it to the //
|
|
// human-readable text form, highlight its operands, and create hexadecimal //
|
|
// dump of the binary command. //
|
|
// //
|
|
// It is a stripped down version of the disassembler used by OllyDbg 2.01. //
|
|
// It can't analyse and comment the contents of the operands, or predict the //
|
|
// results of the command execution. Analysis-dependent features are not //
|
|
// included, too. Most other features are kept. //
|
|
// //
|
|
// Disassembler supports integer, FPU, MMX, 3DNow, SSE1-SSE4.1 and AVX //
|
|
// instructions. 64-bit mode, AVX2, FMA and XOP are not (yet) supported. //
|
|
// //
|
|
// This code can be compiled either in ASCII or UNICODE mode. It is reentrant //
|
|
// (thread-safe, feature not available in the original OllyDbg code). //
|
|
// //
|
|
// Typical operation speed on 3-GHz Phenom II in MASM mode is: //
|
|
// //
|
|
// Command length and info: 130 ns/command (7,700,000 commands/s) //
|
|
// Disassembly: 290 ns/command (3,400,000 commands/s) //
|
|
// Disassembly, dump, highlighting: 350 ns/command (2,800,000 commands/s) //
|
|
// //
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
////////////// PREFERRED SETTINGS AND FIXES FOR BORLAND COMPILERS //////////////
|
|
|
|
#ifdef __BORLANDC__
|
|
#pragma option -a1 // Byte alignment
|
|
#pragma option -w-pin // Disable "partially bracketed" warning
|
|
// Redefinition of MAKELONG removes nasty warning under Borland Builder 4.0:
|
|
// boolean OR in one row with arithmetical shift.
|
|
#undef MAKELONG
|
|
#define MAKELONG(lo,hi) ((LONG)(((WORD)(lo))|(((DWORD)((WORD)(hi)))<<16)))
|
|
#endif
|
|
|
|
#define MAKEWP(lo,hi) ((WPARAM)MAKELONG(lo,hi))
|
|
#define MAKELP(lo,hi) ((LPARAM)MAKELONG(lo,hi))
|
|
|
|
#define LOINT(l) ((signed short)((WORD)(l)))
|
|
#define HIINT(l) ((signed short)(((DWORD)(l)>>16) & 0xFFFF))
|
|
|
|
#ifndef FIELD_OFFSET
|
|
#define FIELD_OFFSET(type,field) ((long)&(((type *)0)->field))
|
|
#endif
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
#define TEXTLEN 256 // Max length of text string
|
|
#define SHORTNAME 32 // Max length of short or module name
|
|
|
|
#ifdef UNICODE
|
|
#define tchar wchar_t // Or replace it with TCHAR
|
|
#define T(x) L##x
|
|
#define tstrlen wcslen
|
|
#define tstrcpy wcscpy
|
|
#define tstrcmp wcscmp
|
|
#define tstrlwr _wcslwr
|
|
#define tsprintf swprintf
|
|
#define ttolower towlower
|
|
#else
|
|
#define tchar char
|
|
#define T(x) x
|
|
#define tstrlen strlen
|
|
#define tstrcpy strcpy
|
|
#define tstrcmp strcmp
|
|
#define tstrlwr strlwr
|
|
#define tsprintf sprintf
|
|
#define ttolower tolower
|
|
#endif
|
|
|
|
#define NOPERAND 4 // Maximal allowed number of operands
|
|
#define NREG 8 // Number of registers (of any type)
|
|
#define NSEG 6 // Number of valid segment registers
|
|
#define MAXCMDSIZE 16 // Maximal length of valid 80x86 command
|
|
#define NEGLIMIT (-16384) // Limit to decode offsets as negative
|
|
#define DECLIMIT 16384 // Limit to decode constants as decimal
|
|
|
|
typedef unsigned char uchar; // Unsigned character (byte)
|
|
typedef unsigned short ushort; // Unsigned short
|
|
typedef unsigned int uint; // Unsigned integer
|
|
typedef unsigned long ulong; // Unsigned long
|
|
|
|
// CMDMASK can be used to balance between the necessary memory size and the
|
|
// disassembly time.
|
|
#define CMDMASK 0x3FFF // Search mask for Disassembler, 2**n-1
|
|
#define NCHAIN 44300 // Max allowed number of chain links
|
|
|
|
// Registers.
|
|
#define REG_UNDEF (-1) // Codes of general purpose registers
|
|
#define REG_EAX 0
|
|
#define REG_ECX 1
|
|
#define REG_EDX 2
|
|
#define REG_EBX 3
|
|
#define REG_ESP 4
|
|
#define REG_EBP 5
|
|
#define REG_ESI 6
|
|
#define REG_EDI 7
|
|
|
|
#define REG_AL 0 // Symbolic indices of 8-bit registers
|
|
#define REG_CL 1
|
|
#define REG_DL 2
|
|
#define REG_BL 3
|
|
#define REG_AH 4
|
|
#define REG_CH 5
|
|
#define REG_DH 6
|
|
#define REG_BH 7
|
|
|
|
#define SEG_UNDEF (-1) // Codes of segment/selector registers
|
|
#define SEG_ES 0
|
|
#define SEG_CS 1
|
|
#define SEG_SS 2
|
|
#define SEG_DS 3
|
|
#define SEG_FS 4
|
|
#define SEG_GS 5
|
|
|
|
// Command highlighting.
|
|
#define DRAW_PLAIN '.' //0x0000000C // Plain commands
|
|
#define DRAW_JUMP '>' //0x0000000D // Unconditional jump commands
|
|
#define DRAW_CJMP '?' //0x0000000E // Conditional jump commands
|
|
#define DRAW_PUSHPOP '=' //0x0000000F // PUSH/POP commands
|
|
#define DRAW_CALL '@' //0x00000010 // CALL commands
|
|
#define DRAW_RET '<' //0x00000011 // RET commands
|
|
#define DRAW_FPU '1' //0x00000012 // FPU, MMX, 3DNow! and SSE commands
|
|
#define DRAW_SUSPECT '!' //0x00000013 // Bad, system and privileged commands
|
|
// Operand highlighting.
|
|
#define DRAW_IREG 'R' //0x00000018 // General purpose registers
|
|
#define DRAW_FREG 'F' //0x00000019 // FPU, MMX and SSE registers
|
|
#define DRAW_SYSREG 'S' //0x0000001A // Segment and system registers
|
|
#define DRAW_STKMEM 'K' //0x0000001B // Memory accessed over ESP or EBP
|
|
#define DRAW_MEM 'M' //0x0000001C // Any other memory
|
|
#define DRAW_CONST 'C' //0x0000001E // Constant
|
|
|
|
#define D_NONE 0x00000000 // No special features
|
|
// General type of command, only one is allowed.
|
|
#define D_CMDTYPE 0x0000001F // Mask to extract type of command
|
|
#define D_CMD 0x00000000 // Ordinary (none of listed below)
|
|
#define D_MOV 0x00000001 // Move to or from integer register
|
|
#define D_MOVC 0x00000002 // Conditional move to integer register
|
|
#define D_SETC 0x00000003 // Conditional set integer register
|
|
#define D_TEST 0x00000004 // Used to test data (CMP, TEST, AND...)
|
|
#define D_STRING 0x00000005 // String command with REPxxx prefix
|
|
#define D_JMP 0x00000006 // Unconditional near jump
|
|
#define D_JMPFAR 0x00000007 // Unconditional far jump
|
|
#define D_JMC 0x00000008 // Conditional jump on flags
|
|
#define D_JMCX 0x00000009 // Conditional jump on (E)CX (and flags)
|
|
#define D_PUSH 0x0000000A // PUSH exactly 1 (d)word of data
|
|
#define D_POP 0x0000000B // POP exactly 1 (d)word of data
|
|
#define D_CALL 0x0000000C // Plain near call
|
|
#define D_CALLFAR 0x0000000D // Far call
|
|
#define D_INT 0x0000000E // Interrupt
|
|
#define D_RET 0x0000000F // Plain near return from call
|
|
#define D_RETFAR 0x00000010 // Far return or IRET
|
|
#define D_FPU 0x00000011 // FPU command
|
|
#define D_MMX 0x00000012 // MMX instruction, incl. SSE extensions
|
|
#define D_3DNOW 0x00000013 // 3DNow! instruction
|
|
#define D_SSE 0x00000014 // SSE instruction
|
|
#define D_IO 0x00000015 // Accesses I/O ports
|
|
#define D_SYS 0x00000016 // Legal but useful in system code only
|
|
#define D_PRIVILEGED 0x00000017 // Privileged (non-Ring3) command
|
|
#define D_AVX 0x00000018 // AVX instruction
|
|
#define D_XOP 0x00000019 // AMD instruction with XOP prefix
|
|
#define D_DATA 0x0000001C // Data recognized by Analyser
|
|
#define D_PSEUDO 0x0000001D // Pseudocommand, for search models only
|
|
#define D_PREFIX 0x0000001E // Standalone prefix
|
|
#define D_BAD 0x0000001F // Bad or unrecognized command
|
|
// Additional parts of the command.
|
|
#define D_SIZE01 0x00000020 // Bit 0x01 in last cmd is data size
|
|
#define D_POSTBYTE 0x00000040 // Command continues in postbyte
|
|
// For string commands, either long or short form can be selected.
|
|
#define D_LONGFORM 0x00000080 // Long form of string command
|
|
// Decoding of some commands depends on data or address size.
|
|
#define D_SIZEMASK 0x00000F00 // Mask for data/address size dependence
|
|
#define D_DATA16 0x00000100 // Requires 16-bit data size
|
|
#define D_DATA32 0x00000200 // Requires 32-bit data size
|
|
#define D_ADDR16 0x00000400 // Requires 16-bit address size
|
|
#define D_ADDR32 0x00000800 // Requires 32-bit address size
|
|
// Prefixes that command may, must or must not possess.
|
|
#define D_MUSTMASK 0x0000F000 // Mask for fixed set of prefixes
|
|
#define D_NOMUST 0x00000000 // No obligatory prefixes (default)
|
|
#define D_MUST66 0x00001000 // (SSE,AVX) Requires 66, no F2 or F3
|
|
#define D_MUSTF2 0x00002000 // (SSE,AVX) Requires F2, no 66 or F3
|
|
#define D_MUSTF3 0x00003000 // (SSE,AVX) Requires F3, no 66 or F2
|
|
#define D_MUSTNONE 0x00004000 // (MMX,SSE,AVX) Requires no 66, F2, F3
|
|
#define D_NEEDF2 0x00005000 // (SSE,AVX) Requires F2, no F3
|
|
#define D_NEEDF3 0x00006000 // (SSE,AVX) Requires F3, no F2
|
|
#define D_NOREP 0x00007000 // Must not include F2 or F3
|
|
#define D_MUSTREP 0x00008000 // Must include F3 (REP)
|
|
#define D_MUSTREPE 0x00009000 // Must include F3 (REPE)
|
|
#define D_MUSTREPNE 0x0000A000 // Must include F2 (REPNE)
|
|
#define D_LOCKABLE 0x00010000 // Allows for F0 (LOCK, memory only)
|
|
#define D_BHINT 0x00020000 // Allows for branch hints (2E, 3E)
|
|
// Decoding of some commands with ModRM-SIB depends whether register or memory.
|
|
#define D_MEMORY 0x00040000 // Mod field must indicate memory
|
|
#define D_REGISTER 0x00080000 // Mod field must indicate register
|
|
// Side effects caused by command.
|
|
#define D_FLAGMASK 0x00700000 // Mask to extract modified flags
|
|
#define D_NOFLAGS 0x00000000 // Flags S,Z,P,O,C remain unchanged
|
|
#define D_ALLFLAGS 0x00100000 // Modifies flags S,Z,P,O,C
|
|
#define D_FLAGZ 0x00200000 // Modifies flag Z only
|
|
#define D_FLAGC 0x00300000 // Modifies flag C only
|
|
#define D_FLAGSCO 0x00400000 // Modifies flag C and O only
|
|
#define D_FLAGD 0x00500000 // Modifies flag D only
|
|
#define D_FLAGSZPC 0x00600000 // Modifies flags Z, P and C only (FPU)
|
|
#define D_NOCFLAG 0x00700000 // S,Z,P,O modified, C unaffected
|
|
#define D_FPUMASK 0x01800000 // Mask for effects on FPU stack
|
|
#define D_FPUSAME 0x00000000 // Doesn't rotate FPU stack (default)
|
|
#define D_FPUPOP 0x00800000 // Pops FPU stack
|
|
#define D_FPUPOP2 0x01000000 // Pops FPU stack twice
|
|
#define D_FPUPUSH 0x01800000 // Pushes FPU stack
|
|
#define D_CHGESP 0x02000000 // Command indirectly modifies ESP
|
|
// Command features.
|
|
#define D_HLADIR 0x04000000 // Nonstandard order of operands in HLA
|
|
#define D_WILDCARD 0x08000000 // Mnemonics contains W/D wildcard ('*')
|
|
#define D_COND 0x10000000 // Conditional (action depends on flags)
|
|
#define D_USESCARRY 0x20000000 // Uses Carry flag
|
|
#define D_USEMASK 0xC0000000 // Mask to detect unusual commands
|
|
#define D_RARE 0x40000000 // Rare or obsolete in Win32 apps
|
|
#define D_SUSPICIOUS 0x80000000 // Suspicious command
|
|
#define D_UNDOC 0xC0000000 // Undocumented command
|
|
|
|
// Extension of D_xxx.
|
|
#define DX_ZEROMASK 0x00000003 // How to decode FLAGS.Z flag
|
|
#define DX_JE 0x00000001 // JE, JNE instead of JZ, JNZ
|
|
#define DX_JZ 0x00000002 // JZ, JNZ instead of JE, JNE
|
|
#define DX_CARRYMASK 0x0000000C // How to decode FLAGS.C flag
|
|
#define DX_JB 0x00000004 // JAE, JB instead of JC, JNC
|
|
#define DX_JC 0x00000008 // JC, JNC instead of JAE, JB
|
|
#define DX_RETN 0x00000010 // The mnemonics is RETN
|
|
#define DX_VEX 0x00000100 // Requires VEX prefix
|
|
#define DX_VLMASK 0x00000600 // Mask to extract VEX operand length
|
|
#define DX_LSHORT 0x00000000 // 128-bit only
|
|
#define DX_LBOTH 0x00000200 // Both 128- and 256-bit versions
|
|
#define DX_LLONG 0x00000400 // 256-bit only
|
|
#define DX_IGNOREL 0x00000600 // Ignore VEX.L
|
|
#define DX_NOVREG 0x00000800 // VEX.vvvv must be set to all 1's
|
|
#define DX_VWMASK 0x00003000 // Mask to extract VEX.W
|
|
#define DX_W0 0x00001000 // VEX.W must be 0
|
|
#define DX_W1 0x00002000 // VEX.W must be 1
|
|
#define DX_LEADMASK 0x00070000 // Mask to extract leading opcode bytes
|
|
#define DX_LEAD0F 0x00000000 // Implied 0F leading byte (default)
|
|
#define DX_LEAD38 0x00010000 // Implied 0F 38 leading opcode bytes
|
|
#define DX_LEAD3A 0x00020000 // Implied 0F 3A leading opcode bytes
|
|
#define DX_WONKYTRAP 0x00800000 // Don't single-step this command
|
|
#define DX_TYPEMASK 0xFF000000 // Precised command type mask
|
|
#define DX_ADD 0x01000000 // The command is integer ADD
|
|
#define DX_SUB 0x02000000 // The command is integer SUB
|
|
#define DX_LEA 0x03000000 // The command is LEA
|
|
#define DX_NOP 0x04000000 // The command is NOP
|
|
|
|
//#define DX_LVEX (DX_VEX|DX_LBOTH)
|
|
//#define DX_GVEX (DX_VEX|DX_LLONG)
|
|
|
|
// Type of operand, only one is allowed. Size of SSE operands is given for the
|
|
// case of 128-bit operations and usually doubles for 256-bit AVX commands. If
|
|
// B_NOVEXSIZE is set, memory may double but XMM registers are not promoted to
|
|
// YMM.
|
|
#define B_ARGMASK 0x000000FF // Mask to extract type of argument
|
|
#define B_NONE 0x00000000 // Operand absent
|
|
#define B_AL 0x00000001 // Register AL
|
|
#define B_AH 0x00000002 // Register AH
|
|
#define B_AX 0x00000003 // Register AX
|
|
#define B_CL 0x00000004 // Register CL
|
|
#define B_CX 0x00000005 // Register CX
|
|
#define B_DX 0x00000006 // Register DX
|
|
#define B_DXPORT 0x00000007 // Register DX as I/O port address
|
|
#define B_EAX 0x00000008 // Register EAX
|
|
#define B_EBX 0x00000009 // Register EBX
|
|
#define B_ECX 0x0000000A // Register ECX
|
|
#define B_EDX 0x0000000B // Register EDX
|
|
#define B_ACC 0x0000000C // Accumulator (AL/AX/EAX)
|
|
#define B_STRCNT 0x0000000D // Register CX or ECX as REPxx counter
|
|
#define B_DXEDX 0x0000000E // Register DX or EDX in DIV/MUL
|
|
#define B_BPEBP 0x0000000F // Register BP or EBP in ENTER/LEAVE
|
|
#define B_REG 0x00000010 // 8/16/32-bit register in Reg
|
|
#define B_REG16 0x00000011 // 16-bit register in Reg
|
|
#define B_REG32 0x00000012 // 32-bit register in Reg
|
|
#define B_REGCMD 0x00000013 // 16/32-bit register in last cmd byte
|
|
#define B_REGCMD8 0x00000014 // 8-bit register in last cmd byte
|
|
#define B_ANYREG 0x00000015 // Reg field is unused, any allowed
|
|
#define B_INT 0x00000016 // 8/16/32-bit register/memory in ModRM
|
|
#define B_INT8 0x00000017 // 8-bit register/memory in ModRM
|
|
#define B_INT16 0x00000018 // 16-bit register/memory in ModRM
|
|
#define B_INT32 0x00000019 // 32-bit register/memory in ModRM
|
|
#define B_INT1632 0x0000001A // 16/32-bit register/memory in ModRM
|
|
#define B_INT64 0x0000001B // 64-bit integer in ModRM, memory only
|
|
#define B_INT128 0x0000001C // 128-bit integer in ModRM, memory only
|
|
#define B_IMMINT 0x0000001D // 8/16/32-bit int at immediate addr
|
|
#define B_INTPAIR 0x0000001E // Two signed 16/32 in ModRM, memory only
|
|
#define B_SEGOFFS 0x0000001F // 16:16/16:32 absolute address in memory
|
|
#define B_STRDEST 0x00000020 // 8/16/32-bit string dest, [ES:(E)DI]
|
|
#define B_STRDEST8 0x00000021 // 8-bit string destination, [ES:(E)DI]
|
|
#define B_STRSRC 0x00000022 // 8/16/32-bit string source, [(E)SI]
|
|
#define B_STRSRC8 0x00000023 // 8-bit string source, [(E)SI]
|
|
#define B_XLATMEM 0x00000024 // 8-bit memory in XLAT, [(E)BX+AL]
|
|
#define B_EAXMEM 0x00000025 // Reference to memory addressed by [EAX]
|
|
#define B_LONGDATA 0x00000026 // Long data in ModRM, mem only
|
|
#define B_ANYMEM 0x00000027 // Reference to memory, data unimportant
|
|
#define B_STKTOP 0x00000028 // 16/32-bit int top of stack
|
|
#define B_STKTOPFAR 0x00000029 // Top of stack (16:16/16:32 far addr)
|
|
#define B_STKTOPEFL 0x0000002A // 16/32-bit flags on top of stack
|
|
#define B_STKTOPA 0x0000002B // 16/32-bit top of stack all registers
|
|
#define B_PUSH 0x0000002C // 16/32-bit int push to stack
|
|
#define B_PUSHRET 0x0000002D // 16/32-bit push of return address
|
|
#define B_PUSHRETF 0x0000002E // 16:16/16:32-bit push of far retaddr
|
|
#define B_PUSHA 0x0000002F // 16/32-bit push all registers
|
|
#define B_EBPMEM 0x00000030 // 16/32-bit int at [EBP]
|
|
#define B_SEG 0x00000031 // Segment register in Reg
|
|
#define B_SEGNOCS 0x00000032 // Segment register in Reg, but not CS
|
|
#define B_SEGCS 0x00000033 // Segment register CS
|
|
#define B_SEGDS 0x00000034 // Segment register DS
|
|
#define B_SEGES 0x00000035 // Segment register ES
|
|
#define B_SEGFS 0x00000036 // Segment register FS
|
|
#define B_SEGGS 0x00000037 // Segment register GS
|
|
#define B_SEGSS 0x00000038 // Segment register SS
|
|
#define B_ST 0x00000039 // 80-bit FPU register in last cmd byte
|
|
#define B_ST0 0x0000003A // 80-bit FPU register ST0
|
|
#define B_ST1 0x0000003B // 80-bit FPU register ST1
|
|
#define B_FLOAT32 0x0000003C // 32-bit float in ModRM, memory only
|
|
#define B_FLOAT64 0x0000003D // 64-bit float in ModRM, memory only
|
|
#define B_FLOAT80 0x0000003E // 80-bit float in ModRM, memory only
|
|
#define B_BCD 0x0000003F // 80-bit BCD in ModRM, memory only
|
|
#define B_MREG8x8 0x00000040 // MMX register as 8 8-bit integers
|
|
#define B_MMX8x8 0x00000041 // MMX reg/memory as 8 8-bit integers
|
|
#define B_MMX8x8DI 0x00000042 // MMX 8 8-bit integers at [DS:(E)DI]
|
|
#define B_MREG16x4 0x00000043 // MMX register as 4 16-bit integers
|
|
#define B_MMX16x4 0x00000044 // MMX reg/memory as 4 16-bit integers
|
|
#define B_MREG32x2 0x00000045 // MMX register as 2 32-bit integers
|
|
#define B_MMX32x2 0x00000046 // MMX reg/memory as 2 32-bit integers
|
|
#define B_MREG64 0x00000047 // MMX register as 1 64-bit integer
|
|
#define B_MMX64 0x00000048 // MMX reg/memory as 1 64-bit integer
|
|
#define B_3DREG 0x00000049 // 3DNow! register as 2 32-bit floats
|
|
#define B_3DNOW 0x0000004A // 3DNow! reg/memory as 2 32-bit floats
|
|
#define B_XMM0I32x4 0x0000004B // XMM0 as 4 32-bit integers
|
|
#define B_XMM0I64x2 0x0000004C // XMM0 as 2 64-bit integers
|
|
#define B_XMM0I8x16 0x0000004D // XMM0 as 16 8-bit integers
|
|
#define B_SREGF32x4 0x0000004E // SSE register as 4 32-bit floats
|
|
#define B_SREGF32L 0x0000004F // Low 32-bit float in SSE register
|
|
#define B_SREGF32x2L 0x00000050 // Low 2 32-bit floats in SSE register
|
|
#define B_SSEF32x4 0x00000051 // SSE reg/memory as 4 32-bit floats
|
|
#define B_SSEF32L 0x00000052 // Low 32-bit float in SSE reg/memory
|
|
#define B_SSEF32x2L 0x00000053 // Low 2 32-bit floats in SSE reg/memory
|
|
#define B_SREGF64x2 0x00000054 // SSE register as 2 64-bit floats
|
|
#define B_SREGF64L 0x00000055 // Low 64-bit float in SSE register
|
|
#define B_SSEF64x2 0x00000056 // SSE reg/memory as 2 64-bit floats
|
|
#define B_SSEF64L 0x00000057 // Low 64-bit float in SSE reg/memory
|
|
#define B_SREGI8x16 0x00000058 // SSE register as 16 8-bit sigints
|
|
#define B_SSEI8x16 0x00000059 // SSE reg/memory as 16 8-bit sigints
|
|
#define B_SSEI8x16DI 0x0000005A // SSE 16 8-bit sigints at [DS:(E)DI]
|
|
#define B_SSEI8x8L 0x0000005B // Low 8 8-bit ints in SSE reg/memory
|
|
#define B_SSEI8x4L 0x0000005C // Low 4 8-bit ints in SSE reg/memory
|
|
#define B_SSEI8x2L 0x0000005D // Low 2 8-bit ints in SSE reg/memory
|
|
#define B_SREGI16x8 0x0000005E // SSE register as 8 16-bit sigints
|
|
#define B_SSEI16x8 0x0000005F // SSE reg/memory as 8 16-bit sigints
|
|
#define B_SSEI16x4L 0x00000060 // Low 4 16-bit ints in SSE reg/memory
|
|
#define B_SSEI16x2L 0x00000061 // Low 2 16-bit ints in SSE reg/memory
|
|
#define B_SREGI32x4 0x00000062 // SSE register as 4 32-bit sigints
|
|
#define B_SREGI32L 0x00000063 // Low 32-bit sigint in SSE register
|
|
#define B_SREGI32x2L 0x00000064 // Low 2 32-bit sigints in SSE register
|
|
#define B_SSEI32x4 0x00000065 // SSE reg/memory as 4 32-bit sigints
|
|
#define B_SSEI32x2L 0x00000066 // Low 2 32-bit sigints in SSE reg/memory
|
|
#define B_SREGI64x2 0x00000067 // SSE register as 2 64-bit sigints
|
|
#define B_SSEI64x2 0x00000068 // SSE reg/memory as 2 64-bit sigints
|
|
#define B_SREGI64L 0x00000069 // Low 64-bit sigint in SSE register
|
|
#define B_EFL 0x0000006A // Flags register EFL
|
|
#define B_FLAGS8 0x0000006B // Flags (low byte)
|
|
#define B_OFFSET 0x0000006C // 16/32 const offset from next command
|
|
#define B_BYTEOFFS 0x0000006D // 8-bit sxt const offset from next cmd
|
|
#define B_FARCONST 0x0000006E // 16:16/16:32 absolute address constant
|
|
#define B_DESCR 0x0000006F // 16:32 descriptor in ModRM
|
|
#define B_1 0x00000070 // Immediate constant 1
|
|
#define B_CONST8 0x00000071 // Immediate 8-bit constant
|
|
#define B_CONST8_2 0x00000072 // Immediate 8-bit const, second in cmd
|
|
#define B_CONST16 0x00000073 // Immediate 16-bit constant
|
|
#define B_CONST 0x00000074 // Immediate 8/16/32-bit constant
|
|
#define B_CONSTL 0x00000075 // Immediate 16/32-bit constant
|
|
#define B_SXTCONST 0x00000076 // Immediate 8-bit sign-extended to size
|
|
#define B_CR 0x00000077 // Control register in Reg
|
|
#define B_CR0 0x00000078 // Control register CR0
|
|
#define B_DR 0x00000079 // Debug register in Reg
|
|
#define B_FST 0x0000007A // FPU status register
|
|
#define B_FCW 0x0000007B // FPU control register
|
|
#define B_MXCSR 0x0000007C // SSE media control and status register
|
|
#define B_SVEXF32x4 0x0000007D // SSE reg in VEX as 4 32-bit floats
|
|
#define B_SVEXF32L 0x0000007E // Low 32-bit float in SSE in VEX
|
|
#define B_SVEXF64x2 0x0000007F // SSE reg in VEX as 2 64-bit floats
|
|
#define B_SVEXF64L 0x00000080 // Low 64-bit float in SSE in VEX
|
|
#define B_SVEXI8x16 0x00000081 // SSE reg in VEX as 16 8-bit sigints
|
|
#define B_SVEXI16x8 0x00000082 // SSE reg in VEX as 8 16-bit sigints
|
|
#define B_SVEXI32x4 0x00000083 // SSE reg in VEX as 4 32-bit sigints
|
|
#define B_SVEXI64x2 0x00000084 // SSE reg in VEX as 2 64-bit sigints
|
|
#define B_SIMMI8x16 0x00000085 // SSE reg in immediate 8-bit constant
|
|
// Type modifiers, used for interpretation of contents, only one is allowed.
|
|
#define B_MODMASK 0x000F0000 // Mask to extract type modifier
|
|
#define B_NONSPEC 0x00000000 // Non-specific operand
|
|
#define B_UNSIGNED 0x00010000 // Decode as unsigned decimal
|
|
#define B_SIGNED 0x00020000 // Decode as signed decimal
|
|
#define B_BINARY 0x00030000 // Decode as binary (full hex) data
|
|
#define B_BITCNT 0x00040000 // Bit count
|
|
#define B_SHIFTCNT 0x00050000 // Shift count
|
|
#define B_COUNT 0x00060000 // General-purpose count
|
|
#define B_NOADDR 0x00070000 // Not an address
|
|
#define B_JMPCALL 0x00080000 // Near jump/call/return destination
|
|
#define B_JMPCALLFAR 0x00090000 // Far jump/call/return destination
|
|
#define B_STACKINC 0x000A0000 // Unsigned stack increment/decrement
|
|
#define B_PORT 0x000B0000 // I/O port
|
|
#define B_ADDR 0x000F0000 // Used internally
|
|
// Validity markers.
|
|
#define B_MEMORY 0x00100000 // Memory only, reg version different
|
|
#define B_REGISTER 0x00200000 // Register only, mem version different
|
|
#define B_MEMONLY 0x00400000 // Warn if operand in register
|
|
#define B_REGONLY 0x00800000 // Warn if operand in memory
|
|
#define B_32BITONLY 0x01000000 // Warn if 16-bit operand
|
|
#define B_NOESP 0x02000000 // ESP is not allowed
|
|
// Miscellaneous options.
|
|
#define B_NOVEXSIZE 0x04000000 // Always 128-bit SSE in 256-bit AVX
|
|
#define B_SHOWSIZE 0x08000000 // Always show argument size in disasm
|
|
#define B_CHG 0x10000000 // Changed, old contents is not used
|
|
#define B_UPD 0x20000000 // Modified using old contents
|
|
#define B_PSEUDO 0x40000000 // Pseoudooperand, not in assembler cmd
|
|
#define B_NOSEG 0x80000000 // Don't add offset of selector
|
|
|
|
// Location of operand, only one bit is allowed.
|
|
#define OP_SOMEREG 0x000000FF // Mask for any kind of register
|
|
#define OP_REGISTER 0x00000001 // Operand is a general-purpose register
|
|
#define OP_SEGREG 0x00000002 // Operand is a segment register
|
|
#define OP_FPUREG 0x00000004 // Operand is a FPU register
|
|
#define OP_MMXREG 0x00000008 // Operand is a MMX register
|
|
#define OP_3DNOWREG 0x00000010 // Operand is a 3DNow! register
|
|
#define OP_SSEREG 0x00000020 // Operand is a SSE register
|
|
#define OP_CREG 0x00000040 // Operand is a control register
|
|
#define OP_DREG 0x00000080 // Operand is a debug register
|
|
#define OP_MEMORY 0x00000100 // Operand is in memory
|
|
#define OP_CONST 0x00000200 // Operand is an immediate constant
|
|
// Additional operand properties.
|
|
#define OP_PORT 0x00000400 // Used to access I/O port
|
|
#define OP_OTHERREG 0x00000800 // Special register like EFL or MXCSR
|
|
#define OP_INVALID 0x00001000 // Invalid operand, like reg in mem-only
|
|
#define OP_PSEUDO 0x00002000 // Pseudooperand (not in mnenonics)
|
|
#define OP_MOD 0x00004000 // Command may change/update operand
|
|
#define OP_MODREG 0x00008000 // Memory, but modifies reg (POP,MOVSD)
|
|
#define OP_IMPORT 0x00020000 // Value imported from different module
|
|
#define OP_SELECTOR 0x00040000 // Includes immediate selector
|
|
// Additional properties of memory address.
|
|
#define OP_INDEXED 0x00080000 // Memory address contains registers
|
|
#define OP_OPCONST 0x00100000 // Memory address contains constant
|
|
#define OP_ADDR16 0x00200000 // 16-bit memory address
|
|
#define OP_ADDR32 0x00400000 // Explicit 32-bit memory address
|
|
|
|
#define DAMODE_MASM 0 // MASM assembling/disassembling style
|
|
#define DAMODE_IDEAL 1 // IDEAL assembling/disassembling style
|
|
#define DAMODE_HLA 2 // HLA assembling/disassembling style
|
|
#define DAMODE_ATT 3 // AT&T disassembling style
|
|
|
|
#define NUM_STYLE 0x0003 // Mask to extract hex style
|
|
#define NUM_STD 0x0000 // 123, 12345678h, 0ABCD1234h
|
|
#define NUM_X 0x0001 // 123, 0x12345678, 0xABCD1234
|
|
#define NUM_OLLY 0x0002 // 123., 12345678, 0ABCD1234
|
|
#define NUM_LONG 0x0010 // 00001234h instead of 1234h
|
|
#define NUM_DECIMAL 0x0020 // 123 instead of 7Bh if under DECLIMIT
|
|
|
|
// Disassembling options.
|
|
#define DA_TEXT 0x00000001 // Decode command to text and comment
|
|
#define DA_HILITE 0x00000002 // Use syntax highlighting
|
|
#define DA_JZ 0x00000004 // JZ, JNZ instead of JE, JNE
|
|
#define DA_JC 0x00000008 // JC, JNC instead of JAE, JB
|
|
#define DA_DUMP 0x00000020 // Dump command to hexadecimal text
|
|
#define DA_PSEUDO 0x00000400 // List pseudooperands
|
|
|
|
// Disassembling errors.
|
|
#define DAE_NOERR 0x00000000 // No errors
|
|
#define DAE_BADCMD 0x00000001 // Unrecognized command
|
|
#define DAE_CROSS 0x00000002 // Command crosses end of memory block
|
|
#define DAE_MEMORY 0x00000004 // Register where only memory allowed
|
|
#define DAE_REGISTER 0x00000008 // Memory where only register allowed
|
|
#define DAE_LOCK 0x00000010 // LOCK prefix is not allowed
|
|
#define DAE_BADSEG 0x00000020 // Invalid segment register
|
|
#define DAE_SAMEPREF 0x00000040 // Two prefixes from the same group
|
|
#define DAE_MANYPREF 0x00000080 // More than 4 prefixes
|
|
#define DAE_BADCR 0x00000100 // Invalid CR register
|
|
#define DAE_INTERN 0x00000200 // Internal error
|
|
|
|
// Disassembling warnings.
|
|
#define DAW_NOWARN 0x00000000 // No warnings
|
|
#define DAW_DATASIZE 0x00000001 // Superfluous data size prefix
|
|
#define DAW_ADDRSIZE 0x00000002 // Superfluous address size prefix
|
|
#define DAW_SEGPREFIX 0x00000004 // Superfluous segment override prefix
|
|
#define DAW_REPPREFIX 0x00000008 // Superfluous REPxx prefix
|
|
#define DAW_DEFSEG 0x00000010 // Segment prefix coincides with default
|
|
#define DAW_JMP16 0x00000020 // 16-bit jump, call or return
|
|
#define DAW_FARADDR 0x00000040 // Far jump or call
|
|
#define DAW_SEGMOD 0x00000080 // Modifies segment register
|
|
#define DAW_PRIV 0x00000100 // Privileged command
|
|
#define DAW_IO 0x00000200 // I/O command
|
|
#define DAW_SHIFT 0x00000400 // Shift out of range 1..31
|
|
#define DAW_LOCK 0x00000800 // Command with valid LOCK prefix
|
|
#define DAW_STACK 0x00001000 // Unaligned stack operation
|
|
#define DAW_NOESP 0x00002000 // Suspicious use of stack pointer
|
|
#define DAW_RARE 0x00004000 // Rare, seldom used command
|
|
#define DAW_NONCLASS 0x00008000 // Non-standard or non-documented code
|
|
#define DAW_INTERRUPT 0x00010000 // Interrupt command
|
|
|
|
// List of prefixes.
|
|
#define PF_SEGMASK 0x0000003F // Mask for segment override prefixes
|
|
#define PF_ES 0x00000001 // 0x26, ES segment override
|
|
#define PF_CS 0x00000002 // 0x2E, CS segment override
|
|
#define PF_SS 0x00000004 // 0x36, SS segment override
|
|
#define PF_DS 0x00000008 // 0x3E, DS segment override
|
|
#define PF_FS 0x00000010 // 0x64, FS segment override
|
|
#define PF_GS 0x00000020 // 0x65, GS segment override
|
|
#define PF_DSIZE 0x00000040 // 0x66, data size override
|
|
#define PF_ASIZE 0x00000080 // 0x67, address size override
|
|
#define PF_LOCK 0x00000100 // 0xF0, bus lock
|
|
#define PF_REPMASK 0x00000600 // Mask for repeat prefixes
|
|
#define PF_REPNE 0x00000200 // 0xF2, REPNE prefix
|
|
#define PF_REP 0x00000400 // 0xF3, REP/REPE prefix
|
|
#define PF_BYTE 0x00000800 // Size bit in command, used in cmdexec
|
|
#define PF_MUSTMASK D_MUSTMASK // Necessary prefixes, used in t_asmmod
|
|
#define PF_VEX2 0x00010000 // 2-byte VEX prefix
|
|
#define PF_VEX3 0x00020000 // 3-byte VEX prefix
|
|
// Useful shortcuts.
|
|
#define PF_66 PF_DSIZE // Alternative names for SSE prefixes
|
|
#define PF_F2 PF_REPNE
|
|
#define PF_F3 PF_REP
|
|
#define PF_HINT (PF_CS|PF_DS) // Alternative names for branch hints
|
|
#define PF_NOTTAKEN PF_CS
|
|
#define PF_TAKEN PF_DS
|
|
#define PF_VEX (PF_VEX2|PF_VEX3)
|
|
|
|
typedef struct t_modrm { // ModRM byte decoding
|
|
ulong size; // Total size with SIB and disp, bytes
|
|
struct t_modrm *psib; // Pointer to SIB table or NULL
|
|
ulong dispsize; // Size of displacement or 0 if none
|
|
ulong features; // Operand features, set of OP_xxx
|
|
int reg; // Register index or REG_UNDEF
|
|
int defseg; // Default selector (SEG_xxx)
|
|
uchar scale[NREG]; // Scales of registers in memory address
|
|
ulong aregs; // List of registers used in address
|
|
int basereg; // Register used as base or REG_UNDEF
|
|
tchar ardec[SHORTNAME]; // Register part of address, INTEL fmt
|
|
tchar aratt[SHORTNAME]; // Register part of address, AT&T fmt
|
|
} t_modrm;
|
|
|
|
typedef struct t_bincmd { // Description of 80x86 command
|
|
tchar *name; // Symbolic name for this command
|
|
ulong cmdtype; // Command's features, set of D_xxx
|
|
ulong exttype; // More features, set of DX_xxx
|
|
ulong length; // Length of main code (before ModRM/SIB)
|
|
ulong mask; // Mask for first 4 bytes of the command
|
|
ulong code; // Compare masked bytes with this
|
|
ulong postbyte; // Postbyte
|
|
ulong arg[NOPERAND]; // Types of arguments, set of B_xxx
|
|
} t_bincmd;
|
|
|
|
typedef struct t_chain { // Element of command chain
|
|
const t_bincmd *pcmd; // Pointer to command descriptor or NULL
|
|
struct t_chain *pnext; // Pointer to next element in chain
|
|
} t_chain;
|
|
|
|
typedef struct t_config { // Disassembler configuration
|
|
int disasmmode; // Main style, one of DAMODE_xxx
|
|
int memmode; // Constant part of address, NUM_xxx
|
|
int jmpmode; // Jump/call destination, NUM_xxx
|
|
int binconstmode; // Binary constants, NUM_xxx
|
|
int constmode; // Numeric constants, NUM_xxx
|
|
int lowercase; // Force lowercase display
|
|
int tabarguments; // Tab between mnemonic and arguments
|
|
int extraspace; // Extra space between arguments
|
|
int useretform; // Use RET instead of RETN
|
|
int shortstringcmds; // Use short form of string commands
|
|
int putdefseg; // Display default segments in listing
|
|
int showmemsize; // Always show memory size
|
|
int shownear; // Show NEAR modifiers
|
|
int ssesizemode; // How to decode size of SSE operands
|
|
int jumphintmode; // How to decode jump hints
|
|
int sizesens; // How to decode size-sensitive mnemonics
|
|
int simplifiedst; // How to decode top of FPU stack
|
|
int hiliteoperands; // Highlight operands
|
|
} t_config;
|
|
|
|
typedef struct t_operand { // Description of disassembled operand
|
|
// Description of operand.
|
|
ulong features; // Operand features, set of OP_xxx
|
|
ulong arg; // Operand type, set of B_xxx
|
|
// int optype; // DEC_INT, DEC_FLOAT or DEC_UNKNOWN
|
|
int opsize; // Total size of data, bytes
|
|
int granularity; // Size of element (opsize exc. MMX/SSE)
|
|
int reg; // REG_xxx (also ESP in POP) or REG_UNDEF
|
|
ulong uses; // List of used regs (not in address!)
|
|
ulong modifies; // List of modified regs (not in addr!)
|
|
// Description of memory address.
|
|
int seg; // Selector (SEG_xxx)
|
|
uchar scale[NREG]; // Scales of registers in memory address
|
|
ulong aregs; // List of registers used in address
|
|
ulong opconst; // Constant or const part of address
|
|
ulong selector; // Immediate selector in far jump/call
|
|
// Textual decoding.
|
|
tchar text[TEXTLEN]; // Operand, decoded to text
|
|
} t_operand;
|
|
|
|
// Note that used registers are those which contents is necessary to create
|
|
// result. Modified registers are those which value is changed. For example,
|
|
// command MOV EAX,[EBX+ECX] uses EBX and ECX and modifies EAX. Command
|
|
// ADD ESI,EDI uses ESI and EDI and modifies ESI.
|
|
typedef struct t_disasm { // Disassembled command
|
|
ulong ip; // Address of first command byte
|
|
ulong size; // Full length of command, bytes
|
|
ulong cmdtype; // Type of command, D_xxx
|
|
ulong exttype; // More features, set of DX_xxx
|
|
ulong prefixes; // List of prefixes, set of PF_xxx
|
|
ulong nprefix; // Number of prefixes, including SSE2
|
|
ulong memfixup; // Offset of first 4-byte fixup or -1
|
|
ulong immfixup; // Offset of second 4-byte fixup or -1
|
|
int errors; // Set of DAE_xxx
|
|
int warnings; // Set of DAW_xxx
|
|
ulong uses; // List of used registers
|
|
ulong modifies; // List of modified registers
|
|
ulong memconst; // Constant in memory address or 0
|
|
ulong stackinc; // Data size in ENTER/RETN/RETF
|
|
t_operand op[NOPERAND]; // Operands
|
|
tchar dump[TEXTLEN]; // Hex dump of the command
|
|
tchar result[TEXTLEN]; // Fully decoded command as text
|
|
uchar mask[TEXTLEN]; // Mask to highlight result
|
|
int masksize; // Length of mask corresponding to result
|
|
} t_disasm;
|
|
|
|
extern t_modrm modrm16[256]; // 16-bit ModRM decodings
|
|
extern t_modrm modrm32[256]; // 32-bit ModRM decodings without SIB
|
|
extern t_modrm sib0[256]; // ModRM-SIB decodings with Mod=00
|
|
extern t_modrm sib1[256]; // ModRM-SIB decodings with Mod=01
|
|
extern t_modrm sib2[256]; // ModRM-SIB decodings with Mod=10
|
|
|
|
extern const t_bincmd bincmd[]; // List of 80x86 commands
|
|
extern t_chain *cmdchain; // Commands sorted by first CMDMASK bits
|
|
|
|
int Preparedisasm(void);
|
|
void Finishdisasm(void);
|
|
|
|
ulong Disasm(uchar const *cmd,ulong cmdsize,ulong cmdip,
|
|
t_disasm *da,int cmdmode,t_config *cmdconfig,
|
|
int (*decodeaddress)(tchar *s,ulong addr));
|
|
tchar *Geterrwarnmessage(ulong errors,ulong warnings);
|
|
|