/*[ 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 /* 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; }