2473 lines
50 KiB
C
2473 lines
50 KiB
C
/*++
|
|
|
|
Copyright (c) 1995 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
disasm.c
|
|
|
|
Abstract:
|
|
|
|
This file contains the x86 disassmbler invoked by "!bde.u <16:16 address>"
|
|
|
|
Author:
|
|
|
|
Barry Bond (BarryBo)
|
|
|
|
Revision History:
|
|
|
|
09-May-1995 Barry Bond (BarryBo) Created
|
|
15-Jan-1996 Neil Sandlin (NeilSa) Merged with vdmexts
|
|
32 bit segments fixes
|
|
|
|
--*/
|
|
|
|
#include <precomp.h>
|
|
#pragma hdrstop
|
|
|
|
WORD gSelector = 0;
|
|
ULONG gOffset = 0;
|
|
int gMode = 0;
|
|
|
|
VOID
|
|
u(
|
|
CMD_ARGLIST
|
|
) {
|
|
VDMCONTEXT ThreadContext;
|
|
WORD selector;
|
|
ULONG offset;
|
|
int mode;
|
|
char rgchOutput[128];
|
|
char rgchExtra[128];
|
|
BYTE rgbInstruction[64];
|
|
CHAR sym_text[255];
|
|
CHAR sym_prev[255] = "";
|
|
DWORD dist;
|
|
int cb;
|
|
int i;
|
|
int j;
|
|
int count=10;
|
|
ULONG Base;
|
|
SELECTORINFO si;
|
|
ULONG BPNum;
|
|
UCHAR BPData;
|
|
BOOL bIsBP;
|
|
|
|
CMD_INIT();
|
|
|
|
mode = GetContext( &ThreadContext );
|
|
|
|
if (!GetNextToken()) {
|
|
if (!gSelector && !gOffset) {
|
|
selector = (WORD) ThreadContext.SegCs;
|
|
offset = ThreadContext.Eip;
|
|
} else {
|
|
mode = gMode;
|
|
selector = gSelector;
|
|
offset = gOffset;
|
|
}
|
|
} else if (!ParseIntelAddress(&mode, &selector, &offset)) {
|
|
return;
|
|
}
|
|
|
|
if (GetNextToken()) {
|
|
count = (int) EXPRESSION(lpArgumentString);
|
|
if (count > 1000) {
|
|
PRINTF("Count too large - ignored\n");
|
|
count=10;
|
|
}
|
|
}
|
|
|
|
if ( mode != PROT_MODE && mode != V86_MODE) {
|
|
PRINTF(" Disassembly of flat mode code not allowed.\n");
|
|
return;
|
|
}
|
|
|
|
LoadBreakPointCache();
|
|
Base = GetInfoFromSelector( selector, mode, &si ) + GetIntelBase();
|
|
|
|
for (i=0; i<count; ++i) {
|
|
|
|
if (FindSymbol(selector, offset, sym_text, &dist, BEFORE, mode )) {
|
|
if (_stricmp(sym_text, sym_prev)) {
|
|
if ( dist == 0 ) {
|
|
PRINTF("%s:\n", sym_text );
|
|
} else {
|
|
PRINTF("%s+0x%lx:\n", sym_text, dist );
|
|
}
|
|
strcpy(sym_prev, sym_text);
|
|
}
|
|
}
|
|
|
|
cb = sizeof(rgbInstruction);
|
|
if ((DWORD)(offset+cb) >= si.Limit)
|
|
cb -= offset+cb-si.Limit;
|
|
if (!READMEM((LPVOID)(Base+offset), rgbInstruction, cb)) {
|
|
PRINTF("%04x:%08x: <Error Reading Memory>\n", selector, offset);
|
|
return;
|
|
}
|
|
|
|
if (bIsBP = IsVdmBreakPoint(selector,
|
|
offset,
|
|
mode==PROT_MODE,
|
|
&BPNum,
|
|
&BPData)) {
|
|
rgbInstruction[0] = BPData;
|
|
}
|
|
|
|
cb = unassemble_one(rgbInstruction,
|
|
si.bBig,
|
|
selector, offset,
|
|
rgchOutput,
|
|
rgchExtra,
|
|
&ThreadContext,
|
|
mode);
|
|
|
|
gOffset += cb;
|
|
|
|
if (offset > 0xffff) {
|
|
PRINTF("%04x:%08x ", selector, offset);
|
|
} else {
|
|
PRINTF("%04x:%04x ", selector, offset);
|
|
}
|
|
|
|
for (j=0; j<cb; ++j)
|
|
PRINTF("%02x", rgbInstruction[j]);
|
|
for (; j<8; ++j)
|
|
PRINTF(" ");
|
|
|
|
PRINTF("%s\t%s", rgchOutput, rgchExtra);
|
|
|
|
if (bIsBP) {
|
|
PRINTF("; BP%d",BPNum);
|
|
}
|
|
|
|
PRINTF("\n");
|
|
offset+=cb;
|
|
}
|
|
}
|
|
|
|
|
|
typedef struct _ADDR {
|
|
ULONG sOff;
|
|
USHORT sSeg;
|
|
} ADDR;
|
|
|
|
|
|
LPBYTE checkprefixes(LPBYTE);
|
|
void AppendPrefixes(void);
|
|
void DisplayAddress(int mod, int rm, int sOff, int size);
|
|
int DisplayBOP(void);
|
|
|
|
#define modrmB 1
|
|
#define modrmW 2
|
|
#define reg1B 3
|
|
#define reg1W 4
|
|
#define reg2B 5
|
|
#define reg2W 6
|
|
#define eeeControl 7
|
|
#define eeeDebug 8
|
|
#define eeeTest 9
|
|
#define regSeg 10
|
|
#define ALreg 11
|
|
#define AHreg 12
|
|
#define BLreg 13
|
|
#define BHreg 14
|
|
#define CLreg 15
|
|
#define CHreg 16
|
|
#define DLreg 17
|
|
#define DHreg 18
|
|
#define AXreg 19
|
|
#define BXreg 20
|
|
#define CXreg 21
|
|
#define DXreg 22
|
|
#define SIreg 23
|
|
#define DIreg 24
|
|
#define SPreg 25
|
|
#define BPreg 26
|
|
#define CSreg 27
|
|
#define SSreg 28
|
|
#define DSreg 29
|
|
#define ESreg 30
|
|
#define FSreg 31
|
|
#define GSreg 32
|
|
#define ImmB 33
|
|
#define ImmBEnter 34
|
|
#define ImmBS 35
|
|
#define ImmW 36
|
|
#define ImmW1 37
|
|
#define jmpB 38
|
|
#define jmpW 39
|
|
#define memB 40
|
|
#define memW 41
|
|
#define memD 42
|
|
#define indirmodrmW 43
|
|
#define indirFARmodrmW 44
|
|
#define memB1 45
|
|
|
|
|
|
int DmodrmB(LPBYTE);
|
|
int DmodrmW(LPBYTE);
|
|
int Dreg1B(LPBYTE);
|
|
int Dreg1W(LPBYTE);
|
|
int Dreg2B(LPBYTE);
|
|
int Dreg2W(LPBYTE);
|
|
int DeeeControl(LPBYTE);
|
|
int DeeeDebug(LPBYTE);
|
|
int DeeeTest(LPBYTE);
|
|
int DregSeg(LPBYTE);
|
|
int DALreg(LPBYTE);
|
|
int DAHreg(LPBYTE);
|
|
int DBLreg(LPBYTE);
|
|
int DBHreg(LPBYTE);
|
|
int DCLreg(LPBYTE);
|
|
int DCHreg(LPBYTE);
|
|
int DDLreg(LPBYTE);
|
|
int DDHreg(LPBYTE);
|
|
int DAXreg(LPBYTE);
|
|
int DBXreg(LPBYTE);
|
|
int DCXreg(LPBYTE);
|
|
int DDXreg(LPBYTE);
|
|
int DSIreg(LPBYTE);
|
|
int DDIreg(LPBYTE);
|
|
int DSPreg(LPBYTE);
|
|
int DBPreg(LPBYTE);
|
|
int DCSreg(LPBYTE);
|
|
int DSSreg(LPBYTE);
|
|
int DDSreg(LPBYTE);
|
|
int DESreg(LPBYTE);
|
|
int DFSreg(LPBYTE);
|
|
int DGSreg(LPBYTE);
|
|
int DImmB(LPBYTE);
|
|
int DImmBEnter(LPBYTE);
|
|
int DImmBS(LPBYTE);
|
|
int DImmW(LPBYTE);
|
|
int DImmW1(LPBYTE); // immediate-16 for 1-byte instructions
|
|
int DjmpB(LPBYTE);
|
|
int DjmpW(LPBYTE);
|
|
int DmemB(LPBYTE);
|
|
int DmemB1(LPBYTE);
|
|
int DmemW(LPBYTE);
|
|
int DmemD(LPBYTE);
|
|
int DindirmodrmW(LPBYTE);
|
|
int DindirFARmodrmW(LPBYTE);
|
|
|
|
struct {
|
|
int (*pfn)(LPBYTE);
|
|
} rgpfn[] = {
|
|
|
|
0, // 0th entry is reserved
|
|
DmodrmB,
|
|
DmodrmW,
|
|
Dreg1B,
|
|
Dreg1W,
|
|
Dreg2B,
|
|
Dreg2W,
|
|
DeeeControl,
|
|
DeeeDebug,
|
|
DeeeTest,
|
|
DregSeg,
|
|
DALreg,
|
|
DAHreg,
|
|
DBLreg,
|
|
DBHreg,
|
|
DCLreg,
|
|
DCHreg,
|
|
DDLreg,
|
|
DDHreg,
|
|
DAXreg,
|
|
DBXreg,
|
|
DCXreg,
|
|
DDXreg,
|
|
DSIreg,
|
|
DDIreg,
|
|
DSPreg,
|
|
DBPreg,
|
|
DCSreg,
|
|
DSSreg,
|
|
DDSreg,
|
|
DESreg,
|
|
DFSreg,
|
|
DGSreg,
|
|
DImmB,
|
|
DImmBEnter,
|
|
DImmBS,
|
|
DImmW,
|
|
DImmW1, // immediate-16 for 1-byte instructions
|
|
DjmpB,
|
|
DjmpW,
|
|
DmemB,
|
|
DmemW,
|
|
DmemD,
|
|
DindirmodrmW,
|
|
DindirFARmodrmW,
|
|
DmemB1
|
|
};
|
|
|
|
VDMCONTEXT *g_pThreadContext;
|
|
int g_mode;
|
|
char *g_pchOutput; // the disassembled instruction
|
|
char *g_pchExtra; // contents of memory (if any) modified by this instr.
|
|
int prefixes;
|
|
|
|
//NOTE: if first byte = 0x0f, then the instruction is two bytes long
|
|
|
|
char *szRegsB[] = {"al", "cl", "dl", "bl", "ah", "ch", "dh", "bh"};
|
|
char *szRegsW[] = {"ax", "cx", "dx", "bx", "sp", "bp", "si", "di"};
|
|
char *szRegsD[] = {"eax","ecx","edx","ebx","esp","ebp","esi","edi"};
|
|
char *szRegsSeg[] = {"es", "cs", "ss", "ds", "fs", "gs", "(bad)", "(bad)"};
|
|
char *szMod[] = {"[bx+si", "[bx+di", "[bp+si", "[bp+di", "[si", "[di", "[bp", "[bx"};
|
|
|
|
#define PREFIX_REPZ 1
|
|
#define PREFIX_REPNZ 2
|
|
#define PREFIX_LOCK 4
|
|
#define PREFIX_CS 8
|
|
#define PREFIX_SS 0x10
|
|
#define PREFIX_DS 0x20
|
|
#define PREFIX_ES 0x40
|
|
#define PREFIX_FS 0x80
|
|
#define PREFIX_GS 0x100
|
|
#define PREFIX_DATA 0x200
|
|
#define PREFIX_ADR 0x400
|
|
#define PREFIX_FWAIT 0x800
|
|
|
|
#define GROUP_1B -1
|
|
#define GROUP_1WS -2
|
|
#define GROUP_1W -3
|
|
#define GROUP_2B -4
|
|
#define GROUP_2W -5
|
|
#define GROUP_2B_1 -6
|
|
#define GROUP_2W_1 -7
|
|
#define GROUP_2B_CL -8
|
|
#define GROUP_2W_CL -9
|
|
#define GROUP_3B -10
|
|
#define GROUP_3W -11
|
|
#define GROUP_4 -12
|
|
#define GROUP_5 -13
|
|
#define GROUP_6 -14
|
|
#define GROUP_7 -15
|
|
#define GROUP_8 -16
|
|
|
|
#define FLOATCODE -51
|
|
#define FLOAT FLOATCODE
|
|
|
|
// WARNING: This list must remain in sync with the szInstructions[] array
|
|
#define szAdc 1
|
|
#define szAdd 2
|
|
#define szAnd 3
|
|
#define szBad 4
|
|
#define szCmp 5
|
|
#define szDec 6
|
|
#define szIn 7
|
|
#define szInc 8
|
|
#define szJmp 9
|
|
#define szMov 10
|
|
#define szOr 11
|
|
#define szOut 12
|
|
#define szRcl 13
|
|
#define szRcr 14
|
|
#define szRol 15
|
|
#define szRor 16
|
|
#define szSar 17
|
|
#define szSbb 18
|
|
#define szShl 19
|
|
#define szShr 20
|
|
#define szSub 21
|
|
#define szTest 22
|
|
#define szPop 23
|
|
#define szPush 24
|
|
#define szXchg 25
|
|
#define szXor 26
|
|
#define szDaa 27
|
|
#define szDas 28
|
|
#define szPusha 29
|
|
#define szPopa 30
|
|
#define szBound 31
|
|
#define szArpl 32
|
|
#define szAaa 33
|
|
#define szAas 34
|
|
#define szImul 35
|
|
#define szIdiv 36
|
|
#define szJo 37
|
|
#define szJno 38
|
|
#define szJb 39
|
|
#define szJae 40
|
|
#define szJe 41
|
|
#define szJne 42
|
|
#define szJbe 43
|
|
#define szJa 44
|
|
#define szJs 45
|
|
#define szJns 46
|
|
#define szJp 47
|
|
#define szJnp 48
|
|
#define szJl 49
|
|
#define szJnl 50
|
|
#define szJle 51
|
|
#define szJg 52
|
|
#define szNop 53
|
|
#define szLea 54
|
|
#define szCbw 55
|
|
#define szCwd 56
|
|
#define szCall 57
|
|
#define szPushf 58
|
|
#define szPopf 59
|
|
#define szSahf 60
|
|
#define szLahf 61
|
|
#define szMovsb 62
|
|
#define szMovsw 63
|
|
#define szCmpsb 64
|
|
#define szCmpsw 65
|
|
#define szStosb 66
|
|
#define szStosw 67
|
|
#define szLodsb 68
|
|
#define szLodsw 69
|
|
#define szScasb 70
|
|
#define szScasw 71
|
|
#define szRetn 72
|
|
#define szLes 73
|
|
#define szLds 74
|
|
#define szEnter 75
|
|
#define szLeave 76
|
|
#define szRetf 77
|
|
#define szInt3 78
|
|
#define szInt 79
|
|
#define szInto 80
|
|
#define szIret 81
|
|
#define szAam 82
|
|
#define szAad 83
|
|
#define szXlat 84
|
|
#define szLoopne 85
|
|
#define szLoope 86
|
|
#define szLoop 87
|
|
#define szJcxz 88
|
|
#define szHalt 89
|
|
#define szCmc 90
|
|
#define szClc 91
|
|
#define szStc 92
|
|
#define szCli 93
|
|
#define szSti 94
|
|
#define szCld 95
|
|
#define szStd 96
|
|
#define szLar 97
|
|
#define szLsl 98
|
|
#define szClts 99
|
|
#define szSeto 100
|
|
#define szSetno 101
|
|
#define szSetb 102
|
|
#define szSetae 103
|
|
#define szSete 104
|
|
#define szSetne 105
|
|
#define szSetbe 106
|
|
#define szSeta 107
|
|
#define szSets 108
|
|
#define szSetns 109
|
|
#define szSetp 110
|
|
#define szSetnp 111
|
|
#define szSetl 112
|
|
#define szSetge 113
|
|
#define szSetle 114
|
|
#define szSetg 115
|
|
#define szBt 116
|
|
#define szShld 117
|
|
#define szBts 118
|
|
#define szShrd 119
|
|
#define szShdr 120
|
|
#define szLss 121
|
|
#define szBtr 122
|
|
#define szLfs 123
|
|
#define szLgs 124
|
|
#define szMovzx 125
|
|
#define szBtc 126
|
|
#define szBsf 127
|
|
#define szBsr 128
|
|
#define szMovsx 129
|
|
#define szNot 130
|
|
#define szNeg 131
|
|
#define szMul 132
|
|
#define szDiv 133
|
|
#define szSldt 134
|
|
#define szStr 135
|
|
#define szLldt 136
|
|
#define szLtr 137
|
|
#define szVerr 138
|
|
#define szVerw 139
|
|
#define szSgdt 140
|
|
#define szSidt 141
|
|
#define szLgdt 142
|
|
#define szLidt 143
|
|
#define szSmsw 144
|
|
#define szLmsw 145
|
|
|
|
// WARNING: This must stay in sync with the #define list above
|
|
char *szInstructions[] = {
|
|
"", //used to indicate groups
|
|
"adc",
|
|
"add",
|
|
"and",
|
|
"(bad)",
|
|
"cmp",
|
|
"dec",
|
|
"in",
|
|
"inc",
|
|
"jmp",
|
|
// 10
|
|
"mov",
|
|
"or",
|
|
"out",
|
|
"rcl",
|
|
"rcr",
|
|
"rol",
|
|
"ror",
|
|
"sar",
|
|
"sbb",
|
|
"shl",
|
|
// 20
|
|
"shr",
|
|
"sub",
|
|
"test",
|
|
"pop",
|
|
"push",
|
|
"xchg",
|
|
"xor",
|
|
"daa",
|
|
"das",
|
|
"pusha",
|
|
// 30
|
|
"popa",
|
|
"bound",
|
|
"arpl",
|
|
"aaa",
|
|
"aas",
|
|
"imul",
|
|
"idiv",
|
|
"jo",
|
|
"jno",
|
|
"jb",
|
|
// 40
|
|
"jae",
|
|
"je",
|
|
"jne",
|
|
"jbe",
|
|
"ja",
|
|
"js",
|
|
"jns",
|
|
"jp",
|
|
"jnp",
|
|
"jl",
|
|
// 50
|
|
"jnl",
|
|
"jle",
|
|
"jg",
|
|
"nop",
|
|
"lea",
|
|
"cbw",
|
|
"cwd",
|
|
"call",
|
|
"pushf",
|
|
"popf",
|
|
// 60
|
|
"sahf",
|
|
"lahf",
|
|
"movsb",
|
|
"movsw",
|
|
"cmpsb",
|
|
"cmpsw",
|
|
"stosb",
|
|
"stosw",
|
|
"lodsb",
|
|
"lodsw",
|
|
// 70
|
|
"scasb",
|
|
"scasw",
|
|
"retn",
|
|
"les",
|
|
"lds",
|
|
"enter",
|
|
"leave",
|
|
"retf",
|
|
"int3",
|
|
"int",
|
|
// 80
|
|
"into",
|
|
"iret",
|
|
"aam",
|
|
"aad",
|
|
"xlat",
|
|
"loopne",
|
|
"loope",
|
|
"loop",
|
|
"jcxz",
|
|
"halt",
|
|
// 90
|
|
"cmc",
|
|
"clc",
|
|
"stc",
|
|
"cli",
|
|
"sti",
|
|
"cld",
|
|
"std",
|
|
"lar",
|
|
"lsl",
|
|
"clts",
|
|
// 100
|
|
"seto",
|
|
"setno",
|
|
"setb",
|
|
"setae",
|
|
"sete",
|
|
"setne",
|
|
"setbe",
|
|
"seta",
|
|
"sets",
|
|
"setns",
|
|
// 110
|
|
"setp",
|
|
"setnp",
|
|
"setl",
|
|
"setge",
|
|
"setle",
|
|
"setg",
|
|
"bt",
|
|
"shld",
|
|
"bts",
|
|
"shrd",
|
|
// 120
|
|
"shdr",
|
|
"lss",
|
|
"btr",
|
|
"lfs",
|
|
"lgs",
|
|
"movzx",
|
|
"btc",
|
|
"bsf",
|
|
"bsr",
|
|
"movsx",
|
|
// 130
|
|
"not",
|
|
"neg",
|
|
"mul",
|
|
"div",
|
|
"sldt",
|
|
"str",
|
|
"lldt",
|
|
"ltr",
|
|
"verr",
|
|
"verw",
|
|
// 140
|
|
"sgdt",
|
|
"sidt",
|
|
"lgdt",
|
|
"lidt",
|
|
"smsw",
|
|
"lmsw"
|
|
};
|
|
|
|
struct dis {
|
|
int szName;
|
|
char iPart1;
|
|
char iPart2;
|
|
char iPart3;
|
|
};
|
|
|
|
struct dis dis386[] = {
|
|
// 0
|
|
{ szAdd, modrmB, reg1B },
|
|
{ szAdd, modrmW, reg1W },
|
|
{ szAdd, reg1B, modrmB },
|
|
{ szAdd, reg1W, modrmW },
|
|
{ szAdd, ALreg, ImmB },
|
|
{ szAdd, AXreg, ImmW },
|
|
{ szPush, ESreg },
|
|
{ szPop, ESreg},
|
|
// 8
|
|
{ szOr, modrmB, reg1B },
|
|
{ szOr, modrmW, reg1W },
|
|
{ szOr, reg1B, modrmB },
|
|
{ szOr, reg1W, modrmW },
|
|
{ szOr, ALreg, ImmB },
|
|
{ szOr, AXreg, ImmW },
|
|
{ szPush, CSreg },
|
|
{ szBad }, // 0x0f is the 2-byte instr prefix
|
|
// 10
|
|
{ szAdc, modrmB, reg1B },
|
|
{ szAdc, modrmW, reg1W },
|
|
{ szAdc, reg1B, modrmB },
|
|
{ szAdc, reg1W, modrmW },
|
|
{ szAdc, ALreg, ImmB },
|
|
{ szAdc, AXreg, ImmW },
|
|
{ szPush, SSreg },
|
|
{ szPop, SSreg },
|
|
// 18
|
|
{ szSbb, modrmB, reg1B },
|
|
{ szSbb, modrmW, reg1W },
|
|
{ szSbb, reg1B, modrmB },
|
|
{ szSbb, reg1W, modrmW },
|
|
{ szSbb, ALreg, ImmB },
|
|
{ szSbb, AXreg, ImmW },
|
|
{ szPush, DSreg },
|
|
{ szPop, DSreg },
|
|
// 20
|
|
{ szAnd, modrmB, reg1B },
|
|
{ szAnd, modrmW, reg1W },
|
|
{ szAnd, reg1B, modrmB },
|
|
{ szAnd, reg1W, modrmW },
|
|
{ szAnd, ALreg, ImmB },
|
|
{ szAnd, AXreg, ImmW },
|
|
{ szBad }, // ES override prefix
|
|
{ szDaa },
|
|
// 28
|
|
{ szSub, modrmB, reg1B },
|
|
{ szSub, modrmW, reg1W },
|
|
{ szSub, reg1B, modrmB },
|
|
{ szSub, reg1W, modrmW },
|
|
{ szSub, ALreg, ImmB },
|
|
{ szSub, AXreg, ImmW },
|
|
{ szBad }, // CS override prefix
|
|
{ szDas },
|
|
// 30
|
|
{ szXor, modrmB, reg1B },
|
|
{ szXor, modrmW, reg1W },
|
|
{ szXor, reg1B, modrmB },
|
|
{ szXor, reg1W, modrmW },
|
|
{ szXor, ALreg, ImmB },
|
|
{ szXor, AXreg, ImmW },
|
|
{ szBad}, // SS override prefix
|
|
{ szAaa },
|
|
// 38
|
|
{ szCmp, modrmB, reg1B },
|
|
{ szCmp, modrmW, reg1W },
|
|
{ szCmp, reg1B, modrmB },
|
|
{ szCmp, reg1W, modrmW },
|
|
{ szCmp, ALreg, ImmB },
|
|
{ szCmp, AXreg, ImmW },
|
|
{ szBad },
|
|
{ szAas },
|
|
// 40
|
|
{ szInc, AXreg },
|
|
{ szInc, CXreg },
|
|
{ szInc, DXreg },
|
|
{ szInc, BXreg },
|
|
{ szInc, SPreg },
|
|
{ szInc, BPreg },
|
|
{ szInc, SIreg },
|
|
{ szInc, DIreg },
|
|
// 48
|
|
{ szDec, AXreg },
|
|
{ szDec, CXreg },
|
|
{ szDec, DXreg },
|
|
{ szDec, BXreg },
|
|
{ szDec, SPreg },
|
|
{ szDec, BPreg },
|
|
{ szDec, SIreg },
|
|
{ szDec, DIreg },
|
|
// 50
|
|
{ szPush, AXreg },
|
|
{ szPush, CXreg },
|
|
{ szPush, DXreg },
|
|
{ szPush, BXreg },
|
|
{ szPush, SPreg },
|
|
{ szPush, BPreg },
|
|
{ szPush, SIreg },
|
|
{ szPush, DIreg },
|
|
// 58
|
|
{ szPop, AXreg },
|
|
{ szPop, CXreg },
|
|
{ szPop, DXreg },
|
|
{ szPop, BXreg },
|
|
{ szPop, SPreg },
|
|
{ szPop, BPreg },
|
|
{ szPop, SIreg },
|
|
{ szPop, DIreg },
|
|
// 60
|
|
{ szPusha },
|
|
{ szPopa },
|
|
{ szBound, reg1W, modrmW },
|
|
{ szArpl, reg1W, reg2W },
|
|
{ szBad }, // FS segment override
|
|
{ szBad }, // GS segment override
|
|
{ szBad }, // op size prefix
|
|
{ szBad }, // addr size prefix
|
|
// 68
|
|
{ szPush, ImmW},
|
|
{ szImul, reg1W, modrmW },
|
|
{ szPush, ImmBS},
|
|
{ szImul, reg1B, modrmB },
|
|
{ szIn, ImmB, DXreg },
|
|
{ szIn, ImmW, DXreg },
|
|
{ szOut, ImmB, DXreg },
|
|
{ szOut, ImmW, DXreg },
|
|
// 70
|
|
{ szJo, jmpB },
|
|
{ szJno, jmpB },
|
|
{ szJb, jmpB },
|
|
{ szJae, jmpB },
|
|
{ szJe, jmpB },
|
|
{ szJne, jmpB },
|
|
{ szJbe, jmpB },
|
|
{ szJa, jmpB },
|
|
// 78
|
|
{ szJs, jmpB },
|
|
{ szJns, jmpB },
|
|
{ szJp, jmpB },
|
|
{ szJnp, jmpB },
|
|
{ szJl, jmpB },
|
|
{ szJnl, jmpB },
|
|
{ szJle, jmpB },
|
|
{ szJg, jmpB },
|
|
// 80
|
|
{ GROUP_1B },
|
|
{ GROUP_1W },
|
|
{ szBad },
|
|
{ GROUP_1WS },
|
|
{ szTest, reg1B, modrmB },
|
|
{ szTest, reg1W, modrmW },
|
|
{ szXchg, reg1B, modrmB },
|
|
{ szXchg, reg1W, modrmW },
|
|
// 88
|
|
{ szMov, modrmB, reg1B },
|
|
{ szMov, modrmW, reg1W },
|
|
{ szMov, reg1B, modrmB },
|
|
{ szMov, reg1W, modrmW },
|
|
{ szMov, modrmW, regSeg },
|
|
{ szLea, reg1W, modrmW },
|
|
{ szMov, regSeg, modrmW },
|
|
{ szPop, modrmW },
|
|
// 90
|
|
{ szNop },
|
|
{ szXchg, AXreg, CXreg },
|
|
{ szXchg, AXreg, DXreg },
|
|
{ szXchg, AXreg, BXreg },
|
|
{ szXchg, AXreg, SPreg },
|
|
{ szXchg, AXreg, BPreg },
|
|
{ szXchg, AXreg, SIreg },
|
|
{ szXchg, AXreg, DIreg },
|
|
// 98
|
|
{ szCbw },
|
|
{ szCwd },
|
|
{ szCall, memD },
|
|
{ szBad },
|
|
{ szPushf },
|
|
{ szPopf },
|
|
{ szSahf },
|
|
{ szLahf },
|
|
// a0
|
|
{ szMov, ALreg, memB },
|
|
{ szMov, AXreg, memW },
|
|
{ szMov, memB, ALreg },
|
|
{ szMov, memW, AXreg },
|
|
{ szMovsb },
|
|
{ szMovsw },
|
|
{ szCmpsb },
|
|
{ szCmpsw },
|
|
// a8
|
|
{ szTest, ALreg, ImmB },
|
|
{ szTest, AXreg, ImmW },
|
|
{ szStosb },
|
|
{ szStosw },
|
|
{ szLodsb },
|
|
{ szLodsw },
|
|
{ szScasb },
|
|
{ szScasw },
|
|
// b0
|
|
{ szMov, ALreg, ImmB },
|
|
{ szMov, CLreg, ImmB },
|
|
{ szMov, DLreg, ImmB },
|
|
{ szMov, BLreg, ImmB },
|
|
{ szMov, AHreg, ImmB },
|
|
{ szMov, CHreg, ImmB },
|
|
{ szMov, DHreg, ImmB },
|
|
{ szMov, BHreg, ImmB },
|
|
// b8
|
|
{ szMov, AXreg, ImmW },
|
|
{ szMov, CXreg, ImmW },
|
|
{ szMov, DXreg, ImmW },
|
|
{ szMov, BXreg, ImmW },
|
|
{ szMov, SPreg, ImmW },
|
|
{ szMov, BPreg, ImmW },
|
|
{ szMov, SIreg, ImmW },
|
|
{ szMov, DIreg, ImmW },
|
|
// c0
|
|
{ GROUP_2B },
|
|
{ GROUP_2W },
|
|
{ szRetn, ImmW },
|
|
{ szRetn },
|
|
{ szLes, reg1W, modrmW },
|
|
{ szLds, reg1W, modrmW },
|
|
{ szMov, modrmB, ImmB },
|
|
{ szMov, modrmW, ImmW },
|
|
// c8
|
|
{ szEnter, ImmW, ImmBEnter },
|
|
{ szLeave },
|
|
{ szRetf, ImmW1 },
|
|
{ szRetf },
|
|
{ szInt3 },
|
|
{ szInt, ImmB },
|
|
{ szInto },
|
|
{ szIret },
|
|
// d0
|
|
{ GROUP_2B_1 },
|
|
{ GROUP_2W_1 },
|
|
{ GROUP_2B_CL },
|
|
{ GROUP_2W_CL },
|
|
{ szAam, ImmB },
|
|
{ szAad, ImmB },
|
|
{ szBad },
|
|
{ szXlat },
|
|
// d8
|
|
{ FLOAT },
|
|
{ FLOAT },
|
|
{ FLOAT },
|
|
{ FLOAT },
|
|
{ FLOAT },
|
|
{ FLOAT },
|
|
{ FLOAT },
|
|
{ FLOAT },
|
|
// e0
|
|
{ szLoopne, jmpB },
|
|
{ szLoope, jmpB },
|
|
{ szLoop, jmpB },
|
|
{ szJcxz, jmpB },
|
|
{ szIn, ALreg, memB1 },
|
|
{ szIn, AXreg, memB1 },
|
|
{ szOut, memB1, ALreg },
|
|
{ szOut, memB1, AXreg },
|
|
// e8
|
|
{ szCall, jmpW },
|
|
{ szJmp, jmpW },
|
|
{ szJmp, memD },
|
|
{ szJmp, jmpB },
|
|
{ szIn, ALreg, DXreg },
|
|
{ szIn, AXreg, DXreg },
|
|
{ szOut, DXreg, ALreg },
|
|
{ szOut, DXreg, AXreg },
|
|
// f0
|
|
{ szBad }, // lock prefix
|
|
{ szBad },
|
|
{ szBad }, // repne prefix
|
|
{ szBad }, // repz prefix
|
|
{ szHalt },
|
|
{ szCmc },
|
|
{ GROUP_3B },
|
|
{ GROUP_3W },
|
|
// f8
|
|
{ szClc },
|
|
{ szStc },
|
|
{ szCli },
|
|
{ szSti },
|
|
{ szCld },
|
|
{ szStd },
|
|
{ GROUP_4 },
|
|
{ GROUP_5 },
|
|
};
|
|
|
|
|
|
struct dis dis386_2[] = {
|
|
// 00
|
|
{ GROUP_6 },
|
|
{ GROUP_7 },
|
|
{ szLar, reg1W, modrmW },
|
|
{ szLsl, reg1W, modrmW },
|
|
{ szBad },
|
|
{ szBad },
|
|
{ szClts },
|
|
{ szBad },
|
|
// 08
|
|
{ szBad },
|
|
{ szBad },
|
|
{ szBad },
|
|
{ szBad },
|
|
{ szBad },
|
|
{ szBad },
|
|
{ szBad },
|
|
{ szBad },
|
|
// 10
|
|
{ szBad },
|
|
{ szBad },
|
|
{ szBad },
|
|
{ szBad },
|
|
{ szBad },
|
|
{ szBad },
|
|
{ szBad },
|
|
{ szBad },
|
|
// 18
|
|
{ szBad },
|
|
{ szBad },
|
|
{ szBad },
|
|
{ szBad },
|
|
{ szBad },
|
|
{ szBad },
|
|
{ szBad },
|
|
{ szBad },
|
|
// 20
|
|
{ szMov, reg2W, eeeControl },
|
|
{ szMov, reg2W, eeeDebug },
|
|
{ szMov, eeeControl, reg2W },
|
|
{ szMov, eeeDebug, reg2W },
|
|
{ szMov, reg2W, eeeTest },
|
|
{ szBad },
|
|
{ szMov, eeeTest, reg2W },
|
|
{ szBad },
|
|
// 28
|
|
{ szBad },
|
|
{ szBad },
|
|
{ szBad },
|
|
{ szBad },
|
|
{ szBad },
|
|
{ szBad },
|
|
{ szBad },
|
|
{ szBad },
|
|
// 30
|
|
{ szBad },
|
|
{ szBad },
|
|
{ szBad },
|
|
{ szBad },
|
|
{ szBad },
|
|
{ szBad },
|
|
{ szBad },
|
|
{ szBad },
|
|
// 38
|
|
{ szBad },
|
|
{ szBad },
|
|
{ szBad },
|
|
{ szBad },
|
|
{ szBad },
|
|
{ szBad },
|
|
{ szBad },
|
|
{ szBad },
|
|
// 40
|
|
{ szBad },
|
|
{ szBad },
|
|
{ szBad },
|
|
{ szBad },
|
|
{ szBad },
|
|
{ szBad },
|
|
{ szBad },
|
|
{ szBad },
|
|
// 48
|
|
{ szBad },
|
|
{ szBad },
|
|
{ szBad },
|
|
{ szBad },
|
|
{ szBad },
|
|
{ szBad },
|
|
{ szBad },
|
|
{ szBad },
|
|
// 50
|
|
{ szBad },
|
|
{ szBad },
|
|
{ szBad },
|
|
{ szBad },
|
|
{ szBad },
|
|
{ szBad },
|
|
{ szBad },
|
|
{ szBad },
|
|
// 58
|
|
{ szBad },
|
|
{ szBad },
|
|
{ szBad },
|
|
{ szBad },
|
|
{ szBad },
|
|
{ szBad },
|
|
{ szBad },
|
|
{ szBad },
|
|
// 60
|
|
{ szBad },
|
|
{ szBad },
|
|
{ szBad },
|
|
{ szBad },
|
|
{ szBad },
|
|
{ szBad },
|
|
{ szBad },
|
|
{ szBad },
|
|
// 68
|
|
{ szBad },
|
|
{ szBad },
|
|
{ szBad },
|
|
{ szBad },
|
|
{ szBad },
|
|
{ szBad },
|
|
{ szBad },
|
|
{ szBad },
|
|
// 70
|
|
{ szBad },
|
|
{ szBad },
|
|
{ szBad },
|
|
{ szBad },
|
|
{ szBad },
|
|
{ szBad },
|
|
{ szBad },
|
|
{ szBad },
|
|
// 78
|
|
{ szBad },
|
|
{ szBad },
|
|
{ szBad },
|
|
{ szBad },
|
|
{ szBad },
|
|
{ szBad },
|
|
{ szBad },
|
|
{ szBad },
|
|
// 80
|
|
{ szJo, jmpW },
|
|
{ szJno, jmpW },
|
|
{ szJb, jmpW },
|
|
{ szJae, jmpW },
|
|
{ szJe, jmpW },
|
|
{ szJne, jmpW },
|
|
{ szJbe, jmpW },
|
|
{ szJa, jmpW },
|
|
// 88
|
|
{ szJs, jmpW },
|
|
{ szJns, jmpW },
|
|
{ szJp, jmpW },
|
|
{ szJnp, jmpW },
|
|
{ szJl, jmpW },
|
|
{ szJnl, jmpW },
|
|
{ szJle, jmpW },
|
|
{ szJg, jmpW },
|
|
// 90
|
|
{ szSeto, modrmB },
|
|
{ szSetno, modrmB },
|
|
{ szSetb, modrmB },
|
|
{ szSetae, modrmB },
|
|
{ szSete, modrmB },
|
|
{ szSetne, modrmB },
|
|
{ szSetbe, modrmB },
|
|
{ szSeta, modrmB },
|
|
// 98
|
|
{ szSets, modrmB },
|
|
{ szSetns, modrmB },
|
|
{ szSetp, modrmB },
|
|
{ szSetnp, modrmB },
|
|
{ szSetl, modrmB },
|
|
{ szSetge, modrmB },
|
|
{ szSetle, modrmB },
|
|
{ szSetg, modrmB },
|
|
// a0
|
|
{ szPush, FSreg },
|
|
{ szPop, FSreg },
|
|
{ szBad },
|
|
{ szBt, modrmW, reg1W },
|
|
{ szShld, reg1W, modrmW, ImmB },
|
|
{ szShld, reg1W, modrmW, CLreg },
|
|
{ szBad },
|
|
{ szBad },
|
|
// a8
|
|
{ szPush, GSreg },
|
|
{ szPop, GSreg },
|
|
{ szBad },
|
|
{ szBts, modrmW, reg1W },
|
|
{ szShrd, reg1W, modrmW, ImmB },
|
|
{ szShdr, reg1W, modrmW, CLreg },
|
|
{ szBad },
|
|
{ szImul, reg1W, modrmW },
|
|
// b0
|
|
{ szBad },
|
|
{ szBad },
|
|
{ szLss, reg1W, modrmW },
|
|
{ szBtr, modrmW, reg1W },
|
|
{ szLfs, reg1W, modrmW },
|
|
{ szLgs, reg1W, modrmW },
|
|
{ szMovzx, reg1B, modrmB },
|
|
{ szMovzx, reg1W, modrmW },
|
|
// b8
|
|
{ szBad },
|
|
{ szBad },
|
|
{ GROUP_8 },
|
|
{ szBtc, modrmW, reg1W },
|
|
{ szBsf, reg1W, modrmW },
|
|
{ szBsr, reg1W, modrmW },
|
|
{ szMovsx, reg1B, modrmB },
|
|
{ szMovsx, reg1W, modrmW },
|
|
// c0
|
|
{ szBad },
|
|
{ szBad },
|
|
{ szBad },
|
|
{ szBad },
|
|
{ szBad },
|
|
{ szBad },
|
|
{ szBad },
|
|
{ szBad },
|
|
// c8
|
|
{ szBad },
|
|
{ szBad },
|
|
{ szBad },
|
|
{ szBad },
|
|
{ szBad },
|
|
{ szBad },
|
|
{ szBad },
|
|
{ szBad },
|
|
// d0
|
|
{ szBad },
|
|
{ szBad },
|
|
{ szBad },
|
|
{ szBad },
|
|
{ szBad },
|
|
{ szBad },
|
|
{ szBad },
|
|
{ szBad },
|
|
// d8
|
|
{ szBad },
|
|
{ szBad },
|
|
{ szBad },
|
|
{ szBad },
|
|
{ szBad },
|
|
{ szBad },
|
|
{ szBad },
|
|
{ szBad },
|
|
// e0
|
|
{ szBad },
|
|
{ szBad },
|
|
{ szBad },
|
|
{ szBad },
|
|
{ szBad },
|
|
{ szBad },
|
|
{ szBad },
|
|
{ szBad },
|
|
// e8
|
|
{ szBad },
|
|
{ szBad },
|
|
{ szBad },
|
|
{ szBad },
|
|
{ szBad },
|
|
{ szBad },
|
|
{ szBad },
|
|
{ szBad },
|
|
// f0
|
|
{ szBad },
|
|
{ szBad },
|
|
{ szBad },
|
|
{ szBad },
|
|
{ szBad },
|
|
{ szBad },
|
|
{ szBad },
|
|
{ szBad },
|
|
// f8
|
|
{ szBad },
|
|
{ szBad },
|
|
{ szBad },
|
|
{ szBad },
|
|
{ szBad },
|
|
{ szBad },
|
|
{ szBad },
|
|
{ szBad },
|
|
};
|
|
|
|
struct dis dis386_groups[][8] = {
|
|
// GROUP_1B
|
|
{
|
|
{ szAdd, modrmB, ImmB },
|
|
{ szOr, modrmB, ImmB },
|
|
{ szAdc, modrmB, ImmB },
|
|
{ szSbb, modrmB, ImmB },
|
|
{ szAnd, modrmB, ImmB },
|
|
{ szSub, modrmB, ImmB },
|
|
{ szXor, modrmB, ImmB },
|
|
{ szCmp, modrmB, ImmB }
|
|
},
|
|
// GROUP_1WS
|
|
{
|
|
{ szAdd, modrmW, ImmBS },
|
|
{ szOr, modrmW, ImmBS },
|
|
{ szAdc, modrmW, ImmBS },
|
|
{ szSbb, modrmW, ImmBS },
|
|
{ szAnd, modrmW, ImmBS },
|
|
{ szSub, modrmW, ImmBS },
|
|
{ szXor, modrmW, ImmBS },
|
|
{ szCmp, modrmW, ImmBS }
|
|
},
|
|
// GROUP_1W
|
|
{
|
|
{ szAdd, modrmW, ImmW },
|
|
{ szOr, modrmW, ImmW },
|
|
{ szAdc, modrmW, ImmW },
|
|
{ szSbb, modrmW, ImmW },
|
|
{ szAnd, modrmW, ImmW },
|
|
{ szSub, modrmW, ImmW },
|
|
{ szXor, modrmW, ImmW },
|
|
{ szCmp, modrmW, ImmW }
|
|
},
|
|
// GROUP_2B
|
|
{
|
|
{ szRol, modrmB, ImmB },
|
|
{ szRor, modrmB, ImmB },
|
|
{ szRcl, modrmB, ImmB },
|
|
{ szRcr, modrmB, ImmB },
|
|
{ szShl, modrmB, ImmB },
|
|
{ szShr, modrmB, ImmB },
|
|
{ szBad },
|
|
{ szSar, modrmB, ImmB }
|
|
},
|
|
// GROUP_2W
|
|
{
|
|
{ szRol, modrmW, ImmB },
|
|
{ szRor, modrmW, ImmB },
|
|
{ szRcl, modrmW, ImmB },
|
|
{ szRcr, modrmW, ImmB },
|
|
{ szShl, modrmW, ImmB },
|
|
{ szShr, modrmW, ImmB },
|
|
{ szBad },
|
|
{ szSar, modrmW, ImmB }
|
|
},
|
|
// GROUP_2B_1
|
|
{
|
|
{ szRol, modrmB },
|
|
{ szRor, modrmB },
|
|
{ szRcl, modrmB },
|
|
{ szRcr, modrmB },
|
|
{ szShl, modrmB },
|
|
{ szShr, modrmB },
|
|
{ szBad },
|
|
{ szSar, modrmB }
|
|
},
|
|
// GROUP_2W_1
|
|
{
|
|
{ szRol, modrmW },
|
|
{ szRor, modrmW },
|
|
{ szRcl, modrmW },
|
|
{ szRcr, modrmW },
|
|
{ szShl, modrmW },
|
|
{ szShr, modrmW },
|
|
{ szBad },
|
|
{ szSar, modrmW }
|
|
},
|
|
// GROUP_2B_CL
|
|
{
|
|
{ szRol, modrmB, CLreg },
|
|
{ szRor, modrmB, CLreg },
|
|
{ szRcl, modrmB, CLreg },
|
|
{ szRcr, modrmB, CLreg },
|
|
{ szShl, modrmB, CLreg },
|
|
{ szShr, modrmB, CLreg },
|
|
{ szBad },
|
|
{ szSar, modrmB, CLreg }
|
|
},
|
|
// GROUP_2W_CL
|
|
{
|
|
{ szRol, modrmW, CLreg },
|
|
{ szRor, modrmW, CLreg },
|
|
{ szRcl, modrmW, CLreg },
|
|
{ szRcr, modrmW, CLreg },
|
|
{ szShl, modrmW, CLreg },
|
|
{ szShr, modrmW, CLreg },
|
|
{ szBad },
|
|
{ szSar, modrmW, CLreg }
|
|
},
|
|
// GROUP_3B
|
|
{
|
|
{ szTest, modrmB, ImmB },
|
|
{ szBad },
|
|
{ szNot, modrmB },
|
|
{ szNeg, modrmB },
|
|
{ szMul, ALreg, modrmB },
|
|
{ szImul, ALreg, modrmB },
|
|
{ szDiv, ALreg, modrmB },
|
|
{ szIdiv, ALreg, modrmB }
|
|
},
|
|
// GROUP_3W
|
|
{
|
|
{ szTest, modrmW, ImmW },
|
|
{ szBad },
|
|
{ szNot, modrmW },
|
|
{ szNeg, modrmW },
|
|
{ szMul, AXreg, modrmW },
|
|
{ szImul, AXreg, modrmW },
|
|
{ szDiv, AXreg, modrmW },
|
|
{ szIdiv, AXreg, modrmW }
|
|
},
|
|
// GROUP_4
|
|
{
|
|
{ szInc, modrmB },
|
|
{ szDec, modrmB },
|
|
{ szBad },
|
|
{ szBad },
|
|
{ szBad },
|
|
{ szBad },
|
|
{ szBad },
|
|
{ szBad }
|
|
},
|
|
// GROUP_5
|
|
{
|
|
{ szInc, modrmW },
|
|
{ szDec, modrmW },
|
|
{ szCall, indirmodrmW },
|
|
{ szCall, indirFARmodrmW },
|
|
{ szJmp, indirmodrmW },
|
|
{ szJmp, indirFARmodrmW },
|
|
{ szPush, modrmW },
|
|
{ szBad }
|
|
},
|
|
// GROUP_6
|
|
{
|
|
{ szSldt, modrmW },
|
|
{ szStr, modrmW },
|
|
{ szLldt, modrmW },
|
|
{ szLtr, modrmW },
|
|
{ szVerr, modrmW },
|
|
{ szVerw, modrmW },
|
|
{ szBad },
|
|
{ szBad }
|
|
},
|
|
// GROUP_7
|
|
{
|
|
{ szSgdt, modrmW },
|
|
{ szSidt, modrmW },
|
|
{ szLgdt, modrmW },
|
|
{ szLidt, modrmW },
|
|
{ szSmsw, modrmW },
|
|
{ szBad },
|
|
{ szLmsw, modrmW },
|
|
{ szBad }
|
|
},
|
|
// GROUP_8
|
|
{
|
|
{ szBad },
|
|
{ szBad },
|
|
{ szBad },
|
|
{ szBad },
|
|
{ szBt, modrmW, ImmB },
|
|
{ szBts, modrmW, ImmB },
|
|
{ szBtr, modrmW, ImmB },
|
|
{ szBtc, modrmW, ImmB }
|
|
}
|
|
};
|
|
|
|
UCHAR OpcodeSize;
|
|
BYTE *pData;
|
|
ADDR g_InstrAddr;
|
|
BOOL bBig;
|
|
|
|
void AppendString(char *str)
|
|
{
|
|
strcpy(g_pchOutput, (str));
|
|
g_pchOutput+=strlen(g_pchOutput);
|
|
}
|
|
|
|
void ExtraString(char *str)
|
|
{
|
|
strcpy(g_pchExtra, (str));
|
|
g_pchExtra+=strlen(g_pchExtra);
|
|
}
|
|
|
|
#define AppendChar(c) {*g_pchOutput++ = (c);}
|
|
#define AppendNumber(d) {_ultoa((ULONG)d,g_pchOutput, 16); g_pchOutput+=strlen(g_pchOutput);}
|
|
|
|
#define ExtraChar(c) {*g_pchExtra++ = (c);}
|
|
#define ExtraNumber(d) {_ultoa((ULONG)d,g_pchExtra, 16); g_pchExtra+=strlen(g_pchExtra);}
|
|
#define OPERAND_32 ((prefixes & PREFIX_DATA) ^ bBig)
|
|
#define ADDR_32 ((prefixes & PREFIX_ADR) ^ bBig)
|
|
|
|
int unassemble_one(
|
|
BYTE *pInstrStart, // instruction to decode (can be local buffer)
|
|
BOOL bDefaultBig,
|
|
WORD wInstrSeg, // selector of instruction
|
|
DWORD dwInstrOff, // offset of instruction
|
|
char *pchOutput, // [out] disassembled instruction
|
|
char *pchExtra, // [out] extra info (ie. "es:[53]=1234")
|
|
// (can be NULL)
|
|
VDMCONTEXT *pThreadContext,
|
|
int mode
|
|
) {
|
|
int i;
|
|
int cb;
|
|
BYTE *pInstr = pInstrStart;
|
|
struct dis *pszDecode;
|
|
|
|
g_pThreadContext = pThreadContext;
|
|
g_mode = mode;
|
|
|
|
g_pchOutput = pchOutput;
|
|
g_InstrAddr.sSeg = wInstrSeg;
|
|
g_InstrAddr.sOff = dwInstrOff;
|
|
bBig = bDefaultBig;
|
|
|
|
gMode = mode;
|
|
gSelector = wInstrSeg;
|
|
gOffset = dwInstrOff;
|
|
|
|
if (pchExtra)
|
|
*pchExtra = '\0';
|
|
|
|
g_pchExtra = pchExtra;
|
|
|
|
if (*(UNALIGNED USHORT*)pInstr == 0xc4c4) {
|
|
pData = pInstr;
|
|
pData+=2;
|
|
return DisplayBOP();
|
|
}
|
|
|
|
pInstr = checkprefixes(pInstr);
|
|
|
|
OpcodeSize = 1;
|
|
|
|
if (*pInstr == 0x0f) {
|
|
OpcodeSize++;
|
|
pInstr++;
|
|
pszDecode = &dis386_2[*pInstr];
|
|
} else {
|
|
pszDecode = &dis386[*pInstr];
|
|
}
|
|
|
|
if (prefixes & PREFIX_REPZ)
|
|
AppendString("repz ");
|
|
if (prefixes & PREFIX_REPNZ)
|
|
AppendString("repnz ");
|
|
if (prefixes & PREFIX_LOCK)
|
|
AppendString("lock ");
|
|
if ((prefixes & PREFIX_FWAIT) && ((*pInstr < 0xd8) || (*pInstr > 0xdf))) {
|
|
/* fwait not followed by floating point instruction */
|
|
AppendString("fwait");
|
|
return (1);
|
|
}
|
|
|
|
pInstr++;
|
|
pData = pInstr;
|
|
if (pszDecode->szName < 0) { // found a GROUP_ or FLOAT entry...
|
|
i = (-pszDecode->szName)-1;
|
|
if (pszDecode->szName == FLOATCODE) {
|
|
AppendString("*float* ");
|
|
//Later: mputs("Floating point instructions NYI\n");
|
|
return 1;
|
|
} else {
|
|
pszDecode = &dis386_groups[i][(*pInstr>>3)&7];
|
|
}
|
|
}
|
|
|
|
AppendString(szInstructions[pszDecode->szName]);
|
|
|
|
if (pszDecode->iPart1) {
|
|
|
|
AppendChar('\t');
|
|
|
|
i = (*(rgpfn[pszDecode->iPart1].pfn))(pInstr);
|
|
|
|
if (pszDecode->iPart2) {
|
|
|
|
AppendString(", ");
|
|
i+=(*(rgpfn[pszDecode->iPart2].pfn))(pInstr);
|
|
|
|
if (pszDecode->iPart3) {
|
|
|
|
AppendString(", ");
|
|
i+=(*(rgpfn[pszDecode->iPart3].pfn))(pInstr);
|
|
|
|
}
|
|
}
|
|
|
|
pInstr+=i;
|
|
}
|
|
|
|
AppendChar('\0');
|
|
cb = pInstr - pInstrStart; // return length of instruction
|
|
|
|
return cb;
|
|
}
|
|
|
|
BOOL safe_read_byte(
|
|
ADDR addr,
|
|
BYTE *pb
|
|
) {
|
|
ULONG Base;
|
|
|
|
*pb = 0xbb;
|
|
Base = GetInfoFromSelector( addr.sSeg, g_mode, NULL );
|
|
if (Base == (ULONG)-1 || Base == 0) {
|
|
return FALSE;
|
|
}
|
|
|
|
Base += GetIntelBase();
|
|
|
|
return READMEM((LPVOID)(Base+(ULONG)addr.sOff), pb, 1);
|
|
}
|
|
|
|
BOOL safe_read_short(
|
|
ADDR addr,
|
|
SHORT *ps
|
|
) {
|
|
ULONG Base;
|
|
|
|
Base = GetInfoFromSelector( addr.sSeg, g_mode, NULL );
|
|
if (Base == (ULONG)-1 || Base == 0) {
|
|
return FALSE;
|
|
}
|
|
|
|
Base += GetIntelBase();
|
|
|
|
return READMEM((LPVOID)(Base+(ULONG)addr.sOff), ps, 2);
|
|
}
|
|
|
|
BOOL safe_read_long(
|
|
ADDR addr,
|
|
LONG *pl
|
|
) {
|
|
ULONG Base;
|
|
|
|
Base = GetInfoFromSelector( addr.sSeg, g_mode, NULL );
|
|
if (Base == (ULONG)-1 || Base == 0) {
|
|
return FALSE;
|
|
}
|
|
|
|
Base += GetIntelBase();
|
|
|
|
return READMEM((LPVOID)(Base+(ULONG)addr.sOff), pl, 4);
|
|
}
|
|
|
|
|
|
int Dreg1B(LPBYTE lpB)
|
|
{
|
|
BYTE b = (*lpB >> 3) & 7;
|
|
|
|
AppendString(szRegsB[b]);
|
|
|
|
return 0;
|
|
}
|
|
|
|
int Dreg1W(LPBYTE lpB)
|
|
{
|
|
BYTE b = (*lpB >> 3) & 7;
|
|
|
|
if (OPERAND_32)
|
|
AppendString(szRegsD[b]);
|
|
else
|
|
AppendString(szRegsW[b]);
|
|
|
|
return 0;
|
|
}
|
|
|
|
int Dreg2B(LPBYTE lpB)
|
|
{
|
|
BYTE b = *lpB & 7;
|
|
|
|
AppendString(szRegsB[b]);
|
|
|
|
return 0;
|
|
}
|
|
|
|
int Dreg2W(LPBYTE lpB)
|
|
{
|
|
BYTE b = *lpB & 7;
|
|
|
|
if (OPERAND_32)
|
|
AppendString(szRegsD[b]);
|
|
else
|
|
AppendString(szRegsW[b]);
|
|
|
|
return 0;
|
|
}
|
|
|
|
int DmodrmB(LPBYTE lpB)
|
|
{
|
|
BYTE rm = *lpB & 0x07;
|
|
BYTE mod = *lpB >> 6;
|
|
unsigned short num;
|
|
int iRet;
|
|
|
|
pData++; // skip past mod r/m
|
|
if (mod == 3) {
|
|
AppendPrefixes();
|
|
AppendString(szRegsB[rm]);
|
|
return 1;
|
|
}
|
|
|
|
iRet = 0;
|
|
AppendString("byte ptr ");
|
|
AppendPrefixes();
|
|
AppendString(szMod[rm]);
|
|
AppendChar('+');
|
|
|
|
switch (mod) {
|
|
case 0:
|
|
if (rm == 6) {
|
|
g_pchOutput-=3; // back up over the 'BP+'
|
|
num = *((UNALIGNED USHORT*)pData);
|
|
AppendNumber(num);
|
|
pData+=2;
|
|
iRet = 3;
|
|
} else {
|
|
num = 0;
|
|
g_pchOutput--;
|
|
iRet = 1;
|
|
}
|
|
break;
|
|
|
|
case 1:
|
|
num = *pData;
|
|
AppendNumber(num);
|
|
pData++;
|
|
iRet = 2;
|
|
break;
|
|
|
|
case 2:
|
|
num = *((UNALIGNED USHORT*)pData);
|
|
AppendNumber(num);
|
|
pData += 2;
|
|
iRet = 3;
|
|
break;
|
|
}
|
|
|
|
AppendChar(']');
|
|
|
|
DisplayAddress(mod, rm, num, 1);
|
|
|
|
return iRet;
|
|
}
|
|
|
|
int DmodrmW(LPBYTE lpB)
|
|
{
|
|
BYTE rm = *lpB & 0x07;
|
|
BYTE mod = *lpB >> 6;
|
|
ULONG num;
|
|
int iRet;
|
|
|
|
pData++; // skip past mod r/m
|
|
AppendPrefixes();
|
|
|
|
if (mod == 3) {
|
|
if (OPERAND_32)
|
|
AppendString(szRegsD[rm]);
|
|
else
|
|
AppendString(szRegsW[rm]);
|
|
return 1;
|
|
}
|
|
|
|
if (ADDR_32) {
|
|
AppendChar('[');
|
|
AppendString(szRegsD[rm]);
|
|
} else {
|
|
AppendString(szMod[rm]);
|
|
}
|
|
AppendChar('+');
|
|
|
|
switch (mod) {
|
|
case 0:
|
|
//
|
|
// Handle special cases of ModRM
|
|
//
|
|
if ((rm == 6) && !ADDR_32) {
|
|
g_pchOutput-=3; // back up over 'BP+'
|
|
num = *((UNALIGNED USHORT*)pData);
|
|
AppendNumber(num);
|
|
pData+=2;
|
|
iRet = 3;
|
|
} else if ((rm == 5) && ADDR_32) {
|
|
g_pchOutput-=4; // back up over 'EBP+'
|
|
num = *((UNALIGNED ULONG*)pData);
|
|
AppendNumber(num);
|
|
pData+=4;
|
|
iRet = 5;
|
|
} else {
|
|
g_pchOutput--; // else back up over '+' alone
|
|
num=0;
|
|
iRet = 1;
|
|
}
|
|
break;
|
|
|
|
case 1:
|
|
num = *pData;
|
|
AppendNumber(num);
|
|
pData++;
|
|
iRet = 2;
|
|
break;
|
|
|
|
case 2:
|
|
num = *((UNALIGNED USHORT *)pData);
|
|
AppendNumber(num);
|
|
pData+=2;
|
|
iRet = 3;
|
|
break;
|
|
}
|
|
|
|
AppendChar(']');
|
|
|
|
DisplayAddress(mod, rm, num, ADDR_32 ? 4 : 2);
|
|
|
|
return iRet;
|
|
}
|
|
|
|
|
|
void DisplayAddress(int mod, int rm, int sOff, int size)
|
|
{
|
|
ADDR addr;
|
|
|
|
// if caller of unassemble_one() didn't want extra info, return now
|
|
if (g_pchExtra == NULL)
|
|
return;
|
|
|
|
// no memory reference
|
|
if (mod == 3)
|
|
return;
|
|
|
|
// display prefix
|
|
|
|
if (prefixes & PREFIX_DS) {
|
|
ExtraChar('D');
|
|
addr.sSeg = (USHORT)g_pThreadContext->SegDs;
|
|
} else if (prefixes & PREFIX_ES) {
|
|
ExtraChar('E');
|
|
addr.sSeg = (USHORT)g_pThreadContext->SegEs;
|
|
} else if (prefixes & PREFIX_FS) {
|
|
ExtraChar('F');
|
|
addr.sSeg = (USHORT)g_pThreadContext->SegFs;
|
|
} else if (prefixes & PREFIX_GS) {
|
|
ExtraChar('G');
|
|
addr.sSeg = (USHORT)g_pThreadContext->SegGs;
|
|
} else if (prefixes & PREFIX_CS) {
|
|
ExtraChar('C');
|
|
addr.sSeg = (USHORT)g_pThreadContext->SegCs;
|
|
} else if ( (prefixes & PREFIX_SS) || rm==2 || rm == 3) {
|
|
ExtraChar('S');
|
|
addr.sSeg = (USHORT)g_pThreadContext->SegSs;
|
|
} else if (rm == 6 && mod != 0) {
|
|
ExtraChar('S');
|
|
addr.sSeg = (USHORT)g_pThreadContext->SegSs;
|
|
} else {
|
|
ExtraChar('D');
|
|
addr.sSeg = (USHORT)g_pThreadContext->SegDs;
|
|
}
|
|
|
|
ExtraString("S:[");
|
|
|
|
switch (rm) {
|
|
case 0:
|
|
addr.sOff = (USHORT)(g_pThreadContext->Ebx + g_pThreadContext->Esi);
|
|
break;
|
|
|
|
case 1:
|
|
addr.sOff = (USHORT)(g_pThreadContext->Ebx + g_pThreadContext->Edi);
|
|
break;
|
|
|
|
case 2:
|
|
addr.sOff = (USHORT)(g_pThreadContext->Ebp + g_pThreadContext->Esi);
|
|
break;
|
|
|
|
case 3:
|
|
addr.sOff = (USHORT)(g_pThreadContext->Ebp + g_pThreadContext->Edi);
|
|
break;
|
|
|
|
case 4:
|
|
addr.sOff = (USHORT)g_pThreadContext->Esi;
|
|
break;
|
|
|
|
case 5:
|
|
addr.sOff = (USHORT)g_pThreadContext->Edi;
|
|
break;
|
|
|
|
case 6:
|
|
if (mod == 0)
|
|
addr.sOff = 0;
|
|
else
|
|
addr.sOff = (USHORT)g_pThreadContext->Ebp;
|
|
break;
|
|
|
|
default:
|
|
addr.sOff = (USHORT)g_pThreadContext->Ebx;
|
|
|
|
}
|
|
|
|
addr.sOff += sOff;
|
|
ExtraNumber(addr.sOff);
|
|
ExtraString("]=");
|
|
if (size == 2) {
|
|
SHORT s;
|
|
if (safe_read_short(addr, &s)) {
|
|
ExtraNumber( s );
|
|
} else {
|
|
ExtraString("????");
|
|
}
|
|
} else if (size == 1) {
|
|
BYTE b;
|
|
if (safe_read_byte(addr, &b)) {
|
|
ExtraNumber( b );
|
|
} else {
|
|
ExtraString("??");
|
|
}
|
|
} else if (size == 4) {
|
|
LONG l;
|
|
if (safe_read_long(addr, &l)) {
|
|
ExtraNumber( l );
|
|
} else {
|
|
ExtraString("????????");
|
|
}
|
|
} else {
|
|
ExtraString("Unknown size!");
|
|
}
|
|
}
|
|
|
|
int DisplayBOP(void)
|
|
{
|
|
UCHAR mjcode;
|
|
int InstSize = 3;
|
|
|
|
AppendString("BOP ");
|
|
|
|
mjcode = *((UCHAR *)pData);
|
|
pData++;
|
|
AppendNumber(mjcode);
|
|
|
|
switch (mjcode) {
|
|
case 0x50:
|
|
case 0x52:
|
|
case 0x53:
|
|
case 0x54:
|
|
case 0x58:
|
|
//
|
|
// This BOP has a minor function code
|
|
//
|
|
InstSize++;
|
|
AppendString(", ");
|
|
AppendNumber(*((UCHAR *)pData));
|
|
}
|
|
return InstSize;
|
|
}
|
|
|
|
int DALreg(LPBYTE lpB)
|
|
{
|
|
AppendString("al");
|
|
|
|
return 0;
|
|
}
|
|
|
|
int DAHreg(LPBYTE lpB)
|
|
{
|
|
AppendString("ah");
|
|
|
|
return 0;
|
|
}
|
|
|
|
int DBLreg(LPBYTE lpB)
|
|
{
|
|
AppendString("bl");
|
|
|
|
return 0;
|
|
}
|
|
|
|
int DBHreg(LPBYTE lpB)
|
|
{
|
|
AppendString("bh");
|
|
|
|
return 0;
|
|
}
|
|
|
|
int DCLreg(LPBYTE lpB)
|
|
{
|
|
AppendString("cl");
|
|
|
|
return 0;
|
|
}
|
|
|
|
int DCHreg(LPBYTE lpB)
|
|
{
|
|
AppendString("ch");
|
|
|
|
return 0;
|
|
}
|
|
|
|
int DDLreg(LPBYTE lpB)
|
|
{
|
|
AppendString("dl");
|
|
|
|
return 0;
|
|
}
|
|
|
|
int DDHreg(LPBYTE lpB)
|
|
{
|
|
AppendString("dh");
|
|
|
|
return 0;
|
|
}
|
|
|
|
int DAXreg(LPBYTE lpB)
|
|
{
|
|
if (OPERAND_32)
|
|
AppendChar('e');
|
|
|
|
AppendString("ax");
|
|
|
|
return 0;
|
|
}
|
|
|
|
int DBXreg(LPBYTE lpB)
|
|
{
|
|
if (OPERAND_32)
|
|
AppendChar('e');
|
|
|
|
AppendString("bx");
|
|
|
|
return 0;
|
|
}
|
|
|
|
int DCXreg(LPBYTE lpB)
|
|
{
|
|
if (OPERAND_32)
|
|
AppendChar('e');
|
|
|
|
AppendString("cx");
|
|
|
|
return 0;
|
|
}
|
|
|
|
int DDXreg(LPBYTE lpB)
|
|
{
|
|
if (OPERAND_32)
|
|
AppendChar('e');
|
|
|
|
AppendString("dx");
|
|
|
|
return 0;
|
|
}
|
|
|
|
int DBPreg(LPBYTE lpB)
|
|
{
|
|
if (OPERAND_32)
|
|
AppendChar('e');
|
|
|
|
AppendString("bp");
|
|
|
|
return 0;
|
|
}
|
|
|
|
int DSPreg(LPBYTE lpB)
|
|
{
|
|
if (OPERAND_32)
|
|
AppendChar('e');
|
|
|
|
AppendString("sp");
|
|
|
|
return 0;
|
|
}
|
|
|
|
int DSIreg(LPBYTE lpB)
|
|
{
|
|
if (OPERAND_32)
|
|
AppendChar('e');
|
|
|
|
AppendString("si");
|
|
|
|
return 0;
|
|
}
|
|
|
|
int DDIreg(LPBYTE lpB)
|
|
{
|
|
if (OPERAND_32)
|
|
AppendChar('e');
|
|
|
|
AppendString("di");
|
|
|
|
return 0;
|
|
}
|
|
|
|
int DCSreg(LPBYTE lpB)
|
|
{
|
|
AppendString("cs");
|
|
|
|
return 0;
|
|
}
|
|
|
|
int DDSreg(LPBYTE lpB)
|
|
{
|
|
AppendString("ds");
|
|
|
|
return 0;
|
|
}
|
|
|
|
int DSSreg(LPBYTE lpB)
|
|
{
|
|
AppendString("es");
|
|
|
|
return 0;
|
|
}
|
|
|
|
int DESreg(LPBYTE lpB)
|
|
{
|
|
AppendString("es");
|
|
|
|
return 0;
|
|
}
|
|
|
|
int DFSreg(LPBYTE lpB)
|
|
{
|
|
AppendString("fs");
|
|
|
|
return 0;
|
|
}
|
|
|
|
int DGSreg(LPBYTE lpB)
|
|
{
|
|
AppendString("gs");
|
|
|
|
return 0;
|
|
}
|
|
|
|
int DImmB(LPBYTE lpB)
|
|
{
|
|
AppendNumber(*((UCHAR *)pData));
|
|
pData++;
|
|
|
|
return 1;
|
|
}
|
|
|
|
int DImmBEnter(LPBYTE lpB)
|
|
{
|
|
AppendNumber(*((UCHAR *)pData));
|
|
pData++;
|
|
|
|
return 1;
|
|
}
|
|
|
|
int DImmBS(LPBYTE lpB) // sign-extend 8-bit value to 16 bits
|
|
{
|
|
int i = (signed char)*(pData);
|
|
|
|
AppendNumber((USHORT)i);
|
|
pData++;
|
|
|
|
return 1;
|
|
}
|
|
|
|
int DImmW(LPBYTE lpB)
|
|
{
|
|
if (OPERAND_32) {
|
|
|
|
AppendNumber( *((UNALIGNED ULONG*)pData) );
|
|
pData+=4;
|
|
return 4;
|
|
|
|
} else {
|
|
|
|
AppendNumber( *((UNALIGNED USHORT*)pData) );
|
|
pData+=2;
|
|
return 2;
|
|
|
|
}
|
|
}
|
|
|
|
int DImmW1(LPBYTE lpB)
|
|
{
|
|
AppendNumber( *((UNALIGNED SHORT*)(pData)) );
|
|
pData++;
|
|
|
|
return 2;
|
|
}
|
|
|
|
int DjmpB(LPBYTE lpB)
|
|
{
|
|
ULONG Dest = g_InstrAddr.sOff + (LONG)*((UNALIGNED CHAR *)lpB) + OpcodeSize + 1;
|
|
|
|
if (OPERAND_32) {
|
|
AppendNumber(Dest);
|
|
} else {
|
|
AppendNumber((USHORT)Dest);
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
int DjmpW(LPBYTE lpB)
|
|
{
|
|
|
|
if (OPERAND_32) {
|
|
AppendNumber(g_InstrAddr.sOff + *((UNALIGNED ULONG *)lpB) + OpcodeSize + 4);
|
|
return 4;
|
|
} else {
|
|
AppendNumber(LOWORD(g_InstrAddr.sOff + (ULONG)*((UNALIGNED USHORT *)lpB) + OpcodeSize + 2));
|
|
return 2;
|
|
}
|
|
}
|
|
|
|
int DregSeg(LPBYTE lpB)
|
|
{
|
|
BYTE b = (*lpB >> 3) & 7;
|
|
|
|
AppendString(szRegsSeg[b]);
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
int DmemB(LPBYTE lpB)
|
|
{
|
|
ADDR addr;
|
|
|
|
addr.sOff = *(lpB+1);
|
|
|
|
AppendChar('[');
|
|
AppendNumber( addr.sOff );
|
|
AppendChar(']');
|
|
|
|
if (g_pchExtra) {
|
|
BYTE b;
|
|
|
|
if (prefixes & PREFIX_DS) {
|
|
ExtraChar('D');
|
|
addr.sSeg = (USHORT)g_pThreadContext->SegDs;
|
|
} else if (prefixes & PREFIX_ES) {
|
|
ExtraChar('E');
|
|
addr.sSeg = (USHORT)g_pThreadContext->SegEs;
|
|
} else if (prefixes & PREFIX_FS) {
|
|
ExtraChar('F');
|
|
addr.sSeg = (USHORT)g_pThreadContext->SegFs;
|
|
} else if (prefixes & PREFIX_GS) {
|
|
ExtraChar('G');
|
|
addr.sSeg = (USHORT)g_pThreadContext->SegGs;
|
|
} else if (prefixes & PREFIX_CS) {
|
|
ExtraChar('C');
|
|
addr.sSeg = (USHORT)g_pThreadContext->SegCs;
|
|
} else if (prefixes & PREFIX_SS) {
|
|
ExtraChar('S');
|
|
addr.sSeg = (USHORT)g_pThreadContext->SegSs;
|
|
} else {
|
|
ExtraChar('D');
|
|
addr.sSeg = (USHORT)g_pThreadContext->SegDs;
|
|
}
|
|
|
|
ExtraString("S:[");
|
|
ExtraNumber( addr.sOff );
|
|
ExtraString("]=");
|
|
if (safe_read_byte(addr, &b)) {
|
|
ExtraNumber( b );
|
|
} else {
|
|
ExtraString("??");
|
|
}
|
|
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
int DmemB1(LPBYTE lpB)
|
|
{
|
|
AppendNumber( *lpB );
|
|
|
|
return 1;
|
|
}
|
|
|
|
int DmemW(LPBYTE lpB)
|
|
{
|
|
int i;
|
|
ADDR addr;
|
|
|
|
addr.sOff = *(lpB+1);
|
|
|
|
AppendChar('[');
|
|
if (ADDR_32) {
|
|
AppendNumber( *((UNALIGNED long*)lpB) );
|
|
i=4;
|
|
} else {
|
|
addr.sOff = *((UNALIGNED short *)lpB);
|
|
AppendNumber( addr.sOff );
|
|
i=2;
|
|
}
|
|
AppendChar(']');
|
|
|
|
if (g_pchExtra) {
|
|
|
|
if (prefixes & PREFIX_DS) {
|
|
ExtraChar('D');
|
|
addr.sSeg = (USHORT)g_pThreadContext->SegDs;
|
|
} else if (prefixes & PREFIX_ES) {
|
|
ExtraChar('E');
|
|
addr.sSeg = (USHORT)g_pThreadContext->SegEs;
|
|
} else if (prefixes & PREFIX_FS) {
|
|
ExtraChar('F');
|
|
addr.sSeg = (USHORT)g_pThreadContext->SegFs;
|
|
} else if (prefixes & PREFIX_GS) {
|
|
ExtraChar('G');
|
|
addr.sSeg = (USHORT)g_pThreadContext->SegGs;
|
|
} else if (prefixes & PREFIX_CS) {
|
|
ExtraChar('C');
|
|
addr.sSeg = (USHORT)g_pThreadContext->SegCs;
|
|
} else if (prefixes & PREFIX_SS) {
|
|
ExtraChar('S');
|
|
addr.sSeg = (USHORT)g_pThreadContext->SegSs;
|
|
} else {
|
|
ExtraChar('D');
|
|
addr.sSeg = (USHORT)g_pThreadContext->SegDs;
|
|
}
|
|
|
|
ExtraString("S:[");
|
|
ExtraNumber( addr.sOff );
|
|
ExtraString("]=");
|
|
if (i == 2) {
|
|
SHORT s;
|
|
if (safe_read_short(addr, &s)) {
|
|
ExtraNumber( s );
|
|
} else {
|
|
ExtraString( "????" );
|
|
}
|
|
} else {
|
|
LONG l;
|
|
|
|
if (safe_read_long(addr, &l)) {
|
|
ExtraNumber( l );
|
|
} else {
|
|
ExtraString( "????????" );
|
|
}
|
|
}
|
|
}
|
|
|
|
return i;
|
|
}
|
|
|
|
|
|
int DmemD(LPBYTE lpB)
|
|
{
|
|
int i;
|
|
|
|
if (OPERAND_32) {
|
|
AppendNumber( *(((UNALIGNED SHORT*)lpB)+2) );
|
|
AppendChar(':');
|
|
AppendNumber( *((UNALIGNED long*)lpB) );
|
|
i=6;
|
|
} else {
|
|
USHORT sel, off;
|
|
|
|
sel = *(((UNALIGNED SHORT*)lpB)+1);
|
|
off = *((UNALIGNED SHORT*)lpB);
|
|
AppendNumber( sel );
|
|
AppendChar(':');
|
|
AppendNumber( off );
|
|
i=4;
|
|
|
|
if (g_pchExtra) {
|
|
char sym_text[1000];
|
|
LONG dist;
|
|
|
|
// if the exact symbol name was found, print it
|
|
if (FindSymbol( sel,
|
|
off,
|
|
sym_text,
|
|
&dist,
|
|
BEFORE,
|
|
g_mode)) {
|
|
ExtraString("= ");
|
|
ExtraString(sym_text);
|
|
if (dist) {
|
|
ExtraString(" + ");
|
|
ExtraNumber( dist );
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
return i;
|
|
}
|
|
|
|
int DindirmodrmW(LPBYTE lpB)
|
|
{
|
|
int i;
|
|
|
|
AppendString("FAR PTR ");
|
|
i = DmodrmW(lpB);
|
|
AppendChar(']');
|
|
|
|
return i;
|
|
}
|
|
|
|
|
|
int DindirFARmodrmW(LPBYTE lpB)
|
|
{
|
|
int i;
|
|
|
|
AppendString("FAR PTR ");
|
|
i = DmodrmW(lpB);
|
|
AppendChar(']');
|
|
|
|
return i;
|
|
}
|
|
|
|
|
|
int DeeeControl(LPBYTE lpB)
|
|
{
|
|
AppendChar('c');
|
|
AppendChar('r');
|
|
AppendChar('0'+ ((*lpB >> 3) & 7) );
|
|
|
|
return 1;
|
|
}
|
|
|
|
int DeeeDebug(LPBYTE lpB)
|
|
{
|
|
AppendChar('d');
|
|
AppendChar('r');
|
|
AppendChar('0'+ ((*lpB >> 3) & 7) );
|
|
|
|
return 1;
|
|
}
|
|
|
|
int DeeeTest(LPBYTE lpB)
|
|
{
|
|
AppendChar('t');
|
|
AppendChar('r');
|
|
AppendChar('0'+ ((*lpB >> 3) & 7) );
|
|
|
|
return 1;
|
|
}
|
|
|
|
|
|
LPBYTE checkprefixes(LPBYTE lpB)
|
|
{
|
|
prefixes = 0;
|
|
|
|
for (;;) {
|
|
|
|
switch (*lpB) {
|
|
case 0xf3:
|
|
prefixes |= PREFIX_REPZ;
|
|
break;
|
|
case 0xf2:
|
|
prefixes |= PREFIX_REPNZ;
|
|
break;
|
|
case 0xf0:
|
|
prefixes |= PREFIX_LOCK;
|
|
break;
|
|
case 0x2e:
|
|
prefixes |= PREFIX_CS;
|
|
break;
|
|
case 0x36:
|
|
prefixes |= PREFIX_SS;
|
|
break;
|
|
case 0x3e:
|
|
prefixes |= PREFIX_DS;
|
|
break;
|
|
case 0x26:
|
|
prefixes |= PREFIX_ES;
|
|
break;
|
|
case 0x64:
|
|
prefixes |= PREFIX_FS;
|
|
break;
|
|
case 0x65:
|
|
prefixes |= PREFIX_GS;
|
|
break;
|
|
case 0x66:
|
|
prefixes |= PREFIX_DATA;
|
|
break;
|
|
case 0x67:
|
|
prefixes |= PREFIX_ADR;
|
|
break;
|
|
case 0x9b:
|
|
prefixes |= PREFIX_FWAIT;
|
|
break;
|
|
default:
|
|
return lpB;
|
|
}
|
|
lpB++;
|
|
}
|
|
}
|
|
|
|
|
|
void AppendPrefixes(void)
|
|
{
|
|
if (prefixes & PREFIX_CS)
|
|
AppendString("cs:");
|
|
if (prefixes & PREFIX_DS)
|
|
AppendString("ds:");
|
|
if (prefixes & PREFIX_SS)
|
|
AppendString("ss:");
|
|
if (prefixes & PREFIX_ES)
|
|
AppendString("es:");
|
|
if (prefixes & PREFIX_FS)
|
|
AppendString("fs:");
|
|
if (prefixes & PREFIX_GS)
|
|
AppendString("gs:");
|
|
}
|