mirror of
https://github.com/reactos/reactos.git
synced 2024-09-09 04:10:19 +00:00
717 lines
28 KiB
C
717 lines
28 KiB
C
/*++
|
|
|
|
Copyright (c) 2000-2001 Goran Devic
|
|
Modified (c) 2001 Klaus P. Gerlicher
|
|
|
|
Module Name:
|
|
|
|
disassembler.c
|
|
|
|
Abstract:
|
|
|
|
line disassembler
|
|
|
|
Environment:
|
|
|
|
LINUX 2.2.X
|
|
Kernel mode only
|
|
|
|
Author:
|
|
|
|
Goran Devic
|
|
|
|
Revision History:
|
|
|
|
17-Mar-2000: Original (Goran Devic)
|
|
26-Apr-2000: Major rewrite, added coprocessor instructions (Goran Devic)
|
|
04-Nov-2000: Modified for LinIce (Goran Devic)
|
|
05-Jan-2001: Modified for pICE (Klaus P. Gerlicher)
|
|
|
|
|
|
Copyright notice:
|
|
|
|
This file may be distributed under the terms of the GNU Public License.
|
|
|
|
--*/
|
|
|
|
/*******************************************************************************
|
|
* Include Files *
|
|
******************************************************************************/
|
|
#include "remods.h"
|
|
#include "precomp.h"
|
|
|
|
#include "disassemblerdata.h" // Include its own data
|
|
|
|
/******************************************************************************
|
|
*
|
|
* This structure is used to pass parameters and options to the
|
|
* line disassembler.
|
|
*
|
|
******************************************************************************/
|
|
typedef struct
|
|
{
|
|
ULONG dwFlags; // Generic flags (described below)
|
|
USHORT wSel; // Selector to use to fetch code
|
|
UCHAR *bpTarget; // Target pointer to disassemble
|
|
UCHAR *szDisasm; // String where to put ascii result
|
|
UCHAR Codes[20]; // Buffer where to store code UCHARs
|
|
|
|
UCHAR bAsciiLen; // Length of the ascii result
|
|
UCHAR bInstrLen; // Instruction lenght in UCHARs
|
|
|
|
int nDisplacement; // Scanner: possible constant displacement
|
|
int nScanEnum; // Scanner: specific flags SCAN_*
|
|
|
|
} TDisassembler;
|
|
|
|
// dwFlags contains a set of boolean flags with the following functionality
|
|
|
|
#define DIS_DATA32 0x0001 // Data size 16/32 bits (0/1)
|
|
#define DIS_GETDATASIZE(flags) ((flags)&DIS_DATA32)
|
|
#define DIS_ADDRESS32 0x0002 // Address size 16/32 bits (0/1)
|
|
#define DIS_GETADDRSIZE(flags) (((flags)&DIS_ADDRESS32)?1:0)
|
|
|
|
#define DIS_SEGOVERRIDE 0x0004 // Default segment has been overriden
|
|
|
|
#define DIS_REP 0x0100 // Return: REP prefix found (followed by..)
|
|
#define DIS_REPNE 0x0200 // Return: REPNE prefix found
|
|
#define DIS_GETREPENUM(flags) (((flags)>>8)&3)
|
|
#define DIS_ILLEGALOP 0x8000 // Return: illegal opcode
|
|
|
|
|
|
/******************************************************************************
|
|
* *
|
|
* Global Variables *
|
|
* *
|
|
******************************************************************************/
|
|
|
|
|
|
/******************************************************************************
|
|
* *
|
|
* External functions (optional) *
|
|
* *
|
|
******************************************************************************/
|
|
|
|
/******************************************************************************
|
|
* *
|
|
* Local Defines, Variables and Macros *
|
|
* *
|
|
******************************************************************************/
|
|
UCHAR GetUCHAR(ULONG addr)
|
|
{
|
|
if(IsAddressValid(addr))
|
|
return *(PUCHAR)addr;
|
|
else
|
|
return 0x82; // INVALID OPCODE
|
|
}
|
|
|
|
static UCHAR GetNextUCHAR(USHORT sel, UCHAR *offset, UCHAR *pCode)
|
|
{
|
|
pCode[0] = GetUCHAR((ULONG) offset + 0) & 0xFF;
|
|
|
|
return( pCode[0] );
|
|
}
|
|
|
|
static USHORT GetNextUSHORT(USHORT sel, UCHAR *offset, UCHAR *pCode)
|
|
{
|
|
pCode[0] = GetUCHAR((ULONG) offset + 0) & 0xFF;
|
|
pCode[1] = GetUCHAR((ULONG) offset + 1) & 0xFF;
|
|
|
|
return( *(USHORT *) pCode );
|
|
}
|
|
|
|
static ULONG GetNextULONG(USHORT sel, UCHAR *offset, UCHAR *pCode)
|
|
{
|
|
pCode[0] = GetUCHAR((ULONG) offset + 0) & 0xFF;
|
|
pCode[1] = GetUCHAR((ULONG) offset + 1) & 0xFF;
|
|
pCode[2] = GetUCHAR((ULONG) offset + 2) & 0xFF;
|
|
pCode[3] = GetUCHAR((ULONG) offset + 3) & 0xFF;
|
|
|
|
return( *(ULONG *) pCode );
|
|
}
|
|
|
|
|
|
#define NEXTUCHAR GetNextUCHAR( pDis->wSel, bpTarget, bpCode); bpCode += 1; bpTarget += 1; bInstrLen += 1
|
|
|
|
#define NEXTUSHORT GetNextUSHORT( pDis->wSel, bpTarget, bpCode); bpCode += 2; bpTarget += 2; bInstrLen += 2
|
|
|
|
#define NEXTULONG GetNextULONG(pDis->wSel, bpTarget, bpCode); bpCode += 4; bpTarget += 4; bInstrLen += 4
|
|
|
|
|
|
/******************************************************************************
|
|
* *
|
|
* Functions *
|
|
* *
|
|
******************************************************************************/
|
|
|
|
/******************************************************************************
|
|
* *
|
|
* UCHAR Disassembler( TDisassembler *pDis ); *
|
|
* *
|
|
*******************************************************************************
|
|
*
|
|
* This is a generic Intel line disassembler.
|
|
*
|
|
* Where:
|
|
* TDisassembler:
|
|
* bpTarget is the address of instruction to disassemble
|
|
* szDisasm is the address of the buffer to print a line into
|
|
* dwFlags contains the default operand and address bits
|
|
* pCode is the address to store code UCHARs (up to 16)
|
|
*
|
|
* Disassembled instruction is stored as an ASCIIZ string pointed by
|
|
* szDisasm pointer (from the pDis structure).
|
|
*
|
|
* Returns:
|
|
* TDisassembler:
|
|
* *szDisasm contains the disassembled instruction string
|
|
* bAsciiLen is set to the length of the printed string
|
|
* bInstrLen is set to instruction length in UCHARs
|
|
* dwFlags - has operand and address size flags adjusted
|
|
* - DIS_ILLEGALOP set if that was illegal instruction
|
|
* UCHAR - instruction length in UCHARs
|
|
*
|
|
******************************************************************************/
|
|
UCHAR Disassembler( TDisassembler *pDis )
|
|
{
|
|
TOpcodeData *p; // Pointer to a current instruction record
|
|
UCHAR *bpTarget; // Pointer to the target code to be disassembled
|
|
UCHAR *bpCode; // Pointer to code UCHARs
|
|
ULONG arg; // Argument counter
|
|
char *sPtr; // Message selection pointer
|
|
int nPos; // Printing position in the output string
|
|
UCHAR *pArg; // Pointer to record where instruction arguments are
|
|
ULONG dwULONG; // Temporary ULONG storage
|
|
USHORT wUSHORT; // Temporary USHORT storage
|
|
UCHAR bUCHAR; // Temporary UCHAR storage
|
|
UCHAR bInstrLen; // Current instruction lenght in UCHARs
|
|
UCHAR bOpcode; // Current opcode that is being disassembled
|
|
UCHAR bSegOverride; // 0 default segment. >0, segment index
|
|
UCHAR bMod=0; // Mod field of the instruction
|
|
UCHAR bReg=0; // Register field of the instruction
|
|
UCHAR bRm=0; // R/M field of the instruction
|
|
UCHAR bW; // Width bit for the register selection
|
|
|
|
UCHAR bSib; // S-I-B UCHAR for the instruction
|
|
UCHAR bSs; // SS field of the s-i-b UCHAR
|
|
UCHAR bIndex; // Index field of the s-i-b UCHAR
|
|
UCHAR bBase; // Base field of the s-i-b UCHAR
|
|
LPSTR pSymbolName; // used to symbolic name of value
|
|
|
|
bInstrLen = 0; // Reset instruction lenght to zero
|
|
bSegOverride = 0; // Set default segment (no override)
|
|
nPos = 0; // Reset printing position
|
|
sPtr = NULL; // Points to no message by default
|
|
bpTarget = pDis->bpTarget; // Set internal pointer to a target address
|
|
bpCode = pDis->Codes; // Set internal pointer to code UCHARs
|
|
|
|
do
|
|
{
|
|
bOpcode = NEXTUCHAR; // Get the first opcode UCHAR from the target address
|
|
p = &Op1[bOpcode]; // Get the address of the instruction record
|
|
|
|
if( p->flags & DIS_SPECIAL )
|
|
{
|
|
// Opcode is one of the special ones, so do what needs to be done there
|
|
|
|
switch( p->name )
|
|
{
|
|
case _EscD8:
|
|
case _EscD9:
|
|
case _EscDA:
|
|
case _EscDB:
|
|
case _EscDC:
|
|
case _EscDD:
|
|
case _EscDE:
|
|
case _EscDF: // Coprocessor escape: UCHARs D8 - DF
|
|
bOpcode = NEXTUCHAR; // Get the modRM UCHAR of the instruction
|
|
|
|
if( bOpcode < 0xC0 )
|
|
{
|
|
// Opcodes 00-BF use Coproc1 table
|
|
|
|
bReg = (bOpcode >> 3) & 7;
|
|
p = &Coproc1[ p->name - _EscD8 ][ bReg ];
|
|
|
|
goto StartInstructionParseMODRM;
|
|
}
|
|
// Opcodes C0-FF use Coproc2 table
|
|
|
|
p = &Coproc2[ p->name - _EscD8 ][ bOpcode - 0xC0 ];
|
|
|
|
goto StartInstructionNoMODRM;
|
|
|
|
case _S_ES: // Segment override
|
|
case _S_CS:
|
|
case _S_SS:
|
|
case _S_DS:
|
|
case _S_FS:
|
|
case _S_GS:
|
|
bSegOverride = p->name - _S_ES + 1;
|
|
continue;
|
|
|
|
case _OPSIZ: // Operand size override - toggle
|
|
pDis->dwFlags ^= DIS_DATA32;
|
|
continue;
|
|
|
|
case _ADSIZ: // Address size override - toggle
|
|
pDis->dwFlags ^= DIS_ADDRESS32;
|
|
continue;
|
|
|
|
case _REPNE: // REPNE/REPNZ prefix
|
|
pDis->dwFlags |= DIS_REPNE;
|
|
continue;
|
|
|
|
case _REP: // REP/REPE/REPZ prefix
|
|
pDis->dwFlags |= DIS_REP;
|
|
continue;
|
|
|
|
case _2BESC: // 2 UCHAR escape code 0x0F
|
|
bOpcode = NEXTUCHAR; // Get the second UCHAR of the instruction
|
|
p = &Op2[bOpcode]; // Get the address of the instruction record
|
|
|
|
if( !(p->flags & DIS_SPECIAL) ) goto StartInstruction;
|
|
if( p->name < _GRP6 ) goto IllegalOpcode;
|
|
|
|
case _GRP1a: // Additional groups of instructions
|
|
case _GRP1b:
|
|
case _GRP1c:
|
|
case _GRP2a:
|
|
case _GRP2b:
|
|
case _GRP2c:
|
|
case _GRP2d:
|
|
case _GRP2e:
|
|
case _GRP2f:
|
|
case _GRP3a:
|
|
case _GRP3b:
|
|
case _GRP4:
|
|
case _GRP5:
|
|
case _GRP6:
|
|
case _GRP7:
|
|
case _GRP8:
|
|
case _GRP9:
|
|
|
|
bOpcode = NEXTUCHAR; // Get the Mod R/M UCHAR whose...
|
|
// bits 3,4,5 select instruction
|
|
|
|
bReg = (bOpcode >> 3) & 7;
|
|
p = &Groups[p->name - _GRP1a][ bReg ];
|
|
|
|
if( !(p->flags & DIS_SPECIAL) ) goto StartInstructionParseMODRM;
|
|
|
|
case _NDEF : // Not defined or illegal opcode
|
|
goto IllegalOpcode;
|
|
|
|
default :; // Should not happen
|
|
}
|
|
}
|
|
else
|
|
goto StartInstruction;
|
|
}
|
|
while( bInstrLen < 15 );
|
|
|
|
IllegalOpcode:
|
|
|
|
nPos += PICE_sprintf( pDis->szDisasm+nPos, "invalid");
|
|
pDis->dwFlags |= DIS_ILLEGALOP;
|
|
|
|
goto DisEnd;
|
|
|
|
StartInstruction:
|
|
|
|
// If this instruction needs additional Mod R/M UCHAR, fetch it
|
|
|
|
if( p->flags & DIS_MODRM )
|
|
{
|
|
// Get the next UCHAR (modR/M bit field)
|
|
bOpcode = NEXTUCHAR;
|
|
|
|
bReg = (bOpcode >> 3) & 7;
|
|
|
|
StartInstructionParseMODRM:
|
|
|
|
// Parse that UCHAR and get mod, reg and rm fields
|
|
bMod = bOpcode >> 6;
|
|
bRm = bOpcode & 7;
|
|
}
|
|
|
|
StartInstructionNoMODRM:
|
|
|
|
// Print the possible repeat prefix followed by the instruction
|
|
|
|
if( p->flags & DIS_COPROC )
|
|
nPos += PICE_sprintf( pDis->szDisasm+nPos, "%-6s ", sCoprocNames[ p->name ]);
|
|
else
|
|
nPos += PICE_sprintf( pDis->szDisasm+nPos, "%s%-6s ",
|
|
sRep[DIS_GETREPENUM(pDis->dwFlags)],
|
|
sNames[ p->name + (DIS_GETNAMEFLAG(p->flags) & DIS_GETDATASIZE(pDis->dwFlags)) ] );
|
|
|
|
// Do instruction argument processing, up to 3 times
|
|
|
|
pArg = &p->dest;
|
|
|
|
for( arg=p->args; arg!=0; arg--, pArg++, arg? nPos += PICE_sprintf( pDis->szDisasm+nPos,", ") : 0 )
|
|
{
|
|
switch( *pArg )
|
|
{
|
|
case _Eb : // modR/M used - bW = 0
|
|
bW = 0;
|
|
goto _E;
|
|
|
|
case _Ev : // modR/M used - bW = 1
|
|
bW = 1;
|
|
goto _E;
|
|
|
|
case _Ew : // always USHORT size
|
|
pDis->dwFlags &= ~DIS_DATA32;
|
|
bW = 1;
|
|
goto _E;
|
|
|
|
case _Ms : // fword ptr (sgdt,sidt,lgdt,lidt)
|
|
sPtr = sFwordPtr;
|
|
goto _E1;
|
|
|
|
case _Mq : // qword ptr (cmpxchg8b)
|
|
sPtr = sQwordPtr;
|
|
goto _E1;
|
|
|
|
case _Mp : // 32 or 48 bit pointer (les,lds,lfs,lss,lgs)
|
|
case _Ep : // Always a memory pointer (call, jmp)
|
|
if( pDis->dwFlags & DIS_DATA32 )
|
|
sPtr = sFwordPtr;
|
|
else
|
|
sPtr = sDwordPtr;
|
|
goto _E1;
|
|
|
|
_E:
|
|
// Do registers first so that the rest may be done together
|
|
if( bMod == 3 )
|
|
{
|
|
// Registers depending on the w field and data size
|
|
nPos+=PICE_sprintf(pDis->szDisasm+nPos, "%s", sRegs1[DIS_GETDATASIZE(pDis->dwFlags)][bW][bRm] );
|
|
|
|
break;
|
|
}
|
|
|
|
if( bW==0 )
|
|
sPtr = sBytePtr;
|
|
else
|
|
if( pDis->dwFlags & DIS_DATA32 )
|
|
sPtr = sDwordPtr;
|
|
else
|
|
sPtr = sWordPtr;
|
|
|
|
case _M : // Pure memory pointer (lea,invlpg,floats)
|
|
if( bMod == 3 ) goto IllegalOpcode;
|
|
|
|
_E1:
|
|
|
|
if( sPtr )
|
|
nPos += PICE_sprintf( pDis->szDisasm+nPos, "%s", sPtr );
|
|
|
|
case _Ma : // Used by bound instruction, skip the pointer info
|
|
|
|
// Print the segment if it is overriden
|
|
//
|
|
nPos += PICE_sprintf( pDis->szDisasm+nPos,"%s", sSegOverride[ bSegOverride ] );
|
|
|
|
//
|
|
// Special case when sib UCHAR is present in 32 address encoding
|
|
//
|
|
if( (bRm==4) && (pDis->dwFlags & DIS_ADDRESS32) )
|
|
{
|
|
//
|
|
// Get the s-i-b UCHAR and parse it
|
|
//
|
|
bSib = NEXTUCHAR;
|
|
|
|
bSs = bSib >> 6;
|
|
bIndex = (bSib >> 3) & 7;
|
|
bBase = bSib & 7;
|
|
|
|
// Special case for base=5 && mod==0 -> fetch 32 bit offset
|
|
if( (bBase==5) && (bMod==0) )
|
|
{
|
|
dwULONG = NEXTULONG;
|
|
if(ScanExportsByAddress(&pSymbolName,dwULONG))
|
|
{
|
|
nPos += PICE_sprintf( pDis->szDisasm+nPos,"[%s", pSymbolName );
|
|
}
|
|
else
|
|
{
|
|
nPos += PICE_sprintf( pDis->szDisasm+nPos,"[%08X", (unsigned int) dwULONG );
|
|
}
|
|
}
|
|
else
|
|
nPos += PICE_sprintf( pDis->szDisasm+nPos,"[%s", sGenReg16_32[ 1 ][ bBase ] );
|
|
|
|
// Scaled index, no index if bIndex is 4
|
|
if( bIndex != 4 )
|
|
nPos += PICE_sprintf( pDis->szDisasm+nPos,"+%s%s", sScale[ bSs ], sGenReg16_32[ 1 ][ bIndex ] );
|
|
else
|
|
if(bSs != 0)
|
|
nPos += PICE_sprintf( pDis->szDisasm+nPos,"<INVALID MODE>" );
|
|
|
|
// Offset 8 bit or 32 bit
|
|
if( bMod == 1 )
|
|
{
|
|
bUCHAR = NEXTUCHAR;
|
|
if( (signed char)bUCHAR < 0 )
|
|
nPos += PICE_sprintf( pDis->szDisasm+nPos,"-%02X", 0-(signed char)bUCHAR );
|
|
else
|
|
nPos += PICE_sprintf( pDis->szDisasm+nPos,"+%02X", bUCHAR );
|
|
}
|
|
|
|
if( bMod == 2 )
|
|
{
|
|
dwULONG = NEXTULONG;
|
|
nPos += PICE_sprintf( pDis->szDisasm+nPos,"+%08X", (unsigned int) dwULONG );
|
|
}
|
|
|
|
// Wrap up the instruction
|
|
nPos += PICE_sprintf( pDis->szDisasm+nPos,"]" );
|
|
break;
|
|
}
|
|
|
|
//
|
|
// 16 or 32 address bit cases with mod zero, one or two
|
|
//
|
|
// Special cases when r/m is 5 and mod is 0, immediate d16 or d32
|
|
if( bMod==0 && ((bRm==6 && !(pDis->dwFlags & DIS_ADDRESS32)) || (bRm==5 && (pDis->dwFlags & DIS_ADDRESS32))) )
|
|
{
|
|
if( pDis->dwFlags & DIS_ADDRESS32 )
|
|
{
|
|
dwULONG = NEXTULONG;
|
|
if(ScanExportsByAddress(&pSymbolName,dwULONG))
|
|
nPos += PICE_sprintf( pDis->szDisasm+nPos,"[%s]", pSymbolName );
|
|
else
|
|
nPos += PICE_sprintf( pDis->szDisasm+nPos,"[%08X]", (unsigned int) dwULONG );
|
|
}
|
|
else
|
|
{
|
|
wUSHORT = NEXTUSHORT;
|
|
nPos += PICE_sprintf( pDis->szDisasm+nPos,"[%04X]", wUSHORT );
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
// Print the start of the line
|
|
nPos += PICE_sprintf( pDis->szDisasm+nPos,"[%s", sAdr1[DIS_GETADDRSIZE(pDis->dwFlags)][ bRm ] );
|
|
|
|
// Offset (8 or 16) or (8 or 32) bit - 16, 32 bits are unsigned
|
|
if( bMod==1 )
|
|
{
|
|
bUCHAR = NEXTUCHAR;
|
|
if( (signed char)bUCHAR < 0 )
|
|
nPos += PICE_sprintf( pDis->szDisasm+nPos,"-%02X", 0-(signed char)bUCHAR );
|
|
else
|
|
nPos += PICE_sprintf( pDis->szDisasm+nPos,"+%02X", bUCHAR );
|
|
}
|
|
|
|
if( bMod==2 )
|
|
{
|
|
if( pDis->dwFlags & DIS_ADDRESS32 )
|
|
{
|
|
dwULONG = NEXTULONG;
|
|
nPos += PICE_sprintf( pDis->szDisasm+nPos,"+%08X", (unsigned int) dwULONG );
|
|
}
|
|
else
|
|
{
|
|
wUSHORT = NEXTUSHORT;
|
|
nPos += PICE_sprintf( pDis->szDisasm+nPos,"+%04X", wUSHORT );
|
|
}
|
|
}
|
|
|
|
// Wrap up the instruction
|
|
nPos += PICE_sprintf( pDis->szDisasm+nPos,"]" );
|
|
|
|
break;
|
|
|
|
case _Gb : // general, UCHAR register
|
|
nPos += PICE_sprintf( pDis->szDisasm+nPos, "%s", sRegs1[0][0][ bReg ] );
|
|
break;
|
|
|
|
case _Gv : // general, (d)USHORT register
|
|
nPos += PICE_sprintf( pDis->szDisasm+nPos, "%s", sGenReg16_32[DIS_GETDATASIZE(pDis->dwFlags)][ bReg ] );
|
|
break;
|
|
|
|
case _Yb : // ES:(E)DI pointer
|
|
case _Yv :
|
|
nPos += PICE_sprintf( pDis->szDisasm+nPos, "%s%s", sSegOverrideDefaultES[ bSegOverride ], sYptr[DIS_GETADDRSIZE(pDis->dwFlags)] );
|
|
break;
|
|
|
|
case _Xb : // DS:(E)SI pointer
|
|
case _Xv :
|
|
nPos += PICE_sprintf( pDis->szDisasm+nPos, "%s%s", sSegOverrideDefaultDS[ bSegOverride ], sXptr[DIS_GETADDRSIZE(pDis->dwFlags)] );
|
|
break;
|
|
|
|
case _Rd : // general register double USHORT
|
|
nPos += PICE_sprintf( pDis->szDisasm+nPos, "%s", sGenReg16_32[ 1 ][ bRm ] );
|
|
break;
|
|
|
|
case _Rw : // register USHORT
|
|
nPos += PICE_sprintf( pDis->szDisasm+nPos, "%s", sGenReg16_32[ 0 ][ bMod ] );
|
|
break;
|
|
|
|
case _Sw : // segment register
|
|
nPos += PICE_sprintf( pDis->szDisasm+nPos, "%s", sSeg[ bReg ] );
|
|
break;
|
|
|
|
case _Cd : // control register
|
|
nPos += PICE_sprintf( pDis->szDisasm+nPos, "%s", sControl[ bReg ] );
|
|
break;
|
|
|
|
case _Dd : // debug register
|
|
nPos += PICE_sprintf( pDis->szDisasm+nPos, "%s", sDebug[ bReg ] );
|
|
break;
|
|
|
|
case _Td : // test register
|
|
nPos += PICE_sprintf( pDis->szDisasm+nPos, "%s", sTest[ bReg ] );
|
|
break;
|
|
|
|
|
|
case _Jb : // immediate UCHAR, relative offset
|
|
bUCHAR = NEXTUCHAR;
|
|
nPos += PICE_sprintf( pDis->szDisasm+nPos, "short %08X", (unsigned int)(pDis->bpTarget + (signed char)bUCHAR + bInstrLen) );
|
|
break;
|
|
|
|
case _Jv : // immediate USHORT or ULONG, relative offset
|
|
if( pDis->dwFlags & DIS_DATA32 )
|
|
{
|
|
dwULONG = NEXTULONG;
|
|
if(ScanExportsByAddress(&pSymbolName,(unsigned int)(pDis->bpTarget + (signed long)dwULONG + bInstrLen)))
|
|
nPos += PICE_sprintf( pDis->szDisasm+nPos, "%s", pSymbolName );
|
|
else
|
|
nPos += PICE_sprintf( pDis->szDisasm+nPos, "%08X", (unsigned int)(pDis->bpTarget + (signed long)dwULONG + bInstrLen) );
|
|
}
|
|
else
|
|
{
|
|
wUSHORT = NEXTUSHORT;
|
|
if(ScanExportsByAddress(&pSymbolName,(unsigned int)(pDis->bpTarget + (signed short)wUSHORT + bInstrLen)))
|
|
nPos += PICE_sprintf( pDis->szDisasm+nPos, "%s", pSymbolName );
|
|
else
|
|
nPos += PICE_sprintf( pDis->szDisasm+nPos, "%08X", (unsigned int)(pDis->bpTarget + (signed short)wUSHORT + bInstrLen) );
|
|
}
|
|
break;
|
|
|
|
case _O : // Simple USHORT or ULONG offset
|
|
if( pDis->dwFlags & DIS_ADDRESS32 ) // depending on the address size
|
|
{
|
|
dwULONG = NEXTULONG;
|
|
nPos += PICE_sprintf( pDis->szDisasm+nPos,"%s[%08X]", sSegOverride[ bSegOverride ], (unsigned int) dwULONG );
|
|
}
|
|
else
|
|
{
|
|
wUSHORT = NEXTUSHORT;
|
|
nPos += PICE_sprintf( pDis->szDisasm+nPos,"%s[%04X]", sSegOverride[ bSegOverride ], wUSHORT );
|
|
}
|
|
break;
|
|
|
|
case _Ib : // immediate UCHAR
|
|
bUCHAR = NEXTUCHAR;
|
|
nPos += PICE_sprintf( pDis->szDisasm+nPos,"%02X", bUCHAR );
|
|
break;
|
|
|
|
case _Iv : // immediate USHORT or ULONG
|
|
if( pDis->dwFlags & DIS_DATA32 )
|
|
{
|
|
dwULONG = NEXTULONG;
|
|
nPos += PICE_sprintf( pDis->szDisasm+nPos, "%08X", (unsigned int) dwULONG );
|
|
}
|
|
else
|
|
{
|
|
wUSHORT = NEXTUSHORT;
|
|
nPos += PICE_sprintf( pDis->szDisasm+nPos, "%04X", wUSHORT );
|
|
}
|
|
break;
|
|
|
|
case _Iw : // Immediate USHORT
|
|
wUSHORT = NEXTUSHORT;
|
|
nPos += PICE_sprintf( pDis->szDisasm+nPos, "%04X", wUSHORT );
|
|
break;
|
|
|
|
case _Ap : // 32 bit or 48 bit pointer (call far, jump far)
|
|
if( pDis->dwFlags & DIS_DATA32 )
|
|
{
|
|
dwULONG = NEXTULONG;
|
|
wUSHORT = NEXTUSHORT;
|
|
nPos += PICE_sprintf( pDis->szDisasm+nPos, "%04X:%08X", wUSHORT, (unsigned int) dwULONG );
|
|
}
|
|
else
|
|
{
|
|
dwULONG = NEXTULONG;
|
|
nPos += PICE_sprintf( pDis->szDisasm+nPos, "%08X", (unsigned int) dwULONG );
|
|
}
|
|
break;
|
|
|
|
case _1 : // numerical 1
|
|
nPos += PICE_sprintf( pDis->szDisasm+nPos,"1" );
|
|
break;
|
|
|
|
case _3 : // numerical 3
|
|
nPos += PICE_sprintf( pDis->szDisasm+nPos,"3" );
|
|
break;
|
|
|
|
// Hard coded registers
|
|
case _DX: case _AL: case _AH: case _BL: case _BH: case _CL: case _CH:
|
|
case _DL: case _DH: case _CS: case _DS: case _ES: case _SS: case _FS:
|
|
case _GS:
|
|
nPos += PICE_sprintf( pDis->szDisasm+nPos,"%s", sRegs2[ *pArg - _DX ] );
|
|
break;
|
|
|
|
case _eAX: case _eBX: case _eCX: case _eDX:
|
|
case _eSP: case _eBP: case _eSI: case _eDI:
|
|
nPos += PICE_sprintf( pDis->szDisasm+nPos, "%s", sGenReg16_32[DIS_GETDATASIZE(pDis->dwFlags)][ *pArg - _eAX ]);
|
|
break;
|
|
|
|
case _ST: // Coprocessor ST
|
|
nPos += PICE_sprintf( pDis->szDisasm+nPos,"%s", sST[9] );
|
|
break;
|
|
|
|
case _ST0: // Coprocessor ST(0) - ST(7)
|
|
case _ST1:
|
|
case _ST2:
|
|
case _ST3:
|
|
case _ST4:
|
|
case _ST5:
|
|
case _ST6:
|
|
case _ST7:
|
|
nPos += PICE_sprintf( pDis->szDisasm+nPos,"%s", sST[ *pArg - _ST0 ] );
|
|
break;
|
|
|
|
case _AX: // Coprocessor AX
|
|
nPos += PICE_sprintf( pDis->szDisasm+nPos,"%s", sGenReg16_32[0][0] );
|
|
break;
|
|
}
|
|
}
|
|
|
|
DisEnd:
|
|
|
|
// Set the returning values and return with the bInstrLen field
|
|
|
|
pDis->bAsciiLen = (UCHAR) nPos;
|
|
pDis->bInstrLen = bInstrLen;
|
|
|
|
return bInstrLen;
|
|
}
|
|
|
|
/******************************************************************************
|
|
* *
|
|
* BOOLEAN Disasm(PULONG pOffset,PUCHAR pchDst) *
|
|
* *
|
|
* entry point for disassembly from other modules *
|
|
******************************************************************************/
|
|
BOOLEAN Disasm(PULONG pOffset,PUCHAR pchDst)
|
|
{
|
|
TDisassembler dis;
|
|
|
|
dis.dwFlags = DIS_DATA32 | DIS_ADDRESS32;
|
|
dis.bpTarget = (UCHAR*)*pOffset;
|
|
dis.szDisasm = pchDst;
|
|
dis.wSel = CurrentCS;
|
|
|
|
*pOffset += (ULONG)Disassembler( &dis);
|
|
return TRUE;
|
|
}
|