1
0
mirror of https://github.com/DxWnd/DxWnd.reloaded synced 2024-12-30 09:25:35 +01:00

672 lines
40 KiB
C
Raw Permalink Normal View History

////////////////////////////////////////////////////////////////////////////////
// //
// 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);