-
Notifications
You must be signed in to change notification settings - Fork 8
/
Copy pathdisasm.h
671 lines (630 loc) · 41.1 KB
/
disasm.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
////////////////////////////////////////////////////////////////////////////////
// //
// OllyDbg Disassembling Engine v2.01 //
// //
// Copyright (c) 2007-2013 Oleh Yuschuk, [email protected] //
// //
// 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 *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);