2006-04-27 19:11:45 +04:00
|
|
|
/////////////////////////////////////////////////////////////////////////
|
2011-02-25 01:05:47 +03:00
|
|
|
// $Id$
|
2009-10-15 00:45:29 +04:00
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
|
|
// Copyright (c) 2005-2009 Stanislav Shwartsman
|
|
|
|
// Written by Stanislav Shwartsman [sshwarts at sourceforge net]
|
|
|
|
//
|
|
|
|
// This library is free software; you can redistribute it and/or
|
|
|
|
// modify it under the terms of the GNU Lesser General Public
|
|
|
|
// License as published by the Free Software Foundation; either
|
|
|
|
// version 2 of the License, or (at your option) any later version.
|
|
|
|
//
|
|
|
|
// This library is distributed in the hope that it will be useful,
|
|
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
// Lesser General Public License for more details.
|
|
|
|
//
|
|
|
|
// You should have received a copy of the GNU Lesser General Public
|
|
|
|
// License along with this library; if not, write to the Free Software
|
|
|
|
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
|
|
//
|
2006-04-27 19:11:45 +04:00
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
|
|
|
2004-12-08 21:54:15 +03:00
|
|
|
#include <stdio.h>
|
2006-08-11 21:23:36 +04:00
|
|
|
#include <assert.h>
|
2003-12-24 23:44:39 +03:00
|
|
|
#include "disasm.h"
|
|
|
|
|
2005-12-23 17:15:13 +03:00
|
|
|
void disassembler::decode_modrm(x86_insn *insn)
|
2003-12-24 23:44:39 +03:00
|
|
|
{
|
2005-12-23 17:15:13 +03:00
|
|
|
insn->modrm = fetch_byte();
|
|
|
|
BX_DECODE_MODRM(insn->modrm, insn->mod, insn->nnn, insn->rm);
|
2006-06-27 01:06:26 +04:00
|
|
|
// MOVs with CRx and DRx always use register ops and ignore the mod field.
|
|
|
|
if ((insn->b1 & ~3) == 0x120) insn->mod = 3;
|
2005-12-23 17:15:13 +03:00
|
|
|
insn->nnn |= insn->rex_r;
|
2007-11-15 01:49:51 +03:00
|
|
|
insn->rm |= insn->rex_b;
|
2003-12-24 23:44:39 +03:00
|
|
|
|
2005-12-23 17:15:13 +03:00
|
|
|
if (insn->mod == 3) {
|
2007-11-15 01:49:51 +03:00
|
|
|
return; /* mod, reg, reg */
|
2005-12-23 17:15:13 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
if (insn->as_64)
|
2003-12-24 23:44:39 +03:00
|
|
|
{
|
2007-11-15 01:49:51 +03:00
|
|
|
if ((insn->rm & 7) != 4) { /* rm != 100b, no s-i-b byte */
|
2003-12-24 23:44:39 +03:00
|
|
|
// one byte modrm
|
2005-12-23 17:15:13 +03:00
|
|
|
switch (insn->mod) {
|
|
|
|
case 0:
|
|
|
|
resolve_modrm = &disassembler::resolve64_mod0;
|
2006-08-11 21:23:36 +04:00
|
|
|
if ((insn->rm & 7) == 5) /* no reg, 32-bit displacement */
|
2005-12-23 17:15:13 +03:00
|
|
|
insn->displacement.displ32 = fetch_dword();
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
/* reg, 8-bit displacement, sign extend */
|
|
|
|
resolve_modrm = &disassembler::resolve64_mod1or2;
|
|
|
|
insn->displacement.displ32 = (Bit8s) fetch_byte();
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
/* reg, 32-bit displacement */
|
|
|
|
resolve_modrm = &disassembler::resolve64_mod1or2;
|
|
|
|
insn->displacement.displ32 = fetch_dword();
|
|
|
|
break;
|
|
|
|
} /* switch (mod) */
|
|
|
|
} /* if (rm != 4) */
|
|
|
|
else { /* rm == 4, s-i-b byte follows */
|
|
|
|
insn->sib = fetch_byte();
|
|
|
|
BX_DECODE_SIB(insn->sib, insn->scale, insn->index, insn->base);
|
2006-08-11 21:23:36 +04:00
|
|
|
insn->base |= insn->rex_b;
|
|
|
|
insn->index |= insn->rex_x;
|
2005-12-23 17:15:13 +03:00
|
|
|
|
|
|
|
switch (insn->mod) {
|
|
|
|
case 0:
|
|
|
|
resolve_modrm = &disassembler::resolve64_mod0_rm4;
|
2006-08-11 21:23:36 +04:00
|
|
|
if ((insn->base & 7) == 5)
|
2005-12-23 17:15:13 +03:00
|
|
|
insn->displacement.displ32 = fetch_dword();
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
resolve_modrm = &disassembler::resolve64_mod1or2_rm4;
|
|
|
|
insn->displacement.displ32 = (Bit8s) fetch_byte();
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
resolve_modrm = &disassembler::resolve64_mod1or2_rm4;
|
|
|
|
insn->displacement.displ32 = fetch_dword();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
} /* s-i-b byte follows */
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (insn->as_32)
|
|
|
|
{
|
2007-11-15 01:49:51 +03:00
|
|
|
if ((insn->rm & 7) != 4) { /* rm != 100b, no s-i-b byte */
|
2005-12-23 17:15:13 +03:00
|
|
|
// one byte modrm
|
|
|
|
switch (insn->mod) {
|
2003-12-24 23:44:39 +03:00
|
|
|
case 0:
|
|
|
|
resolve_modrm = &disassembler::resolve32_mod0;
|
2006-08-11 21:23:36 +04:00
|
|
|
if ((insn->rm & 7) == 5) /* no reg, 32-bit displacement */
|
2005-12-23 17:15:13 +03:00
|
|
|
insn->displacement.displ32 = fetch_dword();
|
2003-12-24 23:44:39 +03:00
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
/* reg, 8-bit displacement, sign extend */
|
2004-12-08 21:54:15 +03:00
|
|
|
resolve_modrm = &disassembler::resolve32_mod1or2;
|
2005-12-23 17:15:13 +03:00
|
|
|
insn->displacement.displ32 = (Bit8s) fetch_byte();
|
2003-12-24 23:44:39 +03:00
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
/* reg, 32-bit displacement */
|
2004-12-08 21:54:15 +03:00
|
|
|
resolve_modrm = &disassembler::resolve32_mod1or2;
|
2005-12-23 17:15:13 +03:00
|
|
|
insn->displacement.displ32 = fetch_dword();
|
2003-12-24 23:44:39 +03:00
|
|
|
break;
|
|
|
|
} /* switch (mod) */
|
|
|
|
} /* if (rm != 4) */
|
|
|
|
else { /* rm == 4, s-i-b byte follows */
|
2005-12-23 17:15:13 +03:00
|
|
|
insn->sib = fetch_byte();
|
|
|
|
BX_DECODE_SIB(insn->sib, insn->scale, insn->index, insn->base);
|
|
|
|
insn->base |= insn->rex_b;
|
|
|
|
insn->index |= insn->rex_x;
|
2003-12-24 23:44:39 +03:00
|
|
|
|
2005-12-23 17:15:13 +03:00
|
|
|
switch (insn->mod) {
|
2003-12-24 23:44:39 +03:00
|
|
|
case 0:
|
|
|
|
resolve_modrm = &disassembler::resolve32_mod0_rm4;
|
2006-08-11 21:23:36 +04:00
|
|
|
if ((insn->base & 7) == 5)
|
2005-12-23 17:15:13 +03:00
|
|
|
insn->displacement.displ32 = fetch_dword();
|
2003-12-24 23:44:39 +03:00
|
|
|
break;
|
|
|
|
case 1:
|
2004-12-08 21:54:15 +03:00
|
|
|
resolve_modrm = &disassembler::resolve32_mod1or2_rm4;
|
2005-12-23 17:15:13 +03:00
|
|
|
insn->displacement.displ32 = (Bit8s) fetch_byte();
|
2003-12-24 23:44:39 +03:00
|
|
|
break;
|
|
|
|
case 2:
|
2004-12-08 21:54:15 +03:00
|
|
|
resolve_modrm = &disassembler::resolve32_mod1or2_rm4;
|
2005-12-23 17:15:13 +03:00
|
|
|
insn->displacement.displ32 = fetch_dword();
|
2003-12-24 23:44:39 +03:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
} /* s-i-b byte follows */
|
2005-12-23 17:15:13 +03:00
|
|
|
}
|
|
|
|
else {
|
2006-08-11 21:23:36 +04:00
|
|
|
assert(insn->rex_b == 0);
|
|
|
|
assert(insn->rex_x == 0);
|
|
|
|
assert(insn->rex_r == 0);
|
2005-12-23 17:15:13 +03:00
|
|
|
/* 16 bit addressing modes. */
|
|
|
|
switch (insn->mod) {
|
|
|
|
case 0:
|
|
|
|
resolve_modrm = &disassembler::resolve16_mod0;
|
|
|
|
if(insn->rm == 6)
|
|
|
|
insn->displacement.displ16 = fetch_word();
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
/* reg, 8-bit displacement, sign extend */
|
|
|
|
resolve_modrm = &disassembler::resolve16_mod1or2;
|
|
|
|
insn->displacement.displ16 = (Bit8s) fetch_byte();
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
resolve_modrm = &disassembler::resolve16_mod1or2;
|
|
|
|
insn->displacement.displ16 = fetch_word();
|
|
|
|
break;
|
|
|
|
} /* switch (mod) ... */
|
|
|
|
}
|
2003-12-24 23:44:39 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-12-23 17:15:13 +03:00
|
|
|
void disassembler::resolve16_mod0(const x86_insn *insn, unsigned mode)
|
2003-12-24 23:44:39 +03:00
|
|
|
{
|
2004-12-08 21:54:15 +03:00
|
|
|
const char *seg;
|
2003-12-24 23:44:39 +03:00
|
|
|
|
2006-01-31 20:42:31 +03:00
|
|
|
if (insn->is_seg_override())
|
2005-12-23 17:15:13 +03:00
|
|
|
seg = segment_name[insn->seg_override];
|
2003-12-24 23:44:39 +03:00
|
|
|
else
|
2005-12-23 17:15:13 +03:00
|
|
|
seg = sreg_mod00_rm16[insn->rm];
|
2003-12-24 23:44:39 +03:00
|
|
|
|
2005-12-23 17:15:13 +03:00
|
|
|
if(insn->rm == 6)
|
|
|
|
print_memory_access16(mode, seg, NULL, insn->displacement.displ16);
|
2003-12-24 23:44:39 +03:00
|
|
|
else
|
2005-12-23 17:15:13 +03:00
|
|
|
print_memory_access16(mode, seg, index16[insn->rm], 0);
|
2003-12-24 23:44:39 +03:00
|
|
|
}
|
|
|
|
|
2005-12-23 17:15:13 +03:00
|
|
|
void disassembler::resolve16_mod1or2(const x86_insn *insn, unsigned mode)
|
2003-12-24 23:44:39 +03:00
|
|
|
{
|
2004-12-08 21:54:15 +03:00
|
|
|
const char *seg;
|
2003-12-24 23:44:39 +03:00
|
|
|
|
2006-01-31 20:42:31 +03:00
|
|
|
if (insn->is_seg_override())
|
2005-12-23 17:15:13 +03:00
|
|
|
seg = segment_name[insn->seg_override];
|
2003-12-24 23:44:39 +03:00
|
|
|
else
|
2005-12-23 17:15:13 +03:00
|
|
|
seg = sreg_mod01or10_rm16[insn->rm];
|
2003-12-24 23:44:39 +03:00
|
|
|
|
2005-12-23 17:15:13 +03:00
|
|
|
print_memory_access16(mode, seg, index16[insn->rm], insn->displacement.displ16);
|
2003-12-24 23:44:39 +03:00
|
|
|
}
|
|
|
|
|
2005-12-23 17:15:13 +03:00
|
|
|
void disassembler::resolve32_mod0(const x86_insn *insn, unsigned mode)
|
2003-12-24 23:44:39 +03:00
|
|
|
{
|
2007-04-10 01:15:00 +04:00
|
|
|
const char *seg, *eip_regname = NULL;
|
2003-12-24 23:44:39 +03:00
|
|
|
|
2006-01-31 20:42:31 +03:00
|
|
|
if (insn->is_seg_override())
|
2005-12-23 17:15:13 +03:00
|
|
|
seg = segment_name[insn->seg_override];
|
2003-12-24 23:44:39 +03:00
|
|
|
else
|
2004-12-08 21:54:15 +03:00
|
|
|
seg = segment_name[DS_REG];
|
2003-12-24 23:44:39 +03:00
|
|
|
|
2007-04-10 01:15:00 +04:00
|
|
|
if (insn->is_64) {
|
|
|
|
if (intel_mode) eip_regname = "eip";
|
|
|
|
else eip_regname = "%eip";
|
|
|
|
}
|
|
|
|
|
2006-08-11 21:23:36 +04:00
|
|
|
if ((insn->rm & 7) == 5) /* no reg, 32-bit displacement */
|
2009-12-28 16:52:40 +03:00
|
|
|
print_memory_access32(mode, seg, eip_regname, NULL, 0, insn->displacement.displ32);
|
2003-12-24 23:44:39 +03:00
|
|
|
else
|
2009-12-28 16:52:40 +03:00
|
|
|
print_memory_access32(mode, seg, general_32bit_regname[insn->rm], NULL, 0, 0);
|
2003-12-24 23:44:39 +03:00
|
|
|
}
|
|
|
|
|
2005-12-23 17:15:13 +03:00
|
|
|
void disassembler::resolve32_mod1or2(const x86_insn *insn, unsigned mode)
|
2003-12-24 23:44:39 +03:00
|
|
|
{
|
2004-12-08 21:54:15 +03:00
|
|
|
const char *seg;
|
2003-12-24 23:44:39 +03:00
|
|
|
|
2006-01-31 20:42:31 +03:00
|
|
|
if (insn->is_seg_override())
|
2005-12-23 17:15:13 +03:00
|
|
|
seg = segment_name[insn->seg_override];
|
2003-12-24 23:44:39 +03:00
|
|
|
else
|
2010-02-01 10:59:22 +03:00
|
|
|
seg = sreg_mod01or10_base32[insn->rm];
|
2003-12-24 23:44:39 +03:00
|
|
|
|
2009-12-28 16:52:40 +03:00
|
|
|
print_memory_access32(mode, seg,
|
2005-12-23 17:15:13 +03:00
|
|
|
general_32bit_regname[insn->rm], NULL, 0, insn->displacement.displ32);
|
2003-12-24 23:44:39 +03:00
|
|
|
}
|
|
|
|
|
2005-12-23 17:15:13 +03:00
|
|
|
void disassembler::resolve32_mod0_rm4(const x86_insn *insn, unsigned mode)
|
2003-12-24 23:44:39 +03:00
|
|
|
{
|
2004-12-08 21:54:15 +03:00
|
|
|
const char *seg, *base = NULL, *index = NULL;
|
|
|
|
Bit32u disp32 = 0;
|
2003-12-24 23:44:39 +03:00
|
|
|
|
2006-01-31 20:42:31 +03:00
|
|
|
if (insn->is_seg_override())
|
2005-12-23 17:15:13 +03:00
|
|
|
seg = segment_name[insn->seg_override];
|
2003-12-24 23:44:39 +03:00
|
|
|
else
|
2005-12-23 17:15:13 +03:00
|
|
|
seg = sreg_mod00_base32[insn->base];
|
2003-12-24 23:44:39 +03:00
|
|
|
|
2006-08-11 21:23:36 +04:00
|
|
|
if ((insn->base & 7) != 5)
|
2005-12-23 17:15:13 +03:00
|
|
|
base = general_32bit_regname[insn->base];
|
2004-12-13 01:12:43 +03:00
|
|
|
else
|
2005-12-23 17:15:13 +03:00
|
|
|
disp32 = insn->displacement.displ32;
|
2008-02-06 01:33:35 +03:00
|
|
|
|
2005-12-23 17:15:13 +03:00
|
|
|
if (insn->index != 4)
|
|
|
|
index = general_32bit_regname[insn->index];
|
2008-02-06 01:33:35 +03:00
|
|
|
|
2009-12-28 16:52:40 +03:00
|
|
|
print_memory_access32(mode, seg, base, index, insn->scale, disp32);
|
2003-12-24 23:44:39 +03:00
|
|
|
}
|
|
|
|
|
2005-12-23 17:15:13 +03:00
|
|
|
void disassembler::resolve32_mod1or2_rm4(const x86_insn *insn, unsigned mode)
|
2003-12-24 23:44:39 +03:00
|
|
|
{
|
2004-12-08 21:54:15 +03:00
|
|
|
const char *seg, *index = NULL;
|
2003-12-24 23:44:39 +03:00
|
|
|
|
2006-01-31 20:42:31 +03:00
|
|
|
if (insn->is_seg_override())
|
2005-12-23 17:15:13 +03:00
|
|
|
seg = segment_name[insn->seg_override];
|
2003-12-24 23:44:39 +03:00
|
|
|
else
|
2005-12-23 17:15:13 +03:00
|
|
|
seg = sreg_mod01or10_base32[insn->base];
|
2003-12-24 23:44:39 +03:00
|
|
|
|
2005-12-23 17:15:13 +03:00
|
|
|
if (insn->index != 4)
|
|
|
|
index = general_32bit_regname[insn->index];
|
2003-12-24 23:44:39 +03:00
|
|
|
|
2009-12-28 16:52:40 +03:00
|
|
|
print_memory_access32(mode, seg,
|
2005-12-23 17:15:13 +03:00
|
|
|
general_32bit_regname[insn->base], index, insn->scale, insn->displacement.displ32);
|
2003-12-24 23:44:39 +03:00
|
|
|
}
|
|
|
|
|
2005-12-23 17:15:13 +03:00
|
|
|
void disassembler::resolve64_mod0(const x86_insn *insn, unsigned mode)
|
|
|
|
{
|
|
|
|
const char *seg, *rip_regname;
|
|
|
|
|
2006-01-31 20:42:31 +03:00
|
|
|
if (insn->is_seg_override())
|
2005-12-23 17:15:13 +03:00
|
|
|
seg = segment_name[insn->seg_override];
|
|
|
|
else
|
|
|
|
seg = segment_name[DS_REG];
|
|
|
|
|
|
|
|
if (intel_mode) rip_regname = "rip";
|
|
|
|
else rip_regname = "%rip";
|
|
|
|
|
2006-08-11 21:23:36 +04:00
|
|
|
if ((insn->rm & 7) == 5) /* no reg, 32-bit displacement */
|
2009-12-28 16:52:40 +03:00
|
|
|
print_memory_access64(mode, seg, rip_regname, NULL, 0, (Bit32s) insn->displacement.displ32);
|
2005-12-23 17:15:13 +03:00
|
|
|
else
|
2009-12-28 16:52:40 +03:00
|
|
|
print_memory_access64(mode, seg, general_64bit_regname[insn->rm], NULL, 0, 0);
|
2005-12-23 17:15:13 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
void disassembler::resolve64_mod1or2(const x86_insn *insn, unsigned mode)
|
|
|
|
{
|
|
|
|
const char *seg;
|
|
|
|
|
2006-01-31 20:42:31 +03:00
|
|
|
if (insn->is_seg_override())
|
2005-12-23 17:15:13 +03:00
|
|
|
seg = segment_name[insn->seg_override];
|
|
|
|
else
|
2010-02-01 10:59:22 +03:00
|
|
|
seg = sreg_mod01or10_base32[insn->rm];
|
2005-12-23 17:15:13 +03:00
|
|
|
|
2009-12-28 16:52:40 +03:00
|
|
|
print_memory_access64(mode, seg,
|
|
|
|
general_64bit_regname[insn->rm], NULL, 0, (Bit32s) insn->displacement.displ32);
|
2005-12-23 17:15:13 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
void disassembler::resolve64_mod0_rm4(const x86_insn *insn, unsigned mode)
|
|
|
|
{
|
|
|
|
const char *seg, *base = NULL, *index = NULL;
|
2007-01-13 13:43:31 +03:00
|
|
|
Bit32s disp32 = 0;
|
2005-12-23 17:15:13 +03:00
|
|
|
|
2006-01-31 20:42:31 +03:00
|
|
|
if (insn->is_seg_override())
|
2005-12-23 17:15:13 +03:00
|
|
|
seg = segment_name[insn->seg_override];
|
|
|
|
else
|
|
|
|
seg = sreg_mod00_base32[insn->base];
|
|
|
|
|
2006-08-11 21:23:36 +04:00
|
|
|
if ((insn->base & 7) != 5)
|
2005-12-23 17:15:13 +03:00
|
|
|
base = general_64bit_regname[insn->base];
|
|
|
|
else
|
2007-01-13 13:43:31 +03:00
|
|
|
disp32 = (Bit32s) insn->displacement.displ32;
|
2008-02-06 01:33:35 +03:00
|
|
|
|
2005-12-23 17:15:13 +03:00
|
|
|
if (insn->index != 4)
|
|
|
|
index = general_64bit_regname[insn->index];
|
2008-02-06 01:33:35 +03:00
|
|
|
|
2009-12-28 16:52:40 +03:00
|
|
|
print_memory_access64(mode, seg, base, index, insn->scale, disp32);
|
2005-12-23 17:15:13 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
void disassembler::resolve64_mod1or2_rm4(const x86_insn *insn, unsigned mode)
|
|
|
|
{
|
|
|
|
const char *seg, *index = NULL;
|
|
|
|
|
2006-01-31 20:42:31 +03:00
|
|
|
if (insn->is_seg_override())
|
2005-12-23 17:15:13 +03:00
|
|
|
seg = segment_name[insn->seg_override];
|
|
|
|
else
|
|
|
|
seg = sreg_mod01or10_base32[insn->base];
|
|
|
|
|
|
|
|
if (insn->index != 4)
|
|
|
|
index = general_64bit_regname[insn->index];
|
|
|
|
|
2009-12-28 16:52:40 +03:00
|
|
|
print_memory_access64(mode, seg,
|
|
|
|
general_64bit_regname[insn->base], index, insn->scale, (Bit32s) insn->displacement.displ32);
|
2005-12-23 17:15:13 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
void disassembler::print_datasize(unsigned size)
|
2003-12-24 23:44:39 +03:00
|
|
|
{
|
2004-12-10 02:19:48 +03:00
|
|
|
if (!intel_mode) return;
|
|
|
|
|
2005-12-23 17:15:13 +03:00
|
|
|
switch(size)
|
2004-12-08 21:54:15 +03:00
|
|
|
{
|
2004-12-10 02:19:48 +03:00
|
|
|
case B_SIZE:
|
2004-12-08 21:54:15 +03:00
|
|
|
dis_sprintf("byte ptr ");
|
|
|
|
break;
|
2004-12-10 02:19:48 +03:00
|
|
|
case W_SIZE:
|
2004-12-08 21:54:15 +03:00
|
|
|
dis_sprintf("word ptr ");
|
|
|
|
break;
|
2004-12-10 02:19:48 +03:00
|
|
|
case D_SIZE:
|
2004-12-08 21:54:15 +03:00
|
|
|
dis_sprintf("dword ptr ");
|
|
|
|
break;
|
2004-12-10 02:19:48 +03:00
|
|
|
case Q_SIZE:
|
2004-12-08 21:54:15 +03:00
|
|
|
dis_sprintf("qword ptr ");
|
|
|
|
break;
|
2004-12-10 02:19:48 +03:00
|
|
|
case O_SIZE:
|
2004-12-08 21:54:15 +03:00
|
|
|
dis_sprintf("dqword ptr ");
|
|
|
|
break;
|
2004-12-10 02:19:48 +03:00
|
|
|
case T_SIZE:
|
2004-12-08 21:54:15 +03:00
|
|
|
dis_sprintf("tbyte ptr ");
|
|
|
|
break;
|
2004-12-10 02:19:48 +03:00
|
|
|
case P_SIZE:
|
2004-12-08 21:54:15 +03:00
|
|
|
break;
|
2004-12-10 02:19:48 +03:00
|
|
|
case X_SIZE:
|
2004-12-08 21:54:15 +03:00
|
|
|
break;
|
|
|
|
};
|
|
|
|
}
|
2003-12-24 23:44:39 +03:00
|
|
|
|
2008-02-06 01:33:35 +03:00
|
|
|
void disassembler::print_memory_access16(int datasize,
|
2004-12-08 21:54:15 +03:00
|
|
|
const char *seg, const char *index, Bit16u disp)
|
|
|
|
{
|
|
|
|
print_datasize(datasize);
|
2003-12-24 23:44:39 +03:00
|
|
|
|
2004-12-08 21:54:15 +03:00
|
|
|
if (intel_mode)
|
2003-12-24 23:44:39 +03:00
|
|
|
{
|
2004-12-08 21:54:15 +03:00
|
|
|
if (index == NULL)
|
|
|
|
{
|
|
|
|
dis_sprintf("%s:0x%x", seg, (unsigned) disp);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2009-12-28 16:52:40 +03:00
|
|
|
if (disp != 0) {
|
|
|
|
if (offset_mode_hex)
|
|
|
|
dis_sprintf("%s:[%s+0x%x]", seg, index, (unsigned) disp);
|
|
|
|
else
|
|
|
|
dis_sprintf("%s:[%s%+d]", seg, index, (int) (Bit16s) disp);
|
|
|
|
}
|
2004-12-08 21:54:15 +03:00
|
|
|
else
|
|
|
|
dis_sprintf("%s:[%s]", seg, index);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (index == NULL)
|
|
|
|
{
|
|
|
|
dis_sprintf("%s:0x%x", seg, (unsigned) disp);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2009-12-28 16:52:40 +03:00
|
|
|
if (disp != 0) {
|
|
|
|
if (offset_mode_hex)
|
|
|
|
dis_sprintf("%s:0x%x(%s,1)", seg, (unsigned) disp, index);
|
|
|
|
else
|
|
|
|
dis_sprintf("%s:%d(%s,1)", seg, (int) (Bit16s) disp, index);
|
|
|
|
}
|
2004-12-08 21:54:15 +03:00
|
|
|
else
|
|
|
|
dis_sprintf("%s:(%s,1)", seg, index);
|
|
|
|
}
|
2003-12-24 23:44:39 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-12-28 16:52:40 +03:00
|
|
|
void disassembler::print_memory_access32(int datasize,
|
|
|
|
const char *seg, const char *base, const char *index, int scale, Bit32s disp)
|
2003-12-24 23:44:39 +03:00
|
|
|
{
|
2004-12-08 21:54:15 +03:00
|
|
|
print_datasize(datasize);
|
2007-01-13 13:43:31 +03:00
|
|
|
|
|
|
|
scale = 1 << scale;
|
2008-02-06 01:33:35 +03:00
|
|
|
|
2004-12-08 21:54:15 +03:00
|
|
|
if (intel_mode)
|
|
|
|
{
|
|
|
|
if (base == NULL)
|
|
|
|
{
|
|
|
|
if (index == NULL)
|
|
|
|
{
|
2009-12-28 16:52:40 +03:00
|
|
|
dis_sprintf("%s:0x%x", seg, (unsigned) disp);
|
2004-12-08 21:54:15 +03:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2007-01-13 13:43:31 +03:00
|
|
|
if (scale != 1)
|
2004-12-08 21:54:15 +03:00
|
|
|
{
|
2007-01-13 13:43:31 +03:00
|
|
|
if (disp != 0) {
|
2009-12-28 16:52:40 +03:00
|
|
|
if (offset_mode_hex)
|
2007-01-13 13:43:31 +03:00
|
|
|
dis_sprintf("%s:[%s*%d+0x%x]", seg, index, scale, (unsigned) disp);
|
2009-12-28 16:52:40 +03:00
|
|
|
else
|
|
|
|
dis_sprintf("%s:[%s*%d%+d]", seg, index, scale, (int) disp);
|
2007-01-13 13:43:31 +03:00
|
|
|
}
|
2004-12-08 21:54:15 +03:00
|
|
|
else
|
2007-01-13 13:43:31 +03:00
|
|
|
dis_sprintf("%s:[%s*%d]", seg, index, scale);
|
2004-12-08 21:54:15 +03:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2007-01-13 13:43:31 +03:00
|
|
|
if (disp != 0) {
|
2009-12-28 16:52:40 +03:00
|
|
|
if (offset_mode_hex)
|
2007-01-13 13:43:31 +03:00
|
|
|
dis_sprintf("%s:[%s+0x%x]", seg, index, (unsigned) disp);
|
2009-12-28 16:52:40 +03:00
|
|
|
else
|
|
|
|
dis_sprintf("%s:[%s%+d]", seg, index, (int) disp);
|
2007-01-13 13:43:31 +03:00
|
|
|
}
|
|
|
|
else {
|
2004-12-08 21:54:15 +03:00
|
|
|
dis_sprintf("%s:[%s]", seg, index);
|
2007-01-13 13:43:31 +03:00
|
|
|
}
|
2004-12-08 21:54:15 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (index == NULL)
|
|
|
|
{
|
2007-01-13 13:43:31 +03:00
|
|
|
if (disp != 0) {
|
2009-12-28 16:52:40 +03:00
|
|
|
if (offset_mode_hex)
|
2007-01-13 13:43:31 +03:00
|
|
|
dis_sprintf("%s:[%s+0x%x]", seg, base, (unsigned) disp);
|
2009-12-28 16:52:40 +03:00
|
|
|
else
|
|
|
|
dis_sprintf("%s:[%s%+d]", seg, base, (int) disp);
|
2007-01-13 13:43:31 +03:00
|
|
|
}
|
|
|
|
else {
|
2004-12-08 21:54:15 +03:00
|
|
|
dis_sprintf("%s:[%s]", seg, base);
|
2007-01-13 13:43:31 +03:00
|
|
|
}
|
2004-12-08 21:54:15 +03:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2007-01-13 13:43:31 +03:00
|
|
|
if (scale != 1)
|
2004-12-08 21:54:15 +03:00
|
|
|
{
|
2007-01-13 13:43:31 +03:00
|
|
|
if (disp != 0) {
|
2009-12-28 16:52:40 +03:00
|
|
|
if (offset_mode_hex)
|
2007-01-13 13:43:31 +03:00
|
|
|
dis_sprintf("%s:[%s+%s*%d+0x%x]", seg, base, index, scale, (unsigned) disp);
|
2009-12-28 16:52:40 +03:00
|
|
|
else
|
|
|
|
dis_sprintf("%s:[%s+%s*%d%+d]", seg, base, index, scale, (int) disp);
|
2007-01-13 13:43:31 +03:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
dis_sprintf("%s:[%s+%s*%d]", seg, base, index, scale);
|
|
|
|
}
|
2004-12-08 21:54:15 +03:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2007-01-13 13:43:31 +03:00
|
|
|
if (disp != 0) {
|
2009-12-28 16:52:40 +03:00
|
|
|
if (offset_mode_hex)
|
2007-01-13 13:43:31 +03:00
|
|
|
dis_sprintf("%s:[%s+%s+0x%x]", seg, base, index, (unsigned) disp);
|
2009-12-28 16:52:40 +03:00
|
|
|
else
|
|
|
|
dis_sprintf("%s:[%s+%s%+d]", seg, base, index, (int) disp);
|
2007-01-13 13:43:31 +03:00
|
|
|
}
|
2004-12-08 21:54:15 +03:00
|
|
|
else
|
|
|
|
dis_sprintf("%s:[%s+%s]", seg, base, index);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2003-12-24 23:44:39 +03:00
|
|
|
else
|
|
|
|
{
|
2004-12-08 21:54:15 +03:00
|
|
|
if (base == NULL)
|
|
|
|
{
|
|
|
|
if (index == NULL)
|
|
|
|
{
|
2009-12-28 16:52:40 +03:00
|
|
|
dis_sprintf("%s:0x%x", seg, (unsigned) disp);
|
2004-12-08 21:54:15 +03:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2007-01-13 13:43:31 +03:00
|
|
|
if (disp != 0) {
|
2009-12-28 16:52:40 +03:00
|
|
|
if (offset_mode_hex)
|
2007-01-13 13:43:31 +03:00
|
|
|
dis_sprintf("%s:0x%x(,%s,%d)", seg, (unsigned) disp, index, scale);
|
2009-12-28 16:52:40 +03:00
|
|
|
else
|
|
|
|
dis_sprintf("%s:%d(,%s,%d)", seg, (int) disp, index, scale);
|
2007-01-13 13:43:31 +03:00
|
|
|
}
|
2004-12-08 21:54:15 +03:00
|
|
|
else
|
2007-01-13 13:43:31 +03:00
|
|
|
dis_sprintf("%s:(,%s,%d)", seg, index, scale);
|
2004-12-08 21:54:15 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (index == NULL)
|
|
|
|
{
|
2007-01-13 13:43:31 +03:00
|
|
|
if (disp != 0) {
|
2009-12-28 16:52:40 +03:00
|
|
|
if (offset_mode_hex)
|
2007-01-13 13:43:31 +03:00
|
|
|
dis_sprintf("%s:0x%x(%s)", seg, (unsigned) disp, base);
|
2009-12-28 16:52:40 +03:00
|
|
|
else
|
|
|
|
dis_sprintf("%s:%d(%s)", seg, (int) disp, base);
|
2007-01-13 13:43:31 +03:00
|
|
|
}
|
2004-12-08 21:54:15 +03:00
|
|
|
else
|
2004-12-10 02:19:48 +03:00
|
|
|
dis_sprintf("%s:(%s)", seg, base);
|
2004-12-08 21:54:15 +03:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2007-01-13 13:43:31 +03:00
|
|
|
if (disp != 0) {
|
2009-12-28 16:52:40 +03:00
|
|
|
if (offset_mode_hex)
|
|
|
|
dis_sprintf("%s:0x%x(%s,%s,%d)", seg, (unsigned) disp, base, index, scale);
|
|
|
|
else
|
|
|
|
dis_sprintf("%s:%d(%s,%s,%d)", seg, (int) disp, base, index, scale);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
dis_sprintf("%s:(%s,%s,%d)", seg, base, index, scale);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void disassembler::print_memory_access64(int datasize,
|
|
|
|
const char *seg, const char *base, const char *index, int scale, Bit32s disp)
|
|
|
|
{
|
|
|
|
Bit64u disp64 = (Bit64s) disp;
|
|
|
|
|
|
|
|
print_datasize(datasize);
|
|
|
|
|
|
|
|
scale = 1 << scale;
|
|
|
|
|
|
|
|
if (intel_mode)
|
|
|
|
{
|
|
|
|
if (base == NULL)
|
|
|
|
{
|
|
|
|
if (index == NULL)
|
|
|
|
{
|
|
|
|
dis_sprintf("%s:0x%08x%08x", seg, GET32H(disp64), GET32L(disp64));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (scale != 1)
|
|
|
|
{
|
|
|
|
if (disp != 0) {
|
|
|
|
if (offset_mode_hex)
|
|
|
|
dis_sprintf("%s:[%s*%d+0x%08x%08x]", seg, index, scale, GET32H(disp64), GET32L(disp64));
|
|
|
|
else
|
|
|
|
dis_sprintf("%s:[%s*%d%+d]", seg, index, scale, (int) disp);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
dis_sprintf("%s:[%s*%d]", seg, index, scale);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (disp != 0) {
|
|
|
|
if (offset_mode_hex)
|
|
|
|
dis_sprintf("%s:[%s+0x%08x%08x]", seg, index, GET32H(disp64), GET32L(disp64));
|
|
|
|
else
|
|
|
|
dis_sprintf("%s:[%s%+d]", seg, index, (int) disp);
|
2007-01-13 13:43:31 +03:00
|
|
|
}
|
|
|
|
else {
|
2009-12-28 16:52:40 +03:00
|
|
|
dis_sprintf("%s:[%s]", seg, index);
|
2007-01-13 13:43:31 +03:00
|
|
|
}
|
|
|
|
}
|
2009-12-28 16:52:40 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (index == NULL)
|
|
|
|
{
|
|
|
|
if (disp != 0) {
|
|
|
|
if (offset_mode_hex)
|
|
|
|
dis_sprintf("%s:[%s+0x%08x%08x]", seg, base, GET32H(disp64), GET32L(disp64));
|
|
|
|
else
|
|
|
|
dis_sprintf("%s:[%s%+d]", seg, base, (int) disp);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
dis_sprintf("%s:[%s]", seg, base);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (scale != 1)
|
|
|
|
{
|
|
|
|
if (disp != 0) {
|
|
|
|
if (offset_mode_hex)
|
|
|
|
dis_sprintf("%s:[%s+%s*%d+0x%08x%08x]", seg, base, index, scale, GET32H(disp64), GET32L(disp64));
|
|
|
|
else
|
|
|
|
dis_sprintf("%s:[%s+%s*%d%+d]", seg, base, index, scale, (int) disp);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
dis_sprintf("%s:[%s+%s*%d]", seg, base, index, scale);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (disp != 0) {
|
|
|
|
if (offset_mode_hex)
|
|
|
|
dis_sprintf("%s:[%s+%s+0x%08x%08x]", seg, base, index, GET32H(disp64), GET32L(disp64));
|
|
|
|
else
|
|
|
|
dis_sprintf("%s:[%s+%s%+d]", seg, base, index, (int) disp);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
dis_sprintf("%s:[%s+%s]", seg, base, index);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (base == NULL)
|
|
|
|
{
|
|
|
|
if (index == NULL)
|
|
|
|
{
|
|
|
|
dis_sprintf("%s:0x%08x%08x", seg, GET32H(disp64), GET32L(disp64));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (disp != 0) {
|
|
|
|
if (offset_mode_hex)
|
|
|
|
dis_sprintf("%s:0x%08x%08x(,%s,%d)", seg, GET32H(disp64), GET32L(disp64), index, scale);
|
|
|
|
else
|
|
|
|
dis_sprintf("%s:%d(,%s,%d)", seg, (int) disp, index, scale);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
dis_sprintf("%s:(,%s,%d)", seg, index, scale);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (index == NULL)
|
|
|
|
{
|
|
|
|
if (disp != 0) {
|
|
|
|
if (offset_mode_hex)
|
|
|
|
dis_sprintf("%s:0x%08x%08x(%s)", seg, GET32H(disp64), GET32L(disp64), base);
|
|
|
|
else
|
|
|
|
dis_sprintf("%s:%d(%s)", seg, (int) disp, base);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
dis_sprintf("%s:(%s)", seg, base);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (disp != 0) {
|
|
|
|
if (offset_mode_hex)
|
|
|
|
dis_sprintf("%s:0x%08x%08x(%s,%s,%d)", seg, GET32H(disp64), GET32L(disp64), base, index, scale);
|
|
|
|
else
|
|
|
|
dis_sprintf("%s:%d(%s,%s,%d)", seg, (int) disp, base, index, scale);
|
|
|
|
}
|
2004-12-08 21:54:15 +03:00
|
|
|
else
|
2007-01-13 13:43:31 +03:00
|
|
|
dis_sprintf("%s:(%s,%s,%d)", seg, base, index, scale);
|
2004-12-08 21:54:15 +03:00
|
|
|
}
|
|
|
|
}
|
2003-12-24 23:44:39 +03:00
|
|
|
}
|
|
|
|
}
|