tstDisasm-2.cpp revision 2cae8ff5782536dc236e1161d351356ba2ac5e0f
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync * Testcase - Generic Disassembler Tool.
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync * Copyright (C) 2008 Sun Microsystems, Inc.
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync * available from http://www.virtualbox.org. This file is free software;
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync * you can redistribute it and/or modify it under the terms of the GNU
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync * General Public License (GPL) as published by the Free Software
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync * Clara, CA 95054 USA or visit http://www.sun.com if you need
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync * additional information or have any questions.
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync/*******************************************************************************
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync* Header Files *
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync*******************************************************************************/
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync/*******************************************************************************
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync* Structures and Typedefs *
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync*******************************************************************************/
8599686860198730ae53d5895386d1b57dbc060evboxsynctypedef enum { kAsmStyle_Default, kAsmStyle_yasm, kAsmStyle_masm, kAsmStyle_gas, kAsmStyle_invalid } ASMSTYLE;
7748b9362d6a39df9045d5d05ccb57871145a649vboxsynctypedef enum { kUndefOp_Fail, kUndefOp_All, kUndefOp_DefineByte, kUndefOp_End } UNDEFOPHANDLING;
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsynctypedef struct MYDISSTATE
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync uint64_t uAddress; /**< The current instruction address. */
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync uint8_t *pbInstr; /**< The current instruction (pointer). */
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync uint32_t cbInstr; /**< The size of the current instruction. */
7748b9362d6a39df9045d5d05ccb57871145a649vboxsync bool fUndefOp; /**< Whether the current instruction is really an undefined opcode.*/
7748b9362d6a39df9045d5d05ccb57871145a649vboxsync UNDEFOPHANDLING enmUndefOp; /**< How to treat undefined opcodes. */
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync size_t cbLeft; /**< The number of bytes left. (read) */
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync uint64_t uNextAddr; /**< The address of the next byte. (read) */
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync char szLine[256]; /**< The disassembler text output. */
8599686860198730ae53d5895386d1b57dbc060evboxsync * Non-logging builds doesn't to full formatting so we must do it on our own.
8599686860198730ae53d5895386d1b57dbc060evboxsync * This should probably be moved into the disassembler later as it's needed for
8599686860198730ae53d5895386d1b57dbc060evboxsync * the vbox debugger as well.
8599686860198730ae53d5895386d1b57dbc060evboxsync * Comment in USE_MY_FORMATTER to enable it.
8599686860198730ae53d5895386d1b57dbc060evboxsync "al\0", "cl\0", "dl\0", "bl\0", "ah\0", "ch\0", "dh\0", "bh\0"
8599686860198730ae53d5895386d1b57dbc060evboxsync "al\0\0", "cl\0\0", "dl\0\0", "bl\0\0", "spb\0", "bpb\0", "sib\0", "dib\0", "r8b\0", "r9b\0", "r10b", "r11b", "r12b", "r13b", "r14b", "r15b"
8599686860198730ae53d5895386d1b57dbc060evboxsync "ax\0\0", "cx\0\0", "dx\0\0", "bx\0\0", "sp\0\0", "bp\0\0", "si\0\0", "di\0\0", "r8w\0", "r9w\0", "r10w", "r11w", "r12w", "r13w", "r14w", "r15w"
8599686860198730ae53d5895386d1b57dbc060evboxsync "bx+si", "bx+di", "bp+si", "bp+di", "si\0\0\0", "di\0\0\0", "bp\0\0\0", "bx\0\0\0"
8599686860198730ae53d5895386d1b57dbc060evboxsync "eax\0", "ecx\0", "edx\0", "ebx\0", "esp\0", "ebp\0", "esi\0", "edi\0", "r8d\0", "r9d\0", "r10d", "r11d", "r12d", "r13d", "r14d", "r15d"
8599686860198730ae53d5895386d1b57dbc060evboxsync "rax", "rcx", "rdx", "rbx", "rsp", "rbp", "rsi", "rdi", "r8\0", "r9\0", "r10", "r11", "r12", "r13", "r14", "r15"
8599686860198730ae53d5895386d1b57dbc060evboxsync "st0", "st1", "st2", "st3", "st4", "st5", "st6", "st7"
8599686860198730ae53d5895386d1b57dbc060evboxsync "mm0", "mm1", "mm2", "mm3", "mm4", "mm5", "mm6", "mm7"
8599686860198730ae53d5895386d1b57dbc060evboxsync "xmm0\0", "xmm1\0", "xmm2\0", "xmm3\0", "xmm4\0", "xmm5\0", "xmm6\0", "xmm7\0", "xmm8\0", "xmm9\0", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15"
8599686860198730ae53d5895386d1b57dbc060evboxsync "cr0\0", "cr1\0", "cr2\0", "cr3\0", "cr4\0", "cr5\0", "cr6\0", "cr7\0", "cr8\0", "cr9\0", "cr10", "cr11", "cr12", "cr13", "cr14", "cr15"
8599686860198730ae53d5895386d1b57dbc060evboxsync "dr0\0", "dr1\0", "dr2\0", "dr3\0", "dr4\0", "dr5\0", "dr6\0", "dr7\0", "dr8\0", "dr9\0", "dr10", "dr11", "dr12", "dr13", "dr14", "dr15"
8599686860198730ae53d5895386d1b57dbc060evboxsync "tr0\0", "tr1\0", "tr2\0", "tr3\0", "tr4\0", "tr5\0", "tr6\0", "tr7\0", "tr8\0", "tr9\0", "tr10", "tr11", "tr12", "tr13", "tr14", "tr15"
8599686860198730ae53d5895386d1b57dbc060evboxsyncDECLINLINE(const char *) MyDisasYasmFormatBaseReg(DISCPUSTATE const *pCpu, PCOP_PARAMETER pParam, size_t *pcchReg, bool fReg1616)
8599686860198730ae53d5895386d1b57dbc060evboxsync switch (pParam->flags & ( USE_REG_GEN8 | USE_REG_GEN16 | USE_REG_GEN32 | USE_REG_GEN64
8599686860198730ae53d5895386d1b57dbc060evboxsync | USE_REG_FP | USE_REG_MMX | USE_REG_XMM | USE_REG_CR
8599686860198730ae53d5895386d1b57dbc060evboxsync Assert(pParam->base.reg_gen < RT_ELEMENTS(g_aszYasmRegGen8Amd64));
8599686860198730ae53d5895386d1b57dbc060evboxsync const char *psz = g_aszYasmRegGen8Amd64[pParam->base.reg_gen];
8599686860198730ae53d5895386d1b57dbc060evboxsync Assert(pParam->base.reg_gen < RT_ELEMENTS(g_aszYasmRegGen8x86));
8599686860198730ae53d5895386d1b57dbc060evboxsync Assert(pParam->base.reg_gen < RT_ELEMENTS(g_aszYasmRegGen1616));
8599686860198730ae53d5895386d1b57dbc060evboxsync const char *psz = g_aszYasmRegGen1616[pParam->base.reg_gen];
8599686860198730ae53d5895386d1b57dbc060evboxsync Assert(pParam->base.reg_gen < RT_ELEMENTS(g_aszYasmRegGen16));
8599686860198730ae53d5895386d1b57dbc060evboxsync const char *psz = g_aszYasmRegGen16[pParam->base.reg_gen];
8599686860198730ae53d5895386d1b57dbc060evboxsync Assert(pParam->base.reg_gen < RT_ELEMENTS(g_aszYasmRegGen32));
8599686860198730ae53d5895386d1b57dbc060evboxsync const char *psz = g_aszYasmRegGen32[pParam->base.reg_gen];
8599686860198730ae53d5895386d1b57dbc060evboxsync Assert(pParam->base.reg_gen < RT_ELEMENTS(g_aszYasmRegGen64));
8599686860198730ae53d5895386d1b57dbc060evboxsync const char *psz = g_aszYasmRegGen64[pParam->base.reg_gen];
8599686860198730ae53d5895386d1b57dbc060evboxsync Assert(pParam->base.reg_fp < RT_ELEMENTS(g_aszYasmRegFP));
8599686860198730ae53d5895386d1b57dbc060evboxsync const char *psz = g_aszYasmRegFP[pParam->base.reg_fp];
8599686860198730ae53d5895386d1b57dbc060evboxsync Assert(pParam->base.reg_mmx < RT_ELEMENTS(g_aszYasmRegMMX));
8599686860198730ae53d5895386d1b57dbc060evboxsync const char *psz = g_aszYasmRegMMX[pParam->base.reg_mmx];
8599686860198730ae53d5895386d1b57dbc060evboxsync Assert(pParam->base.reg_xmm < RT_ELEMENTS(g_aszYasmRegXMM));
8599686860198730ae53d5895386d1b57dbc060evboxsync const char *psz = g_aszYasmRegXMM[pParam->base.reg_mmx];
8599686860198730ae53d5895386d1b57dbc060evboxsync Assert(pParam->base.reg_ctrl < RT_ELEMENTS(g_aszYasmRegCRx));
8599686860198730ae53d5895386d1b57dbc060evboxsync const char *psz = g_aszYasmRegCRx[pParam->base.reg_ctrl];
8599686860198730ae53d5895386d1b57dbc060evboxsync Assert(pParam->base.reg_dbg < RT_ELEMENTS(g_aszYasmRegDRx));
8599686860198730ae53d5895386d1b57dbc060evboxsync const char *psz = g_aszYasmRegDRx[pParam->base.reg_dbg];
8599686860198730ae53d5895386d1b57dbc060evboxsync Assert(pParam->base.reg_seg < RT_ELEMENTS(g_aszYasmRegCRx));
8599686860198730ae53d5895386d1b57dbc060evboxsync const char *psz = g_aszYasmRegSeg[pParam->base.reg_seg];
8599686860198730ae53d5895386d1b57dbc060evboxsync Assert(pParam->base.reg_test < RT_ELEMENTS(g_aszYasmRegTRx));
8599686860198730ae53d5895386d1b57dbc060evboxsync const char *psz = g_aszYasmRegTRx[pParam->base.reg_test];
8599686860198730ae53d5895386d1b57dbc060evboxsync return "r??";
8599686860198730ae53d5895386d1b57dbc060evboxsyncDECLINLINE(const char *) MyDisasYasmFormatIndexReg(DISCPUSTATE const *pCpu, PCOP_PARAMETER pParam, size_t *pcchReg)
8599686860198730ae53d5895386d1b57dbc060evboxsync Assert(pParam->index.reg_gen < RT_ELEMENTS(g_aszYasmRegGen16));
8599686860198730ae53d5895386d1b57dbc060evboxsync const char *psz = g_aszYasmRegGen16[pParam->index.reg_gen];
8599686860198730ae53d5895386d1b57dbc060evboxsync Assert(pParam->index.reg_gen < RT_ELEMENTS(g_aszYasmRegGen32));
8599686860198730ae53d5895386d1b57dbc060evboxsync const char *psz = g_aszYasmRegGen32[pParam->index.reg_gen];
8599686860198730ae53d5895386d1b57dbc060evboxsync Assert(pParam->index.reg_gen < RT_ELEMENTS(g_aszYasmRegGen64));
8599686860198730ae53d5895386d1b57dbc060evboxsync const char *psz = g_aszYasmRegGen64[pParam->index.reg_gen];
8599686860198730ae53d5895386d1b57dbc060evboxsync AssertMsgFailed(("%#x %#x\n", pParam->flags, pCpu->addrmode));
8599686860198730ae53d5895386d1b57dbc060evboxsync return "r??";
8599686860198730ae53d5895386d1b57dbc060evboxsyncstatic size_t MyDisasYasmFormat(DISCPUSTATE const *pCpu, char *pszBuf, size_t cchBuf)
8599686860198730ae53d5895386d1b57dbc060evboxsync /* output macros */
8599686860198730ae53d5895386d1b57dbc060evboxsync } while (0)
8599686860198730ae53d5895386d1b57dbc060evboxsync } while (0)
8599686860198730ae53d5895386d1b57dbc060evboxsync do { const size_t cchTmp = strlen(psz); PUT_STR((psz), cchTmp); } while (0)
8599686860198730ae53d5895386d1b57dbc060evboxsync const size_t cchTmp = RTStrPrintf(pszDst, cchBuf, fmt, (num)); \
8599686860198730ae53d5895386d1b57dbc060evboxsync } while (0)
8599686860198730ae53d5895386d1b57dbc060evboxsync#define PUT_NUM_8(num) PUT_NUM(4, "0%02xh", (uint8_t)(num))
8599686860198730ae53d5895386d1b57dbc060evboxsync#define PUT_NUM_16(num) PUT_NUM(6, "0%04xh", (uint16_t)(num))
8599686860198730ae53d5895386d1b57dbc060evboxsync#define PUT_NUM_32(num) PUT_NUM(10, "0%08xh", (uint32_t)(num))
8599686860198730ae53d5895386d1b57dbc060evboxsync#define PUT_NUM_64(num) PUT_NUM(18, "0%08xh", (uint64_t)(num))
8599686860198730ae53d5895386d1b57dbc060evboxsync * Filter out invalid opcodes first as they need special
8599686860198730ae53d5895386d1b57dbc060evboxsync * treatment. UD2 is an exception and should be handled normally.
8599686860198730ae53d5895386d1b57dbc060evboxsync * Adjust the format string to avoid stuff the assembler cannot handle.
8599686860198730ae53d5895386d1b57dbc060evboxsync pszFmt = pCpu->opmode == CPUMODE_16BIT ? "jcxz %Jb" : pCpu->opmode == CPUMODE_32BIT ? "jecxz %Jb" : "jrcxz %Jb";
8599686860198730ae53d5895386d1b57dbc060evboxsync pszFmt = pCpu->opmode == CPUMODE_16BIT ? "pushfw" : pCpu->opmode == CPUMODE_32BIT ? "pushfd" : "pushfq";
8599686860198730ae53d5895386d1b57dbc060evboxsync pszFmt = pCpu->opmode == CPUMODE_16BIT ? "popfw" : pCpu->opmode == CPUMODE_32BIT ? "popfd" : "popfq";
8599686860198730ae53d5895386d1b57dbc060evboxsync pszFmt = pCpu->opmode == CPUMODE_16BIT ? "insw" : pCpu->opmode == CPUMODE_32BIT ? "insd" : "insq";
8599686860198730ae53d5895386d1b57dbc060evboxsync pszFmt = pCpu->opmode == CPUMODE_16BIT ? "outsw" : pCpu->opmode == CPUMODE_32BIT ? "outsd" : "outsq";
8599686860198730ae53d5895386d1b57dbc060evboxsync pszFmt = pCpu->opmode == CPUMODE_16BIT ? "movsw" : pCpu->opmode == CPUMODE_32BIT ? "movsd" : "movsq";
8599686860198730ae53d5895386d1b57dbc060evboxsync pszFmt = pCpu->opmode == CPUMODE_16BIT ? "cmpsw" : pCpu->opmode == CPUMODE_32BIT ? "cmpsd" : "cmpsq";
8599686860198730ae53d5895386d1b57dbc060evboxsync pszFmt = pCpu->opmode == CPUMODE_16BIT ? "scasw" : pCpu->opmode == CPUMODE_32BIT ? "scasd" : "scasq";
8599686860198730ae53d5895386d1b57dbc060evboxsync pszFmt = pCpu->opmode == CPUMODE_16BIT ? "lodsw" : pCpu->opmode == CPUMODE_32BIT ? "lodsd" : "lodsq";
8599686860198730ae53d5895386d1b57dbc060evboxsync pszFmt = pCpu->opmode == CPUMODE_16BIT ? "stosw" : pCpu->opmode == CPUMODE_32BIT ? "stosd" : "stosq";
2cae8ff5782536dc236e1161d351356ba2ac5e0fvboxsync pszFmt = pCpu->opmode == CPUMODE_16BIT ? "cbw" : pCpu->opmode == CPUMODE_32BIT ? "cwde" : "cdqe";
2cae8ff5782536dc236e1161d351356ba2ac5e0fvboxsync pszFmt = pCpu->opmode == CPUMODE_16BIT ? "cwd" : pCpu->opmode == CPUMODE_32BIT ? "cdq" : "cqo";
8599686860198730ae53d5895386d1b57dbc060evboxsync * Don't know how to tell yasm to generate complicated nop stuff, so 'db' it.
8599686860198730ae53d5895386d1b57dbc060evboxsync /* fine, fine */;
8599686860198730ae53d5895386d1b57dbc060evboxsync else if (pszFmt[sizeof("nop %Ev")] == '/' && pszFmt[sizeof("nop %Ev") + 1] == 'p')
8599686860198730ae53d5895386d1b57dbc060evboxsync /* ST(X) -> stX (floating point) */
8599686860198730ae53d5895386d1b57dbc060evboxsync if (ch == 'S' && pszFmt[0] == 'T' && pszFmt[1] == '(')
8599686860198730ae53d5895386d1b57dbc060evboxsync * Horrible hacks.
8599686860198730ae53d5895386d1b57dbc060evboxsync *(int *)&pCpu->param1.param &= ~0x1f; /* make it pure OP_PARM_M */
8599686860198730ae53d5895386d1b57dbc060evboxsync case OP_LAR: /* hack w -> v, probably not correct. */
8599686860198730ae53d5895386d1b57dbc060evboxsync * Formatting context and associated macros.
8599686860198730ae53d5895386d1b57dbc060evboxsync if ( OP_PARM_VSUBTYPE(pParam->param) == OP_PARM_p \
8599686860198730ae53d5895386d1b57dbc060evboxsync } while (0)
8599686860198730ae53d5895386d1b57dbc060evboxsync /** @todo mov ah,ch ends up with a byte 'override'... */
8599686860198730ae53d5895386d1b57dbc060evboxsync default: break; \
8599686860198730ae53d5895386d1b57dbc060evboxsync if (OP_PARM_VTYPE(pParam->param) != OP_PARM_W) /* these are 128 bit, pray they are all unambiguous.. */ \
8599686860198730ae53d5895386d1b57dbc060evboxsync case OP_PARM_s: if (pParam->flags & USE_REG_FP) PUT_SZ("tword "); break; /* ?? */ \
8599686860198730ae53d5895386d1b57dbc060evboxsync case OP_PARM_z: break; \
8599686860198730ae53d5895386d1b57dbc060evboxsync && ((pParam->flags & USE_REG_FP) || pOp->opcode == OP_FLD)) \
8599686860198730ae53d5895386d1b57dbc060evboxsync default: break; /*no pointer type specified/necessary*/ \
8599686860198730ae53d5895386d1b57dbc060evboxsync } while (0)
8599686860198730ae53d5895386d1b57dbc060evboxsync static const char s_szSegPrefix[6][4] = { "es:", "cs:", "ss:", "ds:", "fs:", "gs:" };
8599686860198730ae53d5895386d1b57dbc060evboxsync } while (0)
2cae8ff5782536dc236e1161d351356ba2ac5e0fvboxsync * Segment prefixing for instructions that doesn't do memory access.
8599686860198730ae53d5895386d1b57dbc060evboxsync * The formatting loop.
8599686860198730ae53d5895386d1b57dbc060evboxsync * ModRM - Register only.
8599686860198730ae53d5895386d1b57dbc060evboxsync case 'C': /* Control register (ParseModRM / UseModRM). */
8599686860198730ae53d5895386d1b57dbc060evboxsync case 'D': /* Debug register (ParseModRM / UseModRM). */
8599686860198730ae53d5895386d1b57dbc060evboxsync case 'G': /* ModRM selects general register (ParseModRM / UseModRM). */
8599686860198730ae53d5895386d1b57dbc060evboxsync case 'S': /* ModRM byte selects a segment register (ParseModRM / UseModRM). */
8599686860198730ae53d5895386d1b57dbc060evboxsync case 'T': /* ModRM byte selects a test register (ParseModRM / UseModRM). */
8599686860198730ae53d5895386d1b57dbc060evboxsync case 'V': /* ModRM byte selects an XMM/SSE register (ParseModRM / UseModRM). */
8599686860198730ae53d5895386d1b57dbc060evboxsync case 'P': /* ModRM byte selects MMX register (ParseModRM / UseModRM). */
8599686860198730ae53d5895386d1b57dbc060evboxsync pszFmt += RT_C_IS_ALPHA(pszFmt[0]) ? RT_C_IS_ALPHA(pszFmt[1]) ? 2 : 1 : 0;
8599686860198730ae53d5895386d1b57dbc060evboxsync Assert(!(pParam->flags & (USE_INDEX | USE_SCALE) /* No SIB here... */));
8599686860198730ae53d5895386d1b57dbc060evboxsync Assert(!(pParam->flags & (USE_DISPLACEMENT8 | USE_DISPLACEMENT16 | USE_DISPLACEMENT32 | USE_DISPLACEMENT64 | USE_RIPDISPLACEMENT32)));
8599686860198730ae53d5895386d1b57dbc060evboxsync const char *pszReg = MyDisasYasmFormatBaseReg(pCpu, pParam, &cchReg, 0 /* pCpu->addrmode == CPUMODE_16BIT */);
8599686860198730ae53d5895386d1b57dbc060evboxsync * ModRM - Register or memory.
8599686860198730ae53d5895386d1b57dbc060evboxsync case 'E': /* ModRM specifies parameter (ParseModRM / UseModRM / UseSIB). */
8599686860198730ae53d5895386d1b57dbc060evboxsync case 'Q': /* ModRM byte selects MMX register or memory address (ParseModRM / UseModRM). */
8599686860198730ae53d5895386d1b57dbc060evboxsync case 'R': /* ModRM byte may only refer to a general register (ParseModRM / UseModRM). */
8599686860198730ae53d5895386d1b57dbc060evboxsync case 'W': /* ModRM byte selects an XMM/SSE register or a memory address (ParseModRM / UseModRM). */
8599686860198730ae53d5895386d1b57dbc060evboxsync case 'M': /* ModRM may only refer to memory (ParseModRM / UseModRM). */
8599686860198730ae53d5895386d1b57dbc060evboxsync pszFmt += RT_C_IS_ALPHA(pszFmt[0]) ? RT_C_IS_ALPHA(pszFmt[1]) ? 2 : 1 : 0;
8599686860198730ae53d5895386d1b57dbc060evboxsync /* Work around mov seg,[mem16] and mov [mem16],seg as these always make a 16-bit mem
8599686860198730ae53d5895386d1b57dbc060evboxsync while the register variants deals with 16, 32 & 64 in the normal fashion. */
8599686860198730ae53d5895386d1b57dbc060evboxsync if (pParam->flags & (USE_DISPLACEMENT8 | USE_DISPLACEMENT16 | USE_DISPLACEMENT32 | USE_DISPLACEMENT64 | USE_RIPDISPLACEMENT32))
8599686860198730ae53d5895386d1b57dbc060evboxsync && (int8_t)pParam->disp16 == (int16_t)pParam->disp16)
8599686860198730ae53d5895386d1b57dbc060evboxsync && (int8_t)pParam->disp32 == (int32_t)pParam->disp32)
8599686860198730ae53d5895386d1b57dbc060evboxsync bool fBase = (pParam->flags & USE_BASE) /* When exactly is USE_BASE supposed to be set? disasmModRMReg doesn't set it. */
8599686860198730ae53d5895386d1b57dbc060evboxsync || ( (pParam->flags & (USE_REG_GEN8 | USE_REG_GEN16 | USE_REG_GEN32 | USE_REG_GEN64))
8599686860198730ae53d5895386d1b57dbc060evboxsync const char *pszReg = MyDisasYasmFormatBaseReg(pCpu, pParam, &cchReg, 0 /*pCpu->addrmode == CPUMODE_16BIT*/);
8599686860198730ae53d5895386d1b57dbc060evboxsync const char *pszReg = MyDisasYasmFormatIndexReg(pCpu, pParam, &cchReg);
8599686860198730ae53d5895386d1b57dbc060evboxsync if (pParam->flags & (USE_DISPLACEMENT8 | USE_DISPLACEMENT16 | USE_DISPLACEMENT32 | USE_DISPLACEMENT64 | USE_RIPDISPLACEMENT32))
8599686860198730ae53d5895386d1b57dbc060evboxsync else if (pParam->flags & (USE_DISPLACEMENT32 | USE_RIPDISPLACEMENT32))
8599686860198730ae53d5895386d1b57dbc060evboxsync case 'F': /* Eflags register (0 - popf/pushf only, avoided in adjustments above). */
8599686860198730ae53d5895386d1b57dbc060evboxsync case 'I': /* Immediate data (ParseImmByte, ParseImmByteSX, ParseImmV, ParseImmUshort, ParseImmZ). */
8599686860198730ae53d5895386d1b57dbc060evboxsync Assert(*pszFmt == 'b' || *pszFmt == 'v' || *pszFmt == 'w' || *pszFmt == 'z'); pszFmt++;
8599686860198730ae53d5895386d1b57dbc060evboxsync switch (pParam->flags & ( USE_IMMEDIATE8 | USE_IMMEDIATE16 | USE_IMMEDIATE32 | USE_IMMEDIATE64
8599686860198730ae53d5895386d1b57dbc060evboxsync if ( (pOp->param1 >= OP_PARM_REG_GEN8_START && pOp->param1 <= OP_PARM_REG_GEN8_END)
8599686860198730ae53d5895386d1b57dbc060evboxsync || (pOp->param2 >= OP_PARM_REG_GEN8_START && pOp->param2 <= OP_PARM_REG_GEN8_END)
8599686860198730ae53d5895386d1b57dbc060evboxsync if ( (int8_t)pParam->parval == (int16_t)pParam->parval
8599686860198730ae53d5895386d1b57dbc060evboxsync || (pOp->param1 >= OP_PARM_REG_GEN16_START && pOp->param1 <= OP_PARM_REG_GEN16_END)
8599686860198730ae53d5895386d1b57dbc060evboxsync || (pOp->param2 >= OP_PARM_REG_GEN16_START && pOp->param2 <= OP_PARM_REG_GEN16_END)
8599686860198730ae53d5895386d1b57dbc060evboxsync else if (OP_PARM_VSUBTYPE(pParam->param) == OP_PARM_v)
8599686860198730ae53d5895386d1b57dbc060evboxsync if ( (int8_t)pParam->parval == (int32_t)pParam->parval
8599686860198730ae53d5895386d1b57dbc060evboxsync || (pOp->param1 >= OP_PARM_REG_GEN32_START && pOp->param1 <= OP_PARM_REG_GEN32_END)
8599686860198730ae53d5895386d1b57dbc060evboxsync || (pOp->param2 >= OP_PARM_REG_GEN32_START && pOp->param2 <= OP_PARM_REG_GEN32_END)
8599686860198730ae53d5895386d1b57dbc060evboxsync else if (OP_PARM_VSUBTYPE(pParam->param) == OP_PARM_v)
8599686860198730ae53d5895386d1b57dbc060evboxsync case 'J': /* Relative jump offset (ParseImmBRel + ParseImmVRel). */
8599686860198730ae53d5895386d1b57dbc060evboxsync RTUINTPTR uTrgAddr = pCpu->opaddr + pCpu->opsize + offDisplacement;
8599686860198730ae53d5895386d1b57dbc060evboxsync case 'A': /* Direct (jump/call) address (ParseImmAddr). */
8599686860198730ae53d5895386d1b57dbc060evboxsync switch (pParam->flags & (USE_IMMEDIATE_ADDR_16_16 | USE_IMMEDIATE_ADDR_16_32 | USE_DISPLACEMENT64 | USE_DISPLACEMENT32 | USE_DISPLACEMENT16))
8599686860198730ae53d5895386d1b57dbc060evboxsync Assert(*pszFmt == 'b' || *pszFmt == 'v'); pszFmt++;
8599686860198730ae53d5895386d1b57dbc060evboxsync switch (pParam->flags & (USE_IMMEDIATE_ADDR_16_16 | USE_IMMEDIATE_ADDR_16_32 | USE_DISPLACEMENT64 | USE_DISPLACEMENT32 | USE_DISPLACEMENT16))
8599686860198730ae53d5895386d1b57dbc060evboxsync Assert(*pszFmt == 'b' || *pszFmt == 'v'); pszFmt++;
8599686860198730ae53d5895386d1b57dbc060evboxsync const char *pszReg = MyDisasYasmFormatBaseReg(pCpu, pParam, &cchReg, 0);
8599686860198730ae53d5895386d1b57dbc060evboxsync case 'e': /* Register based on operand size (e.g. %eAX) (ParseFixedReg). */
8599686860198730ae53d5895386d1b57dbc060evboxsync Assert(RT_C_IS_ALPHA(pszFmt[0]) && RT_C_IS_ALPHA(pszFmt[1]) && !RT_C_IS_ALPHA(pszFmt[2])); pszFmt += 2;
8599686860198730ae53d5895386d1b57dbc060evboxsync const char *pszReg = MyDisasYasmFormatBaseReg(pCpu, pParam, &cchReg, 0);
8599686860198730ae53d5895386d1b57dbc060evboxsync AssertMsg(*pszFmt == ',' || *pszFmt == '\0', ("%c%s\n", ch, pszFmt));
8599686860198730ae53d5895386d1b57dbc060evboxsync } /* while more to format */
8599686860198730ae53d5895386d1b57dbc060evboxsync /* Terminate it - on overflow we'll have reserved one byte for this. */
8599686860198730ae53d5895386d1b57dbc060evboxsync /* clean up macros */
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync * Default style.
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync * @param pState The disassembler state.
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsyncstatic void MyDisasDefaultFormatter(PMYDISSTATE pState)
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync * Yasm style.
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync * @param pState The disassembler state.
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsyncstatic void MyDisasYasmFormatter(PMYDISSTATE pState)
8599686860198730ae53d5895386d1b57dbc060evboxsync /* a very quick hack. */
8fa1e8a8a8702ee38195fbe7ad5959bf971eb93bvboxsync strcpy(szTmp, RTStrStripL(strchr(pState->szLine, ':') + 1));
8599686860198730ae53d5895386d1b57dbc060evboxsync#else /* USE_MY_FORMATTER */
8599686860198730ae53d5895386d1b57dbc060evboxsync size_t cch = MyDisasYasmFormat(&pState->Cpu, szTmp, sizeof(szTmp));
8599686860198730ae53d5895386d1b57dbc060evboxsync#endif /* USE_MY_FORMATTER */
8599686860198730ae53d5895386d1b57dbc060evboxsync RTPrintf(" %s ; %08llu %s", szTmp, pState->uAddress, pState->szLine);
8599686860198730ae53d5895386d1b57dbc060evboxsync * Checks if the encoding of the current instruction is something
8599686860198730ae53d5895386d1b57dbc060evboxsync * we can never get the assembler to produce.
8599686860198730ae53d5895386d1b57dbc060evboxsync * @returns true if it's odd, false if it isn't.
8599686860198730ae53d5895386d1b57dbc060evboxsync * @param pCpu The disassembler output.
8599686860198730ae53d5895386d1b57dbc060evboxsyncstatic bool MyDisasYasmFormatterIsOddEncoding(PMYDISSTATE pState)
8599686860198730ae53d5895386d1b57dbc060evboxsync * Mod rm + SIB: Check for duplicate EBP encodings that yasm won't use for very good reasons.
8599686860198730ae53d5895386d1b57dbc060evboxsync if ( pState->Cpu.addrmode != CPUMODE_16BIT ///@todo correct?
8599686860198730ae53d5895386d1b57dbc060evboxsync /* No scaled index SIB (index=4), except for ESP. */
8599686860198730ae53d5895386d1b57dbc060evboxsync return true;
8599686860198730ae53d5895386d1b57dbc060evboxsync /* EBP + displacement */
8599686860198730ae53d5895386d1b57dbc060evboxsync return true;
8599686860198730ae53d5895386d1b57dbc060evboxsync * Seems to be an instruction alias here, but I cannot find any docs on it... hrmpf!
8599686860198730ae53d5895386d1b57dbc060evboxsync return true;
8599686860198730ae53d5895386d1b57dbc060evboxsync * Check for multiple prefixes of the same kind.
8599686860198730ae53d5895386d1b57dbc060evboxsync case 0x40: case 0x41: case 0x42: case 0x43: case 0x44: case 0x45: case 0x46: case 0x47:
8599686860198730ae53d5895386d1b57dbc060evboxsync case 0x48: case 0x49: case 0x4a: case 0x4b: case 0x4c: case 0x4d: case 0x4e: case 0x4f:
2cae8ff5782536dc236e1161d351356ba2ac5e0fvboxsync f = pState->Cpu.mode == CPUMODE_64BIT ? PREFIX_REX : 0;
8599686860198730ae53d5895386d1b57dbc060evboxsync break; /* done */
8599686860198730ae53d5895386d1b57dbc060evboxsync return true;
8599686860198730ae53d5895386d1b57dbc060evboxsync /* segment overrides are fun */
8599686860198730ae53d5895386d1b57dbc060evboxsync /* no efficient address which it may apply to. */
8599686860198730ae53d5895386d1b57dbc060evboxsync Assert((pState->Cpu.prefix & PREFIX_SEG) || pState->Cpu.mode == CPUMODE_64BIT);
8599686860198730ae53d5895386d1b57dbc060evboxsync if ( !(pState->Cpu.param1.flags & USE_EFFICIENT_ADDRESS)
8599686860198730ae53d5895386d1b57dbc060evboxsync && !(pState->Cpu.param2.flags & USE_EFFICIENT_ADDRESS)
8599686860198730ae53d5895386d1b57dbc060evboxsync && !(pState->Cpu.param3.flags & USE_EFFICIENT_ADDRESS))
8599686860198730ae53d5895386d1b57dbc060evboxsync return true;
8599686860198730ae53d5895386d1b57dbc060evboxsync /* fixed register + addr override doesn't go down all that well. */
8599686860198730ae53d5895386d1b57dbc060evboxsync && ( pState->Cpu.pCurInstr->param1 >= OP_PARM_REG_GEN32_START
8599686860198730ae53d5895386d1b57dbc060evboxsync && pState->Cpu.pCurInstr->param1 <= OP_PARM_REG_GEN32_END))
8599686860198730ae53d5895386d1b57dbc060evboxsync return true;
2cae8ff5782536dc236e1161d351356ba2ac5e0fvboxsync /* nop w/ prefix(es). */
2cae8ff5782536dc236e1161d351356ba2ac5e0fvboxsync return true;
2cae8ff5782536dc236e1161d351356ba2ac5e0fvboxsync /* There are probably a whole bunch of these... */
2cae8ff5782536dc236e1161d351356ba2ac5e0fvboxsync if ( pState->Cpu.pCurInstr->param1 >= OP_PARM_REG_SEG_START
2cae8ff5782536dc236e1161d351356ba2ac5e0fvboxsync && pState->Cpu.pCurInstr->param1 <= OP_PARM_REG_SEG_END)
2cae8ff5782536dc236e1161d351356ba2ac5e0fvboxsync return true;
2cae8ff5782536dc236e1161d351356ba2ac5e0fvboxsync && pState->Cpu.pCurInstr->param1 >= OP_PARM_REG_GEN32_START
2cae8ff5782536dc236e1161d351356ba2ac5e0fvboxsync && pState->Cpu.pCurInstr->param1 <= OP_PARM_REG_GEN32_END)
2cae8ff5782536dc236e1161d351356ba2ac5e0fvboxsync return true;
2cae8ff5782536dc236e1161d351356ba2ac5e0fvboxsync return true;
8599686860198730ae53d5895386d1b57dbc060evboxsync /* check for the version of xyz reg,reg instruction that the assembler doesn't use.
8599686860198730ae53d5895386d1b57dbc060evboxsync expected: 1aee sbb ch, dh ; SBB r8, r/m8
8599686860198730ae53d5895386d1b57dbc060evboxsync yasm: 18F5 sbb ch, dh ; SBB r/m8, r8 */
8599686860198730ae53d5895386d1b57dbc060evboxsync if ( ( pState->Cpu.pCurInstr->param1 == OP_PARM_Gb /* r8 */
8599686860198730ae53d5895386d1b57dbc060evboxsync && pState->Cpu.pCurInstr->param2 == OP_PARM_Eb /* r8/mem8 */)
8599686860198730ae53d5895386d1b57dbc060evboxsync || ( pState->Cpu.pCurInstr->param1 == OP_PARM_Gv /* rX */
8599686860198730ae53d5895386d1b57dbc060evboxsync && pState->Cpu.pCurInstr->param2 == OP_PARM_Ev /* rX/memX */))
8599686860198730ae53d5895386d1b57dbc060evboxsync return true;
2cae8ff5782536dc236e1161d351356ba2ac5e0fvboxsync /* 82 (see table A-6). */
2cae8ff5782536dc236e1161d351356ba2ac5e0fvboxsync return true;
8599686860198730ae53d5895386d1b57dbc060evboxsync /* ff /0, fe /0, ff /1, fe /0 */
8599686860198730ae53d5895386d1b57dbc060evboxsync return true;
2cae8ff5782536dc236e1161d351356ba2ac5e0fvboxsync return true;
2cae8ff5782536dc236e1161d351356ba2ac5e0fvboxsync /* And some more - see table A-6. */
2cae8ff5782536dc236e1161d351356ba2ac5e0fvboxsync return true;
8599686860198730ae53d5895386d1b57dbc060evboxsync /* check for REX.X = 1 without SIB. */
8599686860198730ae53d5895386d1b57dbc060evboxsync /* Yasm encodes setnbe al with /2 instead of /0 like the AMD manual
8599686860198730ae53d5895386d1b57dbc060evboxsync says (intel doesn't appear to care). */
8599686860198730ae53d5895386d1b57dbc060evboxsync AssertMsg(pState->Cpu.opcode >= 0x90 && pState->Cpu.opcode <= 0x9f, ("%#x\n", pState->Cpu.opcode));
8599686860198730ae53d5895386d1b57dbc060evboxsync return true;
2cae8ff5782536dc236e1161d351356ba2ac5e0fvboxsync * The MOVZX reg32,mem16 instruction without an operand size prefix
2cae8ff5782536dc236e1161d351356ba2ac5e0fvboxsync * doesn't quite make sense...
2cae8ff5782536dc236e1161d351356ba2ac5e0fvboxsync && (pState->Cpu.mode == CPUMODE_16BIT) != !!(fPrefixes & PREFIX_OPSIZE))
2cae8ff5782536dc236e1161d351356ba2ac5e0fvboxsync return true;
8599686860198730ae53d5895386d1b57dbc060evboxsync return false;
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync * Masm style.
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync * @param pState The disassembler state.
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsyncstatic void MyDisasMasmFormatter(PMYDISSTATE pState)
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync RTPrintf("masm not implemented: %s", pState->szLine);
8599686860198730ae53d5895386d1b57dbc060evboxsync * This is a temporary workaround for catching a few illegal opcodes
8599686860198730ae53d5895386d1b57dbc060evboxsync * that the disassembler is currently letting thru, just enough to make
8599686860198730ae53d5895386d1b57dbc060evboxsync * the assemblers happy.
8599686860198730ae53d5895386d1b57dbc060evboxsync * We're too close to a release to dare mess with these things now as
8599686860198730ae53d5895386d1b57dbc060evboxsync * they may consequences for performance and let alone introduce bugs.
8599686860198730ae53d5895386d1b57dbc060evboxsync * @returns true if it's valid. false if it isn't.
8599686860198730ae53d5895386d1b57dbc060evboxsync * @param pCpu The disassembler output.
8599686860198730ae53d5895386d1b57dbc060evboxsyncstatic bool MyDisasIsValidInstruction(DISCPUSTATE const *pCpu)
8599686860198730ae53d5895386d1b57dbc060evboxsync /* These doesn't take memory operands. */
8599686860198730ae53d5895386d1b57dbc060evboxsync return false;
8599686860198730ae53d5895386d1b57dbc060evboxsync /* The 0x8f /0 variant of this instruction doesn't get its /r value verified. */
8599686860198730ae53d5895386d1b57dbc060evboxsync return false;
8599686860198730ae53d5895386d1b57dbc060evboxsync /* The 0xc6 /0 and 0xc7 /0 variants of this instruction don't get their /r values verified. */
8599686860198730ae53d5895386d1b57dbc060evboxsync return false;
8599686860198730ae53d5895386d1b57dbc060evboxsync return true;
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync * Callback for reading bytes.
8599686860198730ae53d5895386d1b57dbc060evboxsync * @todo This should check that the disassembler doesn't do unnecessary reads,
8599686860198730ae53d5895386d1b57dbc060evboxsync * however the current doesn't do this and is just complicated...
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsyncstatic DECLCALLBACK(int) MyDisasInstrRead(RTUINTPTR uSrcAddr, uint8_t *pbDst, uint32_t cbRead, void *pvDisCpu)
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync * Straight forward reading.
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync * Jumping up the stream.
7748b9362d6a39df9045d5d05ccb57871145a649vboxsync * This occures when the byte sequence is added to the output string.
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync /* reset the stream. */
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync /* skip ahead. */
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync /* do the reading. */
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync RTStrmPrintf(g_pStdErr, "Reading before current instruction!\n");
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync * Disassembles a block of memory.
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync * @returns VBox status code.
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync * @param argv0 Program name (for errors and warnings).
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync * @param enmCpuMode The cpu mode to disassemble in.
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync * @param uAddress The address we're starting to disassemble at.
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync * @param pbFile Where to start disassemble.
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync * @param cbFile How much to disassemble.
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync * @param enmStyle The assembly output style.
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync * @param fListing Whether to print in a listing like mode.
7748b9362d6a39df9045d5d05ccb57871145a649vboxsync * @param enmUndefOp How to deal with undefined opcodes.
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsyncstatic int MyDisasmBlock(const char *argv0, DISCPUMODE enmCpuMode, uint64_t uAddress, uint8_t *pbFile, size_t cbFile,
7748b9362d6a39df9045d5d05ccb57871145a649vboxsync ASMSTYLE enmStyle, bool fListing, UNDEFOPHANDLING enmUndefOp)
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync * Initialize the CPU context.
8fa1e8a8a8702ee38195fbe7ad5959bf971eb93bvboxsync RTPrintf(" BITS %d\n", enmCpuMode == CPUMODE_16BIT ? 16 : enmCpuMode == CPUMODE_32BIT ? 32 : 64);
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync * The loop.
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync * Disassemble it.
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync int rc = DISInstr(&State.Cpu, State.uAddress, 0, &State.cbInstr, State.szLine);
8599686860198730ae53d5895386d1b57dbc060evboxsync if (State.fUndefOp && State.enmUndefOp == kUndefOp_DefineByte)
8599686860198730ae53d5895386d1b57dbc060evboxsync State.Cpu.pfnReadBytes(State.uAddress + off, &b, 1, &State.Cpu);
8599686860198730ae53d5895386d1b57dbc060evboxsync else if (!State.fUndefOp && State.enmUndefOp == kUndefOp_All)
8fa1e8a8a8702ee38195fbe7ad5959bf971eb93bvboxsync RTPrintf("%s: error at %#RX64: unexpected valid instruction (op=%d)\n", argv0, State.uAddress, State.Cpu.pCurInstr->opcode);
7748b9362d6a39df9045d5d05ccb57871145a649vboxsync else if (State.fUndefOp && State.enmUndefOp == kUndefOp_Fail)
7748b9362d6a39df9045d5d05ccb57871145a649vboxsync RTPrintf("%s: error at %#RX64: undefined opcode (op=%d)\n", argv0, State.uAddress, State.Cpu.pCurInstr->opcode);
8599686860198730ae53d5895386d1b57dbc060evboxsync /* Use db for odd encodings that we can't make the assembler use. */
8599686860198730ae53d5895386d1b57dbc060evboxsync State.Cpu.pfnReadBytes(State.uAddress + off, &b, 1, &State.Cpu);
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync RTPrintf("%s: error at %#RX64: read beyond the end (%Rrc)\n", argv0, State.uAddress, rc);
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync RTPrintf("%s: error at %#RX64: %Rrc cbInstr=%d\n", argv0, State.uAddress, rc, State.cbInstr);
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync RTPrintf("%s: error at %#RX64: %Rrc cbInstr=%d!\n", argv0, State.uAddress, rc, State.cbInstr);
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync * Prints usage info.
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync * @returns 1.
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync * @param argv0 The program name.
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync"usage: %s [options] <file1> [file2..fileN]\n"
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync" or: %s <--help|-h>\n"
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync"Options:\n"
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync" --address|-a <address>\n"
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync" The base address. Default: 0\n"
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync" --max-bytes|-b <bytes>\n"
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync" The maximum number of bytes to disassemble. Default: 1GB\n"
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync" --cpumode|-c <16|32|64>\n"
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync" The cpu mode. Default: 32\n"
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync" --listing|-l, --no-listing|-L\n"
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync" Enables or disables listing mode. Default: --no-listing\n"
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync" --offset|-o <offset>\n"
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync" The file offset at which to start disassembling. Default: 0\n"
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync" --style|-s <default|yasm|masm>\n"
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync" The assembly output style. Default: default\n"
7748b9362d6a39df9045d5d05ccb57871145a649vboxsync" --undef-op|-u <fail|all|db>\n"
7748b9362d6a39df9045d5d05ccb57871145a649vboxsync" How to treat undefined opcodes. Default: fail\n"
8fa1e8a8a8702ee38195fbe7ad5959bf971eb93bvboxsync const char * const argv0 = RTPathFilename(argv[0]);
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync /* options */
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync bool fListing = true;
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync * Parse arguments.
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync while ((ch = RTGetOpt(argc, argv, g_aOptions, RT_ELEMENTS(g_aOptions), &iArg, &ValueUnion)))
8fa1e8a8a8702ee38195fbe7ad5959bf971eb93bvboxsync RTStrmPrintf(g_pStdErr, "%s: Invalid CPU mode value %RU32\n", argv0, ValueUnion.u32);
8fa1e8a8a8702ee38195fbe7ad5959bf971eb93bvboxsync RTStrmPrintf(g_pStdErr, "%s: masm style isn't implemented yet\n", argv0);
8fa1e8a8a8702ee38195fbe7ad5959bf971eb93bvboxsync RTStrmPrintf(g_pStdErr, "%s: unknown assembly style: %s\n", argv0, ValueUnion.psz);
7748b9362d6a39df9045d5d05ccb57871145a649vboxsync RTStrmPrintf(g_pStdErr, "%s: unknown undefined opcode handling method: %s\n", argv0, ValueUnion.psz);
8fa1e8a8a8702ee38195fbe7ad5959bf971eb93bvboxsync RTStrmPrintf(g_pStdErr, "%s: syntax error: %Rrc\n", argv0, ch);
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync * Process the files.
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync * Read the file into memory.
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync rc = RTFileReadAllEx(argv[iArg], off, cbMax, 0, &pvFile, &cbFile);
8fa1e8a8a8702ee38195fbe7ad5959bf971eb93bvboxsync RTStrmPrintf(g_pStdErr, "%s: %s: %Rrc\n", argv0, argv[iArg], rc);
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync * Disassemble it.