x86disas.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 969 行 · 第 1/2 页
C
969 行
th = X86T_DOUBLE;
break;
case DRT_X86_QWORD:
th = X86T_QWORD;
break;
case DRT_X86_WORD:
th = X86T_WORD;
break;
case DRT_X86_BYTE:
th = X86T_BYTE;
break;
case DRT_X86_TBYTE:
th = X86T_EXTENDED;
break;
case DRT_X86_FARPTR48:
th = X86T_F32_PTR;
break;
case DRT_X86_FARPTR32:
th = X86T_F16_PTR;
break;
default:
th = X86T_BYTE;
break;
}
addr.sect_id = 0;
addr.indirect = 0;
addr.mach.offset = op->value;
if( op->base != DR_NONE ) {
addr.mach.offset += RegValue( mr, op->base );
}
if( op->index != DR_NONE ) {
addr.mach.offset += RegValue( mr, op->index ) * op->scale;
}
if( op->type & DO_NO_SEG_OVR ) {
addr.mach.segment = RegValue( mr, DR_X86_es );
} else {
addr.mach.segment = RegValue( mr, GetSegRegOverride( dd, op ) );
}
if( dd->ins.flags & DIF_X86_ADDR_LONG ) {
addr.mach.offset &= ~(dword)0;
} else {
addr.mach.offset &= ~(word)0;
}
mmk = MMK_READ;
switch( dd->ins.type ) {
case DI_X86_pop:
case DI_X86_pop2:
case DI_X86_pop3d:
case DI_X86_pop3e:
case DI_X86_pop3s:
case DI_X86_pop4f:
case DI_X86_pop4g:
case DI_X86_ins:
case DI_X86_stos:
mmk = MMK_WRITE;
break;
case DI_X86_xchg:
case DI_X86_xchg2:
case DI_X86_inc:
case DI_X86_inc2:
case DI_X86_dec:
case DI_X86_dec2:
mmk |= MMK_WRITE;
break;
case DI_X86_cmps:
case DI_X86_lods:
case DI_X86_outs:
case DI_X86_scas:
break;
case DI_X86_movzx:
case DI_X86_movsx:
case DI_X86_mov:
case DI_X86_mov2:
case DI_X86_mov3:
case DI_X86_mov4:
case DI_X86_mov5:
case DI_X86_mov6:
case DI_X86_mov7:
case DI_X86_movs:
if( opnd == OP_1 ) {
mmk = MMK_WRITE;
}
break;
default:
if( dd->ins.num_ops >= 2 && opnd == OP_1 ) {
mmk |= MMK_WRITE;
}
break;
}
return( wk( addr, th, mmk, d ) );
}
walk_result DoDisasmMemRefWalk( mad_disasm_data *dd, MEMREF_WALKER *wk, const mad_registers *mr, void *d )
{
walk_result wr;
mad_type_handle th;
int i;
th = (mad_type_handle)-1;
switch( dd->ins.type ) {
case DI_X86_ret:
case DI_X86_ret2:
th = (dd->ins.flags & DIF_X86_OPND_LONG) ? X86T_N32_PTR : X86T_N16_PTR;
break;
case DI_X86_retf:
case DI_X86_retf2:
th = (dd->ins.flags & DIF_X86_OPND_LONG) ? X86T_F32_PTR : X86T_F16_PTR;
break;
case DI_X86_iret:
case DI_X86_iretd:
th = (dd->ins.flags & DIF_X86_OPND_LONG) ? X86T_IRET32 : X86T_IRET16;
break;
case DI_X86_pop:
case DI_X86_pop2:
case DI_X86_pop3d:
case DI_X86_pop3e:
case DI_X86_pop3s:
case DI_X86_pop4f:
case DI_X86_pop4g:
case DI_X86_popf:
case DI_X86_popfd:
case DI_X86_leave:
th = (dd->ins.flags & DIF_X86_OPND_LONG) ? X86T_DWORD : X86T_WORD;
break;
case DI_X86_popa:
case DI_X86_popad:
th = (dd->ins.flags & DIF_X86_OPND_LONG) ? X86T_POPAD : X86T_POPA;
break;
default:
break;
}
if( th != (mad_type_handle)-1 ) {
wr = wk( GetRegSP( mr ), th, MMK_VOLATILE|MMK_IMPLICIT|MMK_READ, d );
if( wr != WR_CONTINUE ) {
return( wr );
}
}
for( i = 0; i < dd->ins.num_ops; i++ ) {
if( ( dd->ins.op[i].type & ( DO_MASK | DO_HIDDEN ) ) == DO_MEMORY_ABS ) {
wr = MemReference( i, dd, wk, mr, d );
if( wr != WR_CONTINUE ) {
return( wr );
}
}
}
return( WR_CONTINUE );
}
struct memref_glue {
MI_MEMREF_WALKER *wk;
void *d;
};
static walk_result MemRefGlue( address a, mad_type_handle th, mad_memref_kind mk, void *d )
{
struct memref_glue *gd = d;
return( gd->wk( a, th, mk, gd->d ) );
}
walk_result DIGENTRY MIDisasmMemRefWalk( mad_disasm_data *dd, MI_MEMREF_WALKER *wk, const mad_registers *mr, void *d )
{
struct memref_glue glue;
glue.wk = wk;
glue.d = d;
return( DoDisasmMemRefWalk( dd, MemRefGlue, mr, &glue ) );
}
const mad_toggle_strings *DIGENTRY MIDisasmToggleList( void )
{
static const mad_toggle_strings list[] = {
{ MSTR_MUPPER, MSTR_UPPER, MSTR_LOWER },
{ MSTR_MINSIDE, MSTR_INSIDE, MSTR_OUTSIDE },
{ MSTR_NIL, MSTR_NIL, MSTR_NIL }
};
return( list );
}
unsigned DIGENTRY MIDisasmToggle( unsigned on, unsigned off )
{
unsigned toggle;
toggle = (on & off);
MADState->disasm_state ^= toggle;
MADState->disasm_state |= on & ~toggle;
MADState->disasm_state &= ~off | toggle;
return( MADState->disasm_state );
}
static int RegAt( char *from, char *reg )
{
unsigned len;
++from;
switch( *from ) {
case 'e':
case 'E':
++from;
}
len = strlen( reg );
if( strnicmp( from, reg, len ) != 0 )
return( 0 );
if( isalnum( from[len] ) || from[len] == '_' )
return( 0 );
return( 1 );
}
static char *StrCopy( const char *s, char *d )
{
for( ;; ) {
*d = *s;
if( *d == '\0' ) break;
++s;
++d;
}
return( d );
}
mad_status DIGENTRY MIDisasmInspectAddr( char *from, unsigned len, unsigned radix, const mad_registers *mr, address *a )
{
char *buff = __alloca( len * 2 );
char *to;
int parens;
mr = mr;
to = buff;
parens = 0;
while( len != 0 ) {
switch( *from ) {
case '[':
*to++ = '+';
*to++ = '(';
if( RegAt( from, "bp" ) || RegAt( from, "sp" ) ) {
to = StrCopy( "ss", to );
} else {
to = StrCopy( "ds", to );
}
to = StrCopy( ":(", to );
break;
case ']':
to = StrCopy( "))", to );
break;
case ':':
to = StrCopy( "):(", to );
++parens;
break;
default:
*to++ = *from;
}
++from;
--len;
}
while( --parens >= 0 ) {
memmove( buff+1, buff, to - buff + 1 );
buff[0] = '(';
++to;
*to++ = ')';
}
return( MCMemExpr( buff, to - buff, radix, a ) );
}
/*
* CnvRadix -- convert an unsigned number of a given radix to a string
*/
char *CnvRadix( unsigned long value, unsigned radix, char base,
char *buff, int len )
{
char internal[ 33 ];
char *ptr;
unsigned dig;
ptr = &internal[ 32 ];
for( ; len > 0 || value != 0; value /= radix ) {
dig = value % radix;
*ptr = (dig <= 9) ? dig + '0' : dig - 10 + base;
--ptr;
--len;
}
len = &internal[32] - ptr;
memcpy( buff, ptr + 1, len );
buff[ len ] = '\0';
return( buff + len );
}
/****************** DISASSEMBLER INTERFACE **************************************/
/*
* JmpLabel -- process a label
*/
char *JmpLabel( unsigned long addr, addr_off off )
{
address memaddr;
mad_type_handle th;
char *p;
memaddr = DbgAddr;
memaddr.mach.offset = addr;
th = ( BIG_SEG( memaddr ) ) ? X86T_N32_PTR : X86T_N16_PTR;
#define PREFIX_STR "CS:"
#define PREFIX_LEN (sizeof(PREFIX_STR)-1)
p = &ScratchBuff[ PREFIX_LEN ];
if( MCAddrToString( memaddr, th, MLK_CODE, sizeof( ScratchBuff ) - 1 - PREFIX_LEN, p ) != MS_OK ) {
p -= PREFIX_LEN;
memcpy( p, PREFIX_STR, PREFIX_LEN );
}
return( p );
}
/*
* ToSegStr -- convert to segment string
*/
char *ToSegStr( addr_off value, addr_seg seg, addr_off addr )
{
address memaddr;
mad_type_handle th;
memaddr.mach.segment = seg;
memaddr.mach.offset = value;
MCAddrSection( &memaddr );
th = BIG_SEG( memaddr ) ? X86T_F32_PTR : X86T_F16_PTR;
MCAddrToString( memaddr, th, MLK_MEMORY, sizeof( ScratchBuff ) - 1, ScratchBuff );
return( ScratchBuff );
}
static void ReadMem( address a, unsigned s, void *d )
{
if( a.sect_id == Cache.start.sect_id
&& a.mach.segment == Cache.start.mach.segment
&& a.mach.offset >= Cache.start.mach.offset
&& ( a.mach.offset + s ) < ( Cache.start.mach.offset + Cache.len ) ) {
memcpy( d, &Cache.data[a.mach.offset-Cache.start.mach.offset], s );
return;
}
#if 0
InitCache( a, Cache.want );
if( a.sect_id == Cache.start.sect_id
&& a.mach.segment == Cache.start.mach.segment
&& a.mach.offset >= Cache.start.mach.offset
&& (a.mach.offset+s) < (Cache.start.mach.offset+Cache.len) ) {
memcpy( d, &Cache.data[a.mach.offset-Cache.start.mach.offset], s );
return;
}
#endif
MCReadMem( a, s, d );
}
signed_16 GetDataWord( void )
{
signed_16 d;
ReadMem( DbgAddr, sizeof( d ), &d );
DbgAddr.mach.offset += sizeof( d );
return( d );
}
signed_32 GetDataLong( void )
{
signed_32 d;
ReadMem( DbgAddr, sizeof( d ), &d );
DbgAddr.mach.offset += sizeof( d );
return( d );
}
void InitCache( address start, unsigned len )
{
Cache.start = start;
if( len > sizeof( Cache.data ) ) len = sizeof( Cache.data );
Cache.want = len;
Cache.len = MCReadMem( start, len, Cache.data );
}
dis_return DisCliGetData( void *d, unsigned off, unsigned int size, void *data )
{
mad_disasm_data *dd = d;
address addr;
addr = dd->addr;
addr.mach.offset += off;
if( MCReadMem( addr, size, data ) == 0 ) return( DR_FAIL );
return( DR_OK );
}
static int GetValueByteSize( unsigned long value )
{
int size;
for( size = 4; size > 1; size-- ) {
if( value & 0xFF000000 )
break;
value <<= 8;
}
return( size );
}
unsigned DisCliValueString( void *d, dis_dec_ins *ins, unsigned opnd, char *buff )
{
mad_disasm_data *dd = d;
char *p;
unsigned max = 40;
mad_type_info mti;
address val;
dis_operand *op;
int size;
op = &ins->op[opnd];
p = buff;
p[0] = '\0';
val = dd->addr;
switch( op->type & DO_MASK ) {
case DO_IMMED:
switch( op->ref_type ) {
case DRT_X86_BYTE:
size = 1;
break;
case DRT_X86_WORD:
size = 2;
break;
case DRT_X86_DWORD:
case DRT_X86_DWORDF:
size = 4;
break;
default:
size = (ins->flags & DIF_X86_OPND_LONG) ? 4 : 2;
}
MCTypeInfoForHost( MTK_INTEGER, size , &mti );
MCTypeToString( dd->radix, &mti, &op->value, &max, p );
break;
case DO_RELATIVE:
val.mach.offset += op->value;
MCAddrToString( val, (ins->flags & DIF_X86_OPND_LONG) ? X86T_N32_PTR : X86T_N16_PTR , MLK_CODE, max, p );
break;
case DO_ABSOLUTE:
if( op->type & DO_EXTRA ) {
val.mach.offset = op->value;
val.mach.segment = op->extra;
MCAddrToString( val, (ins->flags & DIF_X86_OPND_LONG) ? X86T_F32_PTR : X86T_F16_PTR , MLK_CODE, max, p );
break;
}
/* fall through for LEA instruction */
case DO_MEMORY_ABS:
case DO_MEMORY_REL:
if( op->base == DR_NONE && op->index == DR_NONE ) {
// direct memory address
MCTypeInfoForHost( MTK_INTEGER, (ins->flags & DIF_X86_ADDR_LONG) ? 4 : 2 , &mti );
MCTypeToString( dd->radix, &mti, &op->value, &max, p );
} else if( op->value == 0 ) {
// don't output zero disp in indirect memory address
} else {
// indirect memory address with displacement
if( op->value < 0 ) {
*(p++) = '-';
op->value = - op->value;
}
size = GetValueByteSize( op->value );
MCTypeInfoForHost( MTK_INTEGER, size , &mti );
MCTypeToString( dd->radix, &mti, &op->value, &max, p );
}
break;
}
return( strlen( buff ) );
}
mad_status DisasmInit()
{
if( DisInit( DISCPU_x86, &DH, FALSE ) != DR_OK ) {
return( MS_ERR | MS_FAIL );
}
return( MS_OK );
}
void DisasmFini()
{
DisFini( &DH );
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?