DisasmFormatYasm.cpp revision a0892a0a33b8ffaa8ff2f252411176f63e8d9f18
af062818b47340eef15700d2f0211576ba3506eevboxsync * VBox Disassembler - Yasm(/Nasm) Style Formatter.
af062818b47340eef15700d2f0211576ba3506eevboxsync * Copyright (C) 2008 Oracle Corporation
af062818b47340eef15700d2f0211576ba3506eevboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
af062818b47340eef15700d2f0211576ba3506eevboxsync * available from http://www.virtualbox.org. This file is free software;
af062818b47340eef15700d2f0211576ba3506eevboxsync * you can redistribute it and/or modify it under the terms of the GNU
af062818b47340eef15700d2f0211576ba3506eevboxsync * General Public License (GPL) as published by the Free Software
af062818b47340eef15700d2f0211576ba3506eevboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
af062818b47340eef15700d2f0211576ba3506eevboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
af062818b47340eef15700d2f0211576ba3506eevboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync/*******************************************************************************
4b9d6701570cb98fd36e209314239d104ec584d3vboxsync* Header Files *
4b9d6701570cb98fd36e209314239d104ec584d3vboxsync*******************************************************************************/
af062818b47340eef15700d2f0211576ba3506eevboxsync/*******************************************************************************
af062818b47340eef15700d2f0211576ba3506eevboxsync* Global Variables *
af062818b47340eef15700d2f0211576ba3506eevboxsync*******************************************************************************/
af062818b47340eef15700d2f0211576ba3506eevboxsyncstatic const char g_szSpaces[] =
af062818b47340eef15700d2f0211576ba3506eevboxsync "al\0\0", "cl\0\0", "dl\0\0", "bl\0\0", "ah\0\0", "ch\0\0", "dh\0\0", "bh\0\0", "r8b\0", "r9b\0", "r10b", "r11b", "r12b", "r13b", "r14b", "r15b", "spl\0", "bpl\0", "sil\0", "dil\0"
af062818b47340eef15700d2f0211576ba3506eevboxsync "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"
af062818b47340eef15700d2f0211576ba3506eevboxsync "bx+si", "bx+di", "bp+si", "bp+di", "si\0\0\0", "di\0\0\0", "bp\0\0\0", "bx\0\0\0"
af062818b47340eef15700d2f0211576ba3506eevboxsync "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"
af062818b47340eef15700d2f0211576ba3506eevboxsync "rax", "rcx", "rdx", "rbx", "rsp", "rbp", "rsi", "rdi", "r8\0", "r9\0", "r10", "r11", "r12", "r13", "r14", "r15"
af062818b47340eef15700d2f0211576ba3506eevboxsync "st0", "st1", "st2", "st3", "st4", "st5", "st6", "st7"
af062818b47340eef15700d2f0211576ba3506eevboxsync "mm0", "mm1", "mm2", "mm3", "mm4", "mm5", "mm6", "mm7"
af062818b47340eef15700d2f0211576ba3506eevboxsync "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"
af062818b47340eef15700d2f0211576ba3506eevboxsync "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"
"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"
"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"
static const char *disasmFormatYasmBaseReg(PCDISCPUSTATE pCpu, PCOP_PARAMETER pParam, size_t *pcchReg)
case USE_REG_GEN8:
return psz;
case USE_REG_GEN16:
return psz;
case USE_REG_GEN32:
return psz;
case USE_REG_GEN64:
return psz;
case USE_REG_FP:
return psz;
case USE_REG_MMX:
return psz;
case USE_REG_XMM:
return psz;
case USE_REG_CR:
return psz;
case USE_REG_DBG:
return psz;
case USE_REG_SEG:
return psz;
case USE_REG_TEST:
return psz;
static const char *disasmFormatYasmIndexReg(PCDISCPUSTATE pCpu, PCOP_PARAMETER pParam, size_t *pcchReg)
case CPUMODE_16BIT:
return psz;
case CPUMODE_32BIT:
return psz;
case CPUMODE_64BIT:
return psz;
cchOutput++; \
cchDst--; \
case OP_JECXZ:
pszFmt = pCpu->opmode == CPUMODE_16BIT ? "jcxz %Jb" : pCpu->opmode == CPUMODE_32BIT ? "jecxz %Jb" : "jrcxz %Jb";
case OP_PUSHF:
pszFmt = pCpu->opmode == CPUMODE_16BIT ? "pushfw" : pCpu->opmode == CPUMODE_32BIT ? "pushfd" : "pushfq";
case OP_POPF:
pszFmt = pCpu->opmode == CPUMODE_16BIT ? "popfw" : pCpu->opmode == CPUMODE_32BIT ? "popfd" : "popfq";
case OP_PUSHA:
case OP_POPA:
case OP_INSB:
case OP_INSWD:
case OP_OUTSB:
case OP_OUTSWD:
pszFmt = pCpu->opmode == CPUMODE_16BIT ? "outsw" : pCpu->opmode == CPUMODE_32BIT ? "outsd" : "outsq";
case OP_MOVSB:
case OP_MOVSWD:
pszFmt = pCpu->opmode == CPUMODE_16BIT ? "movsw" : pCpu->opmode == CPUMODE_32BIT ? "movsd" : "movsq";
case OP_CMPSB:
case OP_CMPWD:
pszFmt = pCpu->opmode == CPUMODE_16BIT ? "cmpsw" : pCpu->opmode == CPUMODE_32BIT ? "cmpsd" : "cmpsq";
case OP_SCASB:
case OP_SCASWD:
pszFmt = pCpu->opmode == CPUMODE_16BIT ? "scasw" : pCpu->opmode == CPUMODE_32BIT ? "scasd" : "scasq";
case OP_LODSB:
case OP_LODSWD:
pszFmt = pCpu->opmode == CPUMODE_16BIT ? "lodsw" : pCpu->opmode == CPUMODE_32BIT ? "lodsd" : "lodsq";
case OP_STOSB:
case OP_STOSWD:
pszFmt = pCpu->opmode == CPUMODE_16BIT ? "stosw" : pCpu->opmode == CPUMODE_32BIT ? "stosd" : "stosq";
case OP_CBW:
case OP_CWD:
case OP_SHL:
case OP_XLAT:
case OP_INT3:
case OP_NOP:
char ch;
case OP_FLD:
#define PUT_FAR() \
/** @todo drop the work/dword/qword override when the src/dst is a register (except for movsx/movzx). */
#define PUT_SIZE_OVERRIDE() \
case OP_PARM_v: \
case OP_PARM_dq: \
if (OP_PARM_VTYPE(pParam->param) != OP_PARM_W) /* these are 128 bit, pray they are all unambiguous.. */ \
case OP_PARM_z: break; \
case OP_PARM_NONE: \
#define PUT_SEGMENT_OVERRIDE() \
char ch;
switch (ch)
Assert(!(pParam->flags & (USE_DISPLACEMENT8 | USE_DISPLACEMENT16 | USE_DISPLACEMENT32 | USE_DISPLACEMENT64 | USE_RIPDISPLACEMENT32)));
PUT_FAR();
&& (pParam->flags & (USE_DISPLACEMENT8 | USE_DISPLACEMENT16 | USE_DISPLACEMENT32 | USE_DISPLACEMENT64 | USE_RIPDISPLACEMENT32)))
bool fBase = (pParam->flags & USE_BASE) /* When exactly is USE_BASE supposed to be set? disasmModRMReg doesn't set it. */
if (fBase)
if (fBase)
if (pParam->flags & (USE_DISPLACEMENT8 | USE_DISPLACEMENT16 | USE_DISPLACEMENT32 | USE_DISPLACEMENT64 | USE_RIPDISPLACEMENT32))
AssertFailed();
off2 = 0;
if (off2 < 0)
AssertFailed();
case 'I': /* Immediate data (ParseImmByte, ParseImmByteSX, ParseImmV, ParseImmUshort, ParseImmZ). */
case USE_IMMEDIATE8:
case USE_IMMEDIATE16:
case USE_IMMEDIATE16_SX8:
case USE_IMMEDIATE32:
if ( pCpu->opmode != (pCpu->mode == CPUMODE_16BIT ? CPUMODE_16BIT : CPUMODE_32BIT) /* not perfect */
case USE_IMMEDIATE32_SX8:
case USE_IMMEDIATE64_SX8:
case USE_IMMEDIATE64:
AssertFailed();
if (fPrefix)
if (fPrefix)
if (fPrefix)
if (pfnGetSymbol)
int rc = pfnGetSymbol(pCpu, DIS_FMT_SEL_FROM_REG(DIS_SELREG_CS), uTrgAddr, szSymbol, sizeof(szSymbol), &off, pvUser);
if (off != 0)
PUT_FAR();
switch (pParam->flags & (USE_IMMEDIATE_ADDR_16_16 | USE_IMMEDIATE_ADDR_16_32 | USE_DISPLACEMENT64 | USE_DISPLACEMENT32 | USE_DISPLACEMENT16))
case USE_IMMEDIATE_ADDR_16_16:
if (pfnGetSymbol)
rc = pfnGetSymbol(pCpu, DIS_FMT_SEL_FROM_VALUE(pParam->parval >> 16), (uint16_t)pParam->parval, szSymbol, sizeof(szSymbol), &off, pvUser);
case USE_IMMEDIATE_ADDR_16_32:
if (pfnGetSymbol)
rc = pfnGetSymbol(pCpu, DIS_FMT_SEL_FROM_VALUE(pParam->parval >> 16), (uint32_t)pParam->parval, szSymbol, sizeof(szSymbol), &off, pvUser);
case USE_DISPLACEMENT16:
if (pfnGetSymbol)
rc = pfnGetSymbol(pCpu, DIS_FMT_SEL_FROM_REG(DIS_SELREG_CS), (uint16_t)pParam->parval, szSymbol, sizeof(szSymbol), &off, pvUser);
case USE_DISPLACEMENT32:
if (pfnGetSymbol)
rc = pfnGetSymbol(pCpu, DIS_FMT_SEL_FROM_REG(DIS_SELREG_CS), (uint32_t)pParam->parval, szSymbol, sizeof(szSymbol), &off, pvUser);
case USE_DISPLACEMENT64:
if (pfnGetSymbol)
rc = pfnGetSymbol(pCpu, DIS_FMT_SEL_FROM_REG(DIS_SELREG_CS), (uint64_t)pParam->parval, szSymbol, sizeof(szSymbol), &off, pvUser);
AssertFailed();
if (off != 0)
PUT_FAR();
switch (pParam->flags & (USE_IMMEDIATE_ADDR_16_16 | USE_IMMEDIATE_ADDR_16_32 | USE_DISPLACEMENT64 | USE_DISPLACEMENT32 | USE_DISPLACEMENT16))
case USE_IMMEDIATE_ADDR_16_16:
if (pfnGetSymbol)
rc = pfnGetSymbol(pCpu, DIS_FMT_SEL_FROM_VALUE(pParam->parval >> 16), (uint16_t)pParam->parval, szSymbol, sizeof(szSymbol), &off, pvUser);
case USE_IMMEDIATE_ADDR_16_32:
if (pfnGetSymbol)
rc = pfnGetSymbol(pCpu, DIS_FMT_SEL_FROM_VALUE(pParam->parval >> 16), (uint32_t)pParam->parval, szSymbol, sizeof(szSymbol), &off, pvUser);
case USE_DISPLACEMENT16:
if (pfnGetSymbol)
rc = pfnGetSymbol(pCpu, DIS_FMT_SEL_FROM_REG(DIS_SELREG_CS), pParam->uDisp.u16, szSymbol, sizeof(szSymbol), &off, pvUser);
case USE_DISPLACEMENT32:
if (pfnGetSymbol)
rc = pfnGetSymbol(pCpu, DIS_FMT_SEL_FROM_REG(DIS_SELREG_CS), pParam->uDisp.u32, szSymbol, sizeof(szSymbol), &off, pvUser);
case USE_DISPLACEMENT64:
if (pfnGetSymbol)
rc = pfnGetSymbol(pCpu, DIS_FMT_SEL_FROM_REG(DIS_SELREG_CS), pParam->uDisp.u64, szSymbol, sizeof(szSymbol), &off, pvUser);
AssertFailed();
if (off != 0)
PUT_FAR();
Assert(RT_C_IS_ALPHA(pszFmt[0]) && RT_C_IS_ALPHA(pszFmt[1]) && !RT_C_IS_ALPHA(pszFmt[2])); pszFmt += 2;
switch (++iParam)
if (cchDst > 0)
return cchOutput;
return DISFormatYasmEx(pCpu, pszBuf, cchBuf, 0 /* fFlags */, NULL /* pfnGetSymbol */, NULL /* pvUser */);
uint32_t f;
f = PREFIX_LOCK;
f = PREFIX_SEG;
f = PREFIX_OPSIZE;
f = PREFIX_ADDRSIZE;
if (fPrefixes & f)
fPrefixes |= f;
if (fPrefixes)
case OP_NOP:
case OP_JMP:
case OP_JO:
case OP_JNO:
case OP_JC:
case OP_JNC:
case OP_JE:
case OP_JNE:
case OP_JBE:
case OP_JNBE:
case OP_JS:
case OP_JNS:
case OP_JP:
case OP_JNP:
case OP_JL:
case OP_JNL:
case OP_JLE:
case OP_JNLE:
case OP_POP:
case OP_PUSH:
case OP_POPA:
case OP_POPF:
case OP_PUSHA:
case OP_PUSHF:
case OP_ADD:
case OP_OR:
case OP_ADC:
case OP_SBB:
case OP_AND:
case OP_SUB:
case OP_XOR:
case OP_CMP:
case OP_ADD:
case OP_OR:
case OP_ADC:
case OP_SBB:
case OP_AND:
case OP_SUB:
case OP_XOR:
case OP_CMP:
case OP_DEC:
case OP_INC:
case OP_POP:
case OP_PUSH:
case OP_MOV:
case OP_SHL:
case OP_SHR:
case OP_SAR:
case OP_RCL:
case OP_RCR:
case OP_ROL:
case OP_ROR:
case OP_ADD:
case OP_OR:
case OP_ADC:
case OP_SBB:
case OP_AND:
case OP_SUB:
case OP_XOR:
case OP_CMP:
case OP_SETO:
case OP_SETNO:
case OP_SETC:
case OP_SETNC:
case OP_SETE:
case OP_SETNE:
case OP_SETBE:
case OP_SETNBE:
case OP_SETS:
case OP_SETNS:
case OP_SETP:
case OP_SETNP:
case OP_SETL:
case OP_SETNL:
case OP_SETLE:
case OP_SETNLE: