Windows NT 4.0 source code leak
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1254 lines
36 KiB

/*[
dasm.c
LOCAL CHAR SccsID[]="@(#)dasm386.c 1.14 07/25/94 Copyright Insignia Solutions Ltd.";
Dis-assemble an Intel Instruction
---------------------------------
The possible formats are:-
ssss:oooo 11223344 PRE INST ARGS
ssss:oooo 11223344556677
PRE PRE INST ARGS
ssss:oooo 1122334455667788 INST ARGS
99001122334455
ssss:oooo 1122334455667788
99001122334455
PRE PRE INST ARGS
ssss:oooo 1122334455667788 INST ARGS
etc.
]*/
#include "insignia.h"
#include "host_def.h"
#include "xt.h"
#include <stdio.h>
/* dasm386 forms part of the ccpu386.o (and ccpu386.o) libraries
* used for pigging, and as part of spc.ccpu386.
* When used for pigging the CCPU sas is not available, and will
* cause link errors is "sas_hw_at" is used in this file.
* We #undef CCPU to avoid this problem sogul "sas_xxx" be added
* in this file at a later date.
*/
#ifdef PIG
#undef CCPU
#endif /* PIG */
#include "sas.h"
#define DASM_INTERNAL
#include "decode.h"
#include "dasm.h"
#include "d_oper.h"
#include "d_inst.h"
#include CpuH
/*
The instruction names.
**MUST** be in same order as "d_inst.h".
*/
LOCAL CHAR *inst_name[] =
{
"AAA", /* I_AAA */
"AAD", /* I_AAD */
"AAM", /* I_AAM */
"AAS", /* I_AAS */
"ADC", /* I_ADC8 */
"ADC", /* I_ADC16 */
"ADC", /* I_ADC32 */
"ADD", /* I_ADD8 */
"ADD", /* I_ADD16 */
"ADD", /* I_ADD32 */
"AND", /* I_AND8 */
"AND", /* I_AND16 */
"AND", /* I_AND32 */
"ARPL", /* I_ARPL */
"BOUND", /* I_BOUND16 */
"BOUND", /* I_BOUND32 */
"BSF", /* I_BSF16 */
"BSF", /* I_BSF32 */
"BSR", /* I_BSR16 */
"BSR", /* I_BSR32 */
"BSWAP", /* I_BSWAP */
"BT", /* I_BT16 */
"BT", /* I_BT32 */
"BTC", /* I_BTC16 */
"BTC", /* I_BTC32 */
"BTR", /* I_BTR16 */
"BTR", /* I_BTR32 */
"BTS", /* I_BTS16 */
"BTS", /* I_BTS32 */
"CALLF", /* I_CALLF16 */
"CALLF", /* I_CALLF32 */
"CALLN", /* I_CALLN16 */
"CALLN", /* I_CALLN32 */
"CALLN", /* I_CALLR16 */
"CALLN", /* I_CALLR32 */
"CBW", /* I_CBW */
"CDQ", /* I_CDQ */
"CLC", /* I_CLC */
"CLD", /* I_CLD */
"CLI", /* I_CLI */
"CLTS", /* I_CLTS */
"CMC", /* I_CMC */
"CMP", /* I_CMP8 */
"CMP", /* I_CMP16 */
"CMP", /* I_CMP32 */
"CMPSB", /* I_CMPSB */
"CMPSD", /* I_CMPSD */
"CMPSW", /* I_CMPSW */
"CMPXCHG", /* I_CMPXCHG8 */
"CMPXCHG", /* I_CMPXCHG16 */
"CMPXCHG", /* I_CMPXCHG32 */
"CWD", /* I_CWD */
"CWDE", /* I_CWDE */
"DAA", /* I_DAA */
"DAS", /* I_DAS */
"DEC", /* I_DEC8 */
"DEC", /* I_DEC16 */
"DEC", /* I_DEC32 */
"DIV", /* I_DIV8 */
"DIV", /* I_DIV16 */
"DIV", /* I_DIV32 */
"ENTER", /* I_ENTER16 */
"ENTER", /* I_ENTER32 */
"F2XM1", /* I_F2XM1 */
"FABS", /* I_FABS */
"FADD", /* I_FADD */
"FADDP", /* I_FADDP */
"FBLD", /* I_FBLD */
"FBSTP", /* I_FBSTP */
"FCHS", /* I_FCHS */
"FCLEX", /* I_FCLEX */
"FCOM", /* I_FCOM */
"FCOMP", /* I_FCOMP */
"FCOMPP", /* I_FCOMPP */
"FCOS", /* I_FCOS */
"FDECSTP", /* I_FDECSTP */
"FDIV", /* I_FDIV */
"FDIVP", /* I_FDIVP */
"FDIVR", /* I_FDIVR */
"FDIVRP", /* I_FDIVRP */
"FFREE", /* I_FFREE */
"FFREEP", /* I_FFREEP */
"FIADD", /* I_FIADD */
"FICOM", /* I_FICOM */
"FICOMP", /* I_FICOMP */
"FIDIV", /* I_FIDIV */
"FIDIVR", /* I_FIDIVR */
"FILD", /* I_FILD */
"FIMUL", /* I_FIMUL */
"FINCSTP", /* I_FINCSTP */
"FINIT", /* I_FINIT */
"FIST", /* I_FIST */
"FISTP", /* I_FISTP */
"FISUB", /* I_FISUB */
"FISUBR", /* I_FISUBR */
"FLD", /* I_FLD */
"FLD1", /* I_FLD1 */
"FLDCW", /* I_FLDCW */
"FLDENV", /* I_FLDENV16 */
"FLDENV", /* I_FLDENV32 */
"FLDL2E", /* I_FLDL2E */
"FLDL2T", /* I_FLDL2T */
"FLDLG2", /* I_FLDLG2 */
"FLDLN2", /* I_FLDLN2 */
"FLDPI", /* I_FLDPI */
"FLDZ", /* I_FLDZ */
"FMUL", /* I_FMUL */
"FMULP", /* I_FMULP */
"FNOP", /* I_FNOP */
"FPATAN", /* I_FPATAN */
"FPREM", /* I_FPREM */
"FPREM1", /* I_FPREM1 */
"FPTAN", /* I_FPTAN */
"FRNDINT", /* I_FRNDINT */
"FRSTOR", /* I_FRSTOR16 */
"FRSTOR", /* I_FRSTOR32 */
"FSAVE", /* I_FSAVE16 */
"FSAVE", /* I_FSAVE32 */
"FSCALE", /* I_FSCALE */
"FSETPM", /* I_FSETPM */
"FSIN", /* I_FSIN */
"FSINCOS", /* I_FSINCOS */
"FSQRT", /* I_FSQRT */
"FST", /* I_FST */
"FSTCW", /* I_FSTCW */
"FSTENV", /* I_FSTENV16 */
"FSTENV", /* I_FSTENV32 */
"FSTP", /* I_FSTP */
"FSTSW", /* I_FSTSW */
"FSUB", /* I_FSUB */
"FSUBP", /* I_FSUBP */
"FSUBR", /* I_FSUBR */
"FSUBRP", /* I_FSUBRP */
"FTST", /* I_FTST */
"FUCOM", /* I_FUCOM */
"FUCOMP", /* I_FUCOMP */
"FUCOMPP", /* I_FUCOMPP */
"FXAM", /* I_FXAM */
"FXCH", /* I_FXCH */
"FXTRACT", /* I_FXTRACT */
"FYL2X", /* I_FYL2X */
"FYL2XP1", /* I_FYL2XP1 */
"HLT", /* I_HLT */
"IDIV", /* I_IDIV8 */
"IDIV", /* I_IDIV16 */
"IDIV", /* I_IDIV32 */
"IMUL", /* I_IMUL8 */
"IMUL", /* I_IMUL16 */
"IMUL", /* I_IMUL32 */
"IMUL", /* I_IMUL16T2 */
"IMUL", /* I_IMUL16T3 */
"IMUL", /* I_IMUL32T2 */
"IMUL", /* I_IMUL32T3 */
"IN", /* I_IN8 */
"IN", /* I_IN16 */
"IN", /* I_IN32 */
"INC", /* I_INC8 */
"INC", /* I_INC16 */
"INC", /* I_INC32 */
"INSB", /* I_INSB */
"INSD", /* I_INSD */
"INSW", /* I_INSW */
"INT", /* I_INT3 */
"INT", /* I_INT */
"INTO", /* I_INTO */
"INVD", /* I_INVD */
"INVLPG", /* I_INVLPG */
"IRET", /* I_IRET */
"IRETD", /* I_IRETD */
"JB", /* I_JB16 */
"JB", /* I_JB32 */
"JBE", /* I_JBE16 */
"JBE", /* I_JBE32 */
"JCXZ", /* I_JCXZ */
"JECXZ", /* I_JECXZ */
"JL", /* I_JL16 */
"JL", /* I_JL32 */
"JLE", /* I_JLE16 */
"JLE", /* I_JLE32 */
"JMP", /* I_JMPF16 */
"JMP", /* I_JMPF32 */
"JMP", /* I_JMPN */
"JMP", /* I_JMPR16 */
"JMP", /* I_JMPR32 */
"JNB", /* I_JNB16 */
"JNB", /* I_JNB32 */
"JNBE", /* I_JNBE16 */
"JNBE", /* I_JNBE32 */
"JNL", /* I_JNL16 */
"JNL", /* I_JNL32 */
"JNLE", /* I_JNLE16 */
"JNLE", /* I_JNLE32 */
"JNO", /* I_JNO16 */
"JNO", /* I_JNO32 */
"JNP", /* I_JNP16 */
"JNP", /* I_JNP32 */
"JNS", /* I_JNS16 */
"JNS", /* I_JNS32 */
"JNZ", /* I_JNZ16 */
"JNZ", /* I_JNZ32 */
"JO", /* I_JO16 */
"JO", /* I_JO32 */
"JP", /* I_JP16 */
"JP", /* I_JP32 */
"JS", /* I_JS16 */
"JS", /* I_JS32 */
"JZ", /* I_JZ16 */
"JZ", /* I_JZ32 */
"LAHF", /* I_LAHF */
"LAR", /* I_LAR */
"LDS", /* I_LDS */
"LEA", /* I_LEA */
"LEAVE", /* I_LEAVE16 */
"LEAVE", /* I_LEAVE32 */
"LES", /* I_LES */
"LFS", /* I_LFS */
"LGDT", /* I_LGDT16 */
"LGDT", /* I_LGDT32 */
"LGS", /* I_LGS */
"LIDT", /* I_LIDT16 */
"LIDT", /* I_LIDT32 */
"LLDT", /* I_LLDT */
"LMSW", /* I_LMSW */
"LOADALL", /* I_LOADALL */
"LOCK", /* I_LOCK */
"LODSB", /* I_LODSB */
"LODSD", /* I_LODSD */
"LODSW", /* I_LODSW */
"LOOP", /* I_LOOP16 */
"LOOP", /* I_LOOP32 */
"LOOPE", /* I_LOOPE16 */
"LOOPE", /* I_LOOPE32 */
"LOOPNE", /* I_LOOPNE16 */
"LOOPNE", /* I_LOOPNE32 */
"LSL", /* I_LSL */
"LSS", /* I_LSS */
"LTR", /* I_LTR */
"MOV", /* I_MOV_SR */
"MOV", /* I_MOV_CR */
"MOV", /* I_MOV_DR */
"MOV", /* I_MOV_TR */
"MOV", /* I_MOV8 */
"MOV", /* I_MOV16 */
"MOV", /* I_MOV32 */
"MOVSB", /* I_MOVSB */
"MOVSD", /* I_MOVSD */
"MOVSW", /* I_MOVSW */
"MOVSX", /* I_MOVSX8 */
"MOVSX", /* I_MOVSX16 */
"MOVZX", /* I_MOVZX8 */
"MOVZX", /* I_MOVZX16 */
"MUL", /* I_MUL8 */
"MUL", /* I_MUL16 */
"MUL", /* I_MUL32 */
"NEG", /* I_NEG8 */
"NEG", /* I_NEG16 */
"NEG", /* I_NEG32 */
"NOP", /* I_NOP */
"NOT", /* I_NOT8 */
"NOT", /* I_NOT16 */
"NOT", /* I_NOT32 */
"OR", /* I_OR8 */
"OR", /* I_OR16 */
"OR", /* I_OR32 */
"OUT", /* I_OUT8 */
"OUT", /* I_OUT16 */
"OUT", /* I_OUT32 */
"OUTSB", /* I_OUTSB */
"OUTSD", /* I_OUTSD */
"OUTSW", /* I_OUTSW */
"POP", /* I_POP16 */
"POP", /* I_POP32 */
"POP", /* I_POP_SR */
"POPA", /* I_POPA */
"POPAD", /* I_POPAD */
"POPF", /* I_POPF */
"POPFD", /* I_POPFD */
"PUSH", /* I_PUSH16 */
"PUSH", /* I_PUSH32 */
"PUSHA", /* I_PUSHA */
"PUSHAD", /* I_PUSHAD */
"PUSHF", /* I_PUSHF */
"PUSHFD", /* I_PUSHFD */
"RCL", /* I_RCL8 */
"RCL", /* I_RCL16 */
"RCL", /* I_RCL32 */
"RCR", /* I_RCR8 */
"RCR", /* I_RCR16 */
"RCR", /* I_RCR32 */
"RETF", /* I_RETF16 */
"RETF", /* I_RETF32 */
"RET", /* I_RETN16 */
"RET", /* I_RETN32 */
"ROL", /* I_ROL8 */
"ROL", /* I_ROL16 */
"ROL", /* I_ROL32 */
"ROR", /* I_ROR8 */
"ROR", /* I_ROR16 */
"ROR", /* I_ROR32 */
"REP INSB", /* I_R_INSB */
"REP INSD", /* I_R_INSD */
"REP INSW", /* I_R_INSW */
"REP OUTSB", /* I_R_OUTSB */
"REP OUTSD", /* I_R_OUTSD */
"REP OUTSW", /* I_R_OUTSW */
"REP LODSB", /* I_R_LODSB */
"REP LODSD", /* I_R_LODSD */
"REP LODSW", /* I_R_LODSW */
"REP MOVSB", /* I_R_MOVSB */
"REP MOVSD", /* I_R_MOVSD */
"REP MOVSW", /* I_R_MOVSW */
"REP STOSB", /* I_R_STOSB */
"REP STOSD", /* I_R_STOSD */
"REP STOSW", /* I_R_STOSW */
"REPE CMPSB", /* I_RE_CMPSB */
"REPE CMPSD", /* I_RE_CMPSD */
"REPE CMPSW", /* I_RE_CMPSW */
"REPNE CMPSB", /* I_RNE_CMPSB */
"REPNE CMPSD", /* I_RNE_CMPSD */
"REPNE CMPSW", /* I_RNE_CMPSW */
"REPE SCASB", /* I_RE_SCASB */
"REPE SCASD", /* I_RE_SCASD */
"REPE SCASW", /* I_RE_SCASW */
"REPNE SCASB", /* I_RNE_SCASB */
"REPNE SCASD", /* I_RNE_SCASD */
"REPNE SCASW", /* I_RNE_SCASW */
"SAHF", /* I_SAHF */
"SAR", /* I_SAR8 */
"SAR", /* I_SAR16 */
"SAR", /* I_SAR32 */
"SBB", /* I_SBB8 */
"SBB", /* I_SBB16 */
"SBB", /* I_SBB32 */
"SCASB", /* I_SCASB */
"SCASD", /* I_SCASD */
"SCASW", /* I_SCASW */
"SETB", /* I_SETB */
"SETBE", /* I_SETBE */
"SETL", /* I_SETL */
"SETLE", /* I_SETLE */
"SETNB", /* I_SETNB */
"SETNBE", /* I_SETNBE */
"SETNL", /* I_SETNL */
"SETNLE", /* I_SETNLE */
"SETNO", /* I_SETNO */
"SETNP", /* I_SETNP */
"SETNS", /* I_SETNS */
"SETNZ", /* I_SETNZ */
"SETO", /* I_SETO */
"SETP", /* I_SETP */
"SETS", /* I_SETS */
"SETZ", /* I_SETZ */
"SGDT", /* I_SGDT16 */
"SGDT", /* I_SGDT32 */
"SHL", /* I_SHL8 */
"SHL", /* I_SHL16 */
"SHL", /* I_SHL32 */
"SHLD", /* I_SHLD16 */
"SHLD", /* I_SHLD32 */
"SHR", /* I_SHR8 */
"SHR", /* I_SHR16 */
"SHR", /* I_SHR32 */
"SHRD", /* I_SHRD16 */
"SHRD", /* I_SHRD32 */
"SIDT", /* I_SIDT16 */
"SIDT", /* I_SIDT32 */
"SLDT", /* I_SLDT */
"SMSW", /* I_SMSW */
"STC", /* I_STC */
"STD", /* I_STD */
"STI", /* I_STI */
"STOSB", /* I_STOSB */
"STOSD", /* I_STOSD */
"STOSW", /* I_STOSW */
"STR", /* I_STR */
"SUB", /* I_SUB8 */
"SUB", /* I_SUB16 */
"SUB", /* I_SUB32 */
"TEST", /* I_TEST8 */
"TEST", /* I_TEST16 */
"TEST", /* I_TEST32 */
"VERR", /* I_VERR */
"VERW", /* I_VERW */
"WAIT", /* I_WAIT */
"WBINVD", /* I_WBINVD */
"XADD", /* I_XADD8 */
"XADD", /* I_XADD16 */
"XADD", /* I_XADD32 */
"XCHG", /* I_XCHG8 */
"XCHG", /* I_XCHG16 */
"XCHG", /* I_XCHG32 */
"XLAT", /* I_XLAT */
"XOR", /* I_XOR8 */
"XOR", /* I_XOR16 */
"XOR", /* I_XOR32 */
"????", /* I_ZBADOP */
"BOP", /* I_ZBOP */
"FRSRVD", /* I_ZFRSRVD */
"RSRVD", /* I_ZRSRVD */
"UNSIMULATE" /* I_ZZEXIT */
};
#define NR_VALID_INSTS (sizeof(inst_name)/sizeof(CHAR *))
/*
Character to print before each argument.
*/
LOCAL CHAR arg_preface[] = { ' ', ',', ',' };
/*
Register (byte) names.
*/
LOCAL CHAR *Rb_name[] =
{
"AL", "CL", "DL", "BL", "AH", "CH", "DH", "BH"
};
/*
Register (word) names.
*/
LOCAL CHAR *Rw_name[] =
{
"AX", "CX", "DX", "BX", "SP", "BP", "SI", "DI"
};
/*
Register (double word) names.
*/
LOCAL CHAR *Rd_name[] =
{
"EAX", "ECX", "EDX", "EBX", "ESP", "EBP", "ESI", "EDI"
};
/*
Segment Register (word) names.
*/
LOCAL CHAR *Sw_name[] =
{
"ES", "CS", "SS", "DS", "FS", "GS"
};
/*
Control Register (double word) names.
*/
LOCAL CHAR *Cd_name[] =
{
"CR0", "CR1(UNDEF)", "CR2", "CR3",
"CR4(UNDEF)", "CR5(UNDEF)", "CR6(UNDEF)", "CR7(UNDEF)"
};
/*
Debug Register (double word) names.
*/
LOCAL CHAR *Dd_name[] =
{
"DR0", "DR1", "DR2", "DR3", "DR4(UNDEF)", "DR5(UNDEF)", "DR6", "DR7"
};
/*
Test Register (double word) names.
*/
LOCAL CHAR *Td_name[] =
{
"TR0(UNDEF)", "TR1(UNDEF)", "TR2(UNDEF)", "TR3",
"TR4", "TR5", "TR6", "TR7"
};
/*
Memory Addressing names.
*/
typedef struct
{
CHAR *positive;
CHAR *negative;
ULONG disp_mask;
ULONG sign_mask;
} MEM_RECORD;
LOCAL MEM_RECORD mem_name[] =
{
{ "%s[BX+SI%s]", "%s[BX+SI%s]", 0x00000000, 0x00000000}, /* A_1600 */
{ "%s[BX+DI%s]", "%s[BX+DI%s]", 0x00000000, 0x00000000}, /* A_1601 */
{ "%s[BP+SI%s]", "%s[BP+SI%s]", 0x00000000, 0x00000000}, /* A_1602 */
{ "%s[BP+DI%s]", "%s[BP+DI%s]", 0x00000000, 0x00000000}, /* A_1603 */
{ "%s[SI%s]", "%s[SI%s]", 0x00000000, 0x00000000}, /* A_1604 */
{ "%s[DI%s]", "%s[DI%s]", 0x00000000, 0x00000000}, /* A_1605 */
{ "%s[%s%04x]", "%s[%s%04x]", 0x0000ffff, 0x00000000}, /* A_1606 */
{ "%s[BX%s]", "%s[BX%s]", 0x00000000, 0x00000000}, /* A_1607 */
{ "%s[BX+SI%s+%02x]", "%s[BX+SI%s-%02x]", 0x000000ff, 0x00000080}, /* A_1610 */
{ "%s[BX+DI%s+%02x]", "%s[BX+DI%s-%02x]", 0x000000ff, 0x00000080}, /* A_1611 */
{ "%s[BP+SI%s+%02x]", "%s[BP+SI%s-%02x]", 0x000000ff, 0x00000080}, /* A_1612 */
{ "%s[BP+DI%s+%02x]", "%s[BP+DI%s-%02x]", 0x000000ff, 0x00000080}, /* A_1613 */
{ "%s[SI%s+%02x]", "%s[SI%s-%02x]", 0x000000ff, 0x00000080}, /* A_1614 */
{ "%s[DI%s+%02x]", "%s[DI%s-%02x]", 0x000000ff, 0x00000080}, /* A_1615 */
{ "%s[BP%s+%02x]", "%s[BP%s-%02x]", 0x000000ff, 0x00000080}, /* A_1616 */
{ "%s[BX%s+%02x]", "%s[BX%s-%02x]", 0x000000ff, 0x00000080}, /* A_1617 */
{ "%s[BX+SI%s+%04x]", "%s[BX+SI%s+%04x]", 0x0000ffff, 0x00000000}, /* A_1620 */
{ "%s[BX+DI%s+%04x]", "%s[BX+DI%s+%04x]", 0x0000ffff, 0x00000000}, /* A_1621 */
{ "%s[BP+SI%s+%04x]", "%s[BP+SI%s+%04x]", 0x0000ffff, 0x00000000}, /* A_1622 */
{ "%s[BP+DI%s+%04x]", "%s[BP+DI%s+%04x]", 0x0000ffff, 0x00000000}, /* A_1623 */
{ "%s[SI%s+%04x]", "%s[SI%s+%04x]", 0x0000ffff, 0x00000000}, /* A_1624 */
{ "%s[DI%s+%04x]", "%s[DI%s+%04x]", 0x0000ffff, 0x00000000}, /* A_1625 */
{ "%s[BP%s+%04x]", "%s[BP%s-%04x]", 0x0000ffff, 0x0000f000}, /* A_1626 */
{ "%s[BX%s+%04x]", "%s[BX%s+%04x]", 0x0000ffff, 0x00000000}, /* A_1627 */
{ "%s[EAX%s]", "%s[EAX%s]", 0x00000000, 0x00000000}, /* A_3200 */
{ "%s[ECX%s]", "%s[ECX%s]", 0x00000000, 0x00000000}, /* A_3201 */
{ "%s[EDX%s]", "%s[EDX%s]", 0x00000000, 0x00000000}, /* A_3202 */
{ "%s[EBX%s]", "%s[EBX%s]", 0x00000000, 0x00000000}, /* A_3203 */
{ "%s[%s%08x]", "%s[%s%08x]", 0xffffffff, 0x00000000}, /* A_3205 */
{ "%s[ESI%s]", "%s[ESI%s]", 0x00000000, 0x00000000}, /* A_3206 */
{ "%s[EDI%s]", "%s[EDI%s]", 0x00000000, 0x00000000}, /* A_3207 */
{ "%s[EAX+%s%02x]", "%s[EAX-%s%02x]", 0x000000ff, 0x00000080}, /* A_3210 */
{ "%s[ECX+%s%02x]", "%s[ECX-%s%02x]", 0x000000ff, 0x00000080}, /* A_3211 */
{ "%s[EDX+%s%02x]", "%s[EDX-%s%02x]", 0x000000ff, 0x00000080}, /* A_3212 */
{ "%s[EBX+%s%02x]", "%s[EBX-%s%02x]", 0x000000ff, 0x00000080}, /* A_3213 */
{ "%s[EBP+%s%02x]", "%s[EBP-%s%02x]", 0x000000ff, 0x00000080}, /* A_3215 */
{ "%s[ESI+%s%02x]", "%s[ESI-%s%02x]", 0x000000ff, 0x00000080}, /* A_3216 */
{ "%s[EDI+%s%02x]", "%s[EDI-%s%02x]", 0x000000ff, 0x00000080}, /* A_3217 */
{ "%s[EAX+%s%08x]", "%s[EAX+%s%08x]", 0xffffffff, 0x00000000}, /* A_3220 */
{ "%s[ECX+%s%08x]", "%s[ECX+%s%08x]", 0xffffffff, 0x00000000}, /* A_3221 */
{ "%s[EDX+%s%08x]", "%s[EDX+%s%08x]", 0xffffffff, 0x00000000}, /* A_3222 */
{ "%s[EBX+%s%08x]", "%s[EBX+%s%08x]", 0xffffffff, 0x00000000}, /* A_3223 */
{ "%s[EBP+%s%08x]", "%s[EBP-%s%08x]", 0xffffffff, 0xfff00000}, /* A_3225 */
{ "%s[ESI+%s%08x]", "%s[ESI+%s%08x]", 0xffffffff, 0x00000000}, /* A_3226 */
{ "%s[EDI+%s%08x]", "%s[EDI+%s%08x]", 0xffffffff, 0x00000000}, /* A_3227 */
{ "%s[EAX%s]", "%s[EAX%s]", 0x00000000, 0x00000000}, /* A_32S00 */
{ "%s[ECX%s]", "%s[ECX%s]", 0x00000000, 0x00000000}, /* A_32S01 */
{ "%s[EDX%s]", "%s[EDX%s]", 0x00000000, 0x00000000}, /* A_32S02 */
{ "%s[EBX%s]", "%s[EBX%s]", 0x00000000, 0x00000000}, /* A_32S03 */
{ "%s[ESP%s]", "%s[ESP%s]", 0x00000000, 0x00000000}, /* A_32S04 */
{ "%s[%08x%s]", "%s[%08x%s]", 0xffffffff, 0x00000000}, /* A_32S05 */
{ "%s[ESI%s]", "%s[ESI%s]", 0x00000000, 0x00000000}, /* A_32S06 */
{ "%s[EDI%s]", "%s[EDI%s]", 0x00000000, 0x00000000}, /* A_32S07 */
{ "%s[EAX%s+%02x]", "%s[EAX%s-%02x]", 0x000000ff, 0x00000080}, /* A_32S10 */
{ "%s[ECX%s+%02x]", "%s[ECX%s-%02x]", 0x000000ff, 0x00000080}, /* A_32S11 */
{ "%s[EDX%s+%02x]", "%s[EDX%s-%02x]", 0x000000ff, 0x00000080}, /* A_32S12 */
{ "%s[EBX%s+%02x]", "%s[EBX%s-%02x]", 0x000000ff, 0x00000080}, /* A_32S13 */
{ "%s[ESP%s+%02x]", "%s[ESP%s-%02x]", 0x000000ff, 0x00000080}, /* A_32S14 */
{ "%s[EBP%s+%02x]", "%s[EBP%s-%02x]", 0x000000ff, 0x00000080}, /* A_32S15 */
{ "%s[ESI%s+%02x]", "%s[ESI%s-%02x]", 0x000000ff, 0x00000080}, /* A_32S16 */
{ "%s[EDI%s+%02x]", "%s[EDI%s-%02x]", 0x000000ff, 0x00000080}, /* A_32S17 */
{ "%s[EAX%s+%08x]", "%s[EAX%s+%08x]", 0xffffffff, 0x00000000}, /* A_32S20 */
{ "%s[ECX%s+%08x]", "%s[ECX%s+%08x]", 0xffffffff, 0x00000000}, /* A_32S21 */
{ "%s[EDX%s+%08x]", "%s[EDX%s+%08x]", 0xffffffff, 0x00000000}, /* A_32S22 */
{ "%s[EBX%s+%08x]", "%s[EBX%s+%08x]", 0xffffffff, 0x00000000}, /* A_32S23 */
{ "%s[ESP%s+%08x]", "%s[ESP%s+%08x]", 0xffffffff, 0x00000000}, /* A_32S24 */
{ "%s[EBP%s+%08x]", "%s[EBP%s-%08x]", 0xffffffff, 0xfff00000}, /* A_32S25 */
{ "%s[ESI%s+%08x]", "%s[ESI%s+%08x]", 0xffffffff, 0x00000000}, /* A_32S26 */
{ "%s[EDI%s+%08x]", "%s[EDI%s+%08x]", 0xffffffff, 0x00000000}, /* A_32S27 */
{ "%s[%s%04x]", "%s[%s%04x]", 0x0000ffff, 0x00000000}, /* A_MOFFS16 */
{ "%s[%s%08x]", "%s[%s%08x]", 0xffffffff, 0x00000000}, /* A_MOFFS32 */
{ "%s[BX+AL%s]", "%s[BX+AL%s]", 0x00000000, 0x00000000}, /* A_16XLT */
{ "%s[EBX+AL%s]", "%s[EBX+AL%s]", 0x00000000, 0x00000000}, /* A_32XLT */
{ "%s[SI%s]", "%s[SI%s]", 0x00000000, 0x00000000}, /* A_16STSRC */
{ "%s[ESI%s]", "%s[ESI%s]", 0x00000000, 0x00000000}, /* A_32STSRC */
{ "%s[DI%s]", "%s[DI%s]", 0x00000000, 0x00000000}, /* A_16STDST */
{ "%s[EDI%s]", "%s[EDI%s]", 0x00000000, 0x00000000} /* A_32STDST */
};
LOCAL char *mem_id[] =
{
"", /* A_M */
"", /* A_M14 */
"", /* A_M28 */
"", /* A_M94 */
"", /* A_M108 */
"DWord Ptr ", /* A_Ma16 */
"QWord Ptr ", /* A_Ma32 */
"Byte Ptr ", /* A_Mb */
"DWord Ptr ", /* A_Md */
"Word Ptr ", /* A_Mi16 */
"DWord Ptr ", /* A_Mi32 */
"QWord Ptr ", /* A_Mi64 */
"TByte Ptr ", /* A_Mi80 */
"DWord Ptr ", /* A_Mp16 */
"FWord Ptr ", /* A_Mp32 */
"DWord Ptr ", /* A_Mr32 */
"QWord Ptr ", /* A_Mr64 */
"Tbyte Ptr ", /* A_Mr80 */
"FWord Ptr ", /* A_Ms */
"Word Ptr " /* A_Mw */
};
/*
SIB byte names.
*/
LOCAL CHAR *sib_name[] =
{
"",
"+EAX", "+ECX", "+EDX", "+EBX",
"", "+EBP", "+ESI", "+EDI",
"+2*EAX", "+2*ECX", "+2*EDX", "+2*EBX",
"+undef", "+2*EBP", "+2*ESI", "+2*EDI",
"+4*EAX", "+4*ECX", "+4*EDX", "+4*EBX",
"+undef", "+4*EBP", "+4*ESI", "+4*EDI",
"+8*EAX", "+8*ECX", "+8*EDX", "+8*EBX",
"+undef", "+8*EBP", "+8*ESI", "+8*EDI"
};
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
/* Read a byte from the given Intel linear address, return -1 if */
/* unable to read a */
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
LOCAL IS32 read_byte IFN1(LIN_ADDR, linAddr)
{
IU8 res = Sas.Sas_hw_at(linAddr);
/* if (was_error)
* return -1;
* else
*/
return (IS32)(res);
}
/*
=====================================================================
EXECUTION STARTS HERE.
=====================================================================
*/
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
/* Dis-assemble a single Intel Instruction. */
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
GLOBAL IU16
dasm IFN4(char *, txt, IU16, seg, LIN_ADDR, off, SIZE_SPECIFIER, default_size)
{
/* txt Buffer to hold dis-assembly text (-1 means not required) */
/* seg Segment for instruction to be dis-assembled */
/* off Offset for instruction to be dis-assembled */
/* default_size 16BIT or 32BIT */
char *fmt, *newline;
/* format for seg:off */
if ( off & 0xffff0000 )
{
fmt = "%04x:%08x ";
newline = "\n ";
}
else
{
fmt = "%04x:%04x ";
newline = "\n ";
}
return (dasm_internal(txt,
seg,
off,
default_size,
effective_addr(seg, off),
read_byte,
fmt,
newline));
}
extern IU16 dasm_internal IFN8(
char *, txt, /* Buffer to hold dis-assembly text (-1 means not required) */
IU16, seg, /* Segment for xxxx:... text in dis-assembly */
LIN_ADDR, off, /* ditto offset */
SIZE_SPECIFIER, default_size,/* 16BIT or 32BIT code segment */
LIN_ADDR, p, /* linear address of start of instruction */
read_byte_proc, byte_at, /* like sas_hw_at() to use to read intel
* but will return -1 if there is an error
*/
char *, fmt, /* sprintf format for first line seg:offset */
char *, newline) /* strcat text to separate lines */
{
LIN_ADDR pp; /* pntr to prefix bytes */
DECODED_INST d_inst; /* Decoded form of Intel instruction */
DECODED_ARG *d_arg; /* pntr to decoded form of Intel operand */
USHORT inst_len; /* Nr. bytes in instruction */
USHORT mc; /* Nr. machine code bytes processed */
char *arg_name; /* pntr to symbolic argument name */
char *inst_txt;
INT i;
INT name_len; /* Nr. chars in symbolic instruction name */
MEM_RECORD *m_rec; /* pntr to memory addressing record */
UTINY args_out; /* Nr. arguments actually printed */
INT prefix_width; /* Width of prefixes actually printed */
UTINY memory_id; /* Memory identifier reference */
ULONG immed; /* value for immediate arithmetic */
IBOOL unreadable = FALSE; /* TRUE if instr bytes are not readable (past M?) */
char prefix_buf[16*4];
char *prefix_txt;
/* initialise */
args_out = prefix_width = 0;
pp=p;
/* get in decoded form */
decode(p, &d_inst, default_size, byte_at);
/* hence find length of instruction */
inst_len = d_inst.inst_sz;
/* if no text required, just return the length now */
if (txt == (char*)-1){
/* Check bytes were read without errors */
if ((byte_at(p) < 0) || (byte_at(p+inst_len-1) < 0))
{
int i = inst_len - 1;
while (i > 0)
{
if (byte_at(i) >= 0)
return (i);
}
return 0;
}
return inst_len;
}
/* output seg:off in requested format */
sprintf(txt, fmt, seg, off);
txt += strlen(txt);
/* Output upto eight machine code bytes */
for ( mc = 0; mc < 8; mc++)
{
if ( mc < inst_len )
{
IS32 b = byte_at(p++);
if (b < 0)
{
sprintf(txt, ".."); /* print ".." if not readable */
unreadable = TRUE;
inst_len = mc;
}
else
sprintf(txt, "%02x", b); /* print machine code byte */
}
else
sprintf(txt, " "); /* fill in with spaces */
txt += 2;
}
/* Check inst identifier is within our known range.
* Get text for opcode and length so we can see if the
* prefix will fit.
*/
if ( d_inst.inst_id >= NR_VALID_INSTS )
{
fprintf(stderr, "Bad decoded instruction found %d\n", d_inst.inst_id);
d_inst.inst_id = I_ZBADOP;
}
/* Obtain symbolic form of instruction */
inst_txt = inst_name[d_inst.inst_id];
name_len = 1 + strlen(inst_txt);
/* Format prefix bytes if any */
prefix_txt = prefix_buf;
*prefix_txt = '\0';
if ( d_inst.prefix_sz )
{
for ( i = 0; i < d_inst.prefix_sz; byte_at(pp), i++)
{
switch ( byte_at(pp) )
{
case 0xf1:
/* it don't do nothing -- don't display nothing */
case 0xf2:
case 0xf3:
/* if valid instructions will print them */
case 0x66:
case 0x67:
/* the effect is obvious from the operands */
break;
case 0xf0: sprintf(prefix_txt, " LOCK"); prefix_txt += 5; break;
case 0x26: sprintf(prefix_txt, " ES:"); prefix_txt += 4; break;
case 0x2e: sprintf(prefix_txt, " CS:"); prefix_txt += 4; break;
case 0x36: sprintf(prefix_txt, " SS:"); prefix_txt += 4; break;
case 0x3e: sprintf(prefix_txt, " DS:"); prefix_txt += 4; break;
case 0x64: sprintf(prefix_txt, " FS:"); prefix_txt += 4; break;
case 0x65: sprintf(prefix_txt, " GS:"); prefix_txt += 4; break;
default:
fprintf(stderr, "Bad prefix found %02x\n", byte_at(pp));
break;
} /* end switch */
pp++;
} /* end for */
} /* end if d_inst.prefix_sz */
prefix_width = strlen(prefix_buf);
if ( newline != NULL )
{
if ( ((inst_len * 2) + prefix_width) > 16)
{
/* start new line for instruction */
strcat(txt, newline);
txt += strlen(txt);
/* output rest of machine code bytes */
for ( ; mc < 16; mc++)
{
if ( mc < inst_len )
{
IS32 b = byte_at(p++);
if (b < 0)
{
sprintf(txt, ".."); /* print ".." if not readable */
unreadable = TRUE;
inst_len = mc;
}
else
sprintf(txt, "%02x", b); /* print machine code byte */
}
else
sprintf(txt, " "); /* fill in with spaces */
txt += 2;
}
}
if ( ((inst_len * 2) + prefix_width) > 32)
{
/* wont fit on two lines */
strcat(txt, newline);
txt += strlen(txt);
/* output rest of machine code bytes */
for ( ; mc < 24; mc++)
{
sprintf(txt, " "); /* fill in with spaces */
txt += 2;
}
}
txt -= (prefix_width <= 17 ? prefix_width: 17);
}
if (unreadable)
{
sprintf(txt, "<< Unreadable >>\n");
return inst_len;
}
sprintf(txt, "%s %s", prefix_buf, inst_txt);
txt += prefix_width + name_len;
/* pad out to 11 characters wide */
for (i = name_len; i <= 11; i++)
*txt++ = ' ';
if (d_inst.inst_id != I_ZBADOP)
{
/* output each valid argument in turn */
for ( i = 0; i < 3; i++ )
{
d_arg = &d_inst.args[i];
arg_name = (CHAR *)0;
if ( d_arg->arg_type != A_ )
{
/* process valid arg */
sprintf(txt, "%c", arg_preface[args_out++]);
txt += 1;
switch ( d_arg->arg_type )
{
case A_Rb: /* aka r8,r/m8 */
arg_name = Rb_name[DCD_IDENTIFIER(d_arg)];
break;
case A_Rw: /* aka r16,r/m16 */
arg_name = Rw_name[DCD_IDENTIFIER(d_arg)];
break;
case A_Rd: /* aka r32,r/m32 */
arg_name = Rd_name[DCD_IDENTIFIER(d_arg)];
break;
case A_Sw: /* aka Sreg */
arg_name = Sw_name[DCD_IDENTIFIER(d_arg)];
break;
case A_Cd: /* aka CRx */
arg_name = Cd_name[DCD_IDENTIFIER(d_arg)];
break;
case A_Dd: /* aka DRx */
arg_name = Dd_name[DCD_IDENTIFIER(d_arg)];
break;
case A_Td: /* aka TRx */
arg_name = Td_name[DCD_IDENTIFIER(d_arg)];
break;
case A_M: /* aka m */
case A_M14: /* aka m14byte */
case A_M28: /* aka m28byte */
case A_M94: /* aka m94byte */
case A_M108: /* aka m108byte */
case A_Ma16: /* aka m16&16 */
case A_Ma32: /* aka m32&32 */
case A_Mb: /* aka m8,r/m8,moffs8 */
case A_Md: /* aka m32,r/m32,moffs32 */
case A_Mi16: /* aka m16int */
case A_Mi32: /* aka m32int */
case A_Mi64: /* aka m64int */
case A_Mi80: /* aka m80dec */
case A_Mp16: /* aka m16:16 */
case A_Mp32: /* aka m16:32 */
case A_Mr32: /* aka m32real */
case A_Mr64: /* aka m64real */
case A_Mr80: /* aka m80real */
case A_Ms: /* aka m16&32 */
case A_Mw: /* aka m16,r/m16,moffs16 */
/* First work out memory identifier */
switch ( d_arg->arg_type )
{
case A_M: memory_id = 0; break;
case A_M14: memory_id = 1; break;
case A_M28: memory_id = 2; break;
case A_M94: memory_id = 3; break;
case A_M108: memory_id = 4; break;
case A_Ma16: memory_id = 5; break;
case A_Ma32: memory_id = 6; break;
case A_Mb: memory_id = 7; break;
case A_Md: memory_id = 8; break;
case A_Mi16: memory_id = 9; break;
case A_Mi32: memory_id = 10; break;
case A_Mi64: memory_id = 11; break;
case A_Mi80: memory_id = 12; break;
case A_Mp16: memory_id = 13; break;
case A_Mp32: memory_id = 14; break;
case A_Mr32: memory_id = 15; break;
case A_Mr64: memory_id = 16; break;
case A_Mr80: memory_id = 17; break;
case A_Ms: memory_id = 18; break;
case A_Mw: memory_id = 19; break;
}
/* output memory details */
m_rec = &mem_name[DCD_IDENTIFIER(d_arg)];
if ( m_rec->disp_mask == 0 )
{
/* no displacement to print out */
sprintf(txt, m_rec->positive,
mem_id[memory_id],
sib_name[DCD_SUBTYPE(d_arg)]);
}
else
{
/* displacement to print out */
IU32 disp = DCD_DISP(d_arg);
char *fmt;
/* Do we think this is a negative displacement ? */
if (m_rec->sign_mask && ((m_rec->sign_mask & disp) == m_rec->sign_mask))
{
disp = -disp;
fmt = m_rec->negative;
}
else
fmt = m_rec->positive;
disp &= m_rec->disp_mask;
if ( DCD_IDENTIFIER(d_arg) == A_32S05 )
sprintf(txt, fmt,
mem_id[memory_id],
disp,
sib_name[DCD_SUBTYPE(d_arg)]);
else
sprintf(txt, fmt,
mem_id[memory_id],
sib_name[DCD_SUBTYPE(d_arg)],
disp);
}
name_len = strlen(txt);
txt += name_len;
break;
case A_I: /* aka imm8,imm16,imm32 */
immed = DCD_IMMED1(d_arg);
switch ( DCD_IDENTIFIER(d_arg) )
{
case A_IMMC:
/* check for inbuilt zero - don't print */
if ( immed )
{
sprintf(txt, "%1d", immed); txt += 1;
}
else
{
/* kill preface */
args_out--;
txt -= 1;
*txt = '\0';
}
break;
case A_IMMB:
sprintf(txt, "%02x", immed); txt += 2;
break;
case A_IMMW:
sprintf(txt, "%04x", immed); txt += 4;
break;
case A_IMMD:
sprintf(txt, "%08x", immed); txt += 8;
break;
case A_IMMWB:
case A_IMMDB:
/* remove sign extension */
immed &= 0xff;
/* print byte with correct sign */
if ( immed <= 0x7f )
{
sprintf(txt, "+%02x", immed); txt += 3;
}
else
{
immed = 0x100 - immed;
sprintf(txt, "-%02x", immed); txt += 3;
}
break;
}
break;
case A_J: /* aka rel8,rel16,rel32 */
/* calc new dest */
immed = off + inst_len + DCD_IMMED1(d_arg);
/* handle as 16-bit mode or 32-bit mode */
switch ( d_inst.inst_id )
{
case I_JO16: case I_JNO16: case I_JB16:
case I_JNB16: case I_JZ16: case I_JNZ16:
case I_JBE16: case I_JNBE16: case I_JS16:
case I_JNS16: case I_JP16: case I_JNP16:
case I_JL16: case I_JNL16: case I_JLE16:
case I_JNLE16: case I_LOOPNE16: case I_LOOPE16:
case I_LOOP16: case I_JCXZ: case I_CALLR16:
case I_JMPR16:
immed &= 0xffff;
sprintf(txt, "%04x", immed);
txt += 4;
break;
default: /* 32-bit mode */
sprintf(txt, "%08x", immed);
txt += 8;
break;
}
break;
case A_K: /* aka ptr16:16,ptr16:32 */
{
/* handle as 16-bit mode or 32-bit mode */
char *sep = ":";
switch ( d_inst.inst_id )
{
case I_CALLF16: case I_JMPF16:
sprintf(txt, "%04x%s%04x", DCD_IMMED2(d_arg), sep, DCD_IMMED1(d_arg));
txt += 9;
break;
default: /* 32-bit mode */
sprintf(txt, "%04x%s%08x", DCD_IMMED2(d_arg), sep, DCD_IMMED1(d_arg));
txt += 13;
break;
}
}
break;
case A_V: /* aka ST,push onto ST, ST(i) */
switch ( DCD_IDENTIFIER(d_arg) )
{
case A_ST:
/* Some cases are obvious - so not all get printed */
switch ( d_inst.inst_id )
{
case I_F2XM1: case I_FABS: case I_FBSTP:
case I_FCHS: case I_FCOS: case I_FIST:
case I_FISTP: case I_FPATAN: case I_FPREM:
case I_FPREM1: case I_FPTAN: case I_FRNDINT:
case I_FSCALE: case I_FSIN: case I_FSINCOS:
case I_FSQRT: case I_FST: case I_FSTP:
case I_FTST: case I_FXAM: case I_FXTRACT:
case I_FYL2X: case I_FYL2XP1:
break;
default: /* do print */
arg_name = "ST";
break;
}
break;
case A_STP:
/* All cases are obvious - so no printing */
break;
case A_STI:
/* Some cases are obvious - so not all get printed */
switch ( d_inst.inst_id )
{
case I_FPATAN: case I_FPREM: case I_FPREM1:
case I_FSCALE: case I_FYL2X: case I_FYL2XP1:
break;
default: /* do print */
sprintf(txt, "ST(%1d", DCD_INDEX(d_arg));
txt += 4;
arg_name = ")";
break;
}
break;
}
/* if we aren't printing - kill preface */
if ( arg_name == (CHAR *)0 )
{
args_out--;
txt -= 1;
*txt = '\0';
}
break;
default:
fprintf(stderr, "Bad decoded argument found %d\n",
d_arg->arg_type);
break;
} /* end switch */
} /* end if */
/* print something if we have it */
if ( arg_name != (CHAR *)0 )
{
sprintf(txt, "%s", arg_name);
name_len = strlen(arg_name);
txt += name_len;
}
} /* end for arg */
}
if (d_inst.inst_id == I_ZBOP)
{
IU8 num = DCD_IMMED1(&d_inst.args[0]);
extern char *bop_name IPT1(IU8, num);
char *name = bop_name(num);
if (name != NULL)
{
sprintf(txt, " : %s", name);
txt += strlen(txt);
}
}
/* Finally output any machine code bytes remaining */
/* iff bytes remaining && room in output format */
if ( (newline != NULL ) && ( mc < inst_len && mc < 16 ))
{
strcat(txt, newline);
txt += strlen(txt);
for ( ; mc < inst_len && mc < 16; mc++ )
{
IS32 b = byte_at(p++);
if (b < 0)
{
sprintf(txt, ".."); /* print ".." if not readable */
inst_len = mc;
}
else
sprintf(txt, "%02x", b); /* print machine code byte */
p++;
txt += 2;
}
}
sprintf(txt, "\n");
return inst_len;
}