349 lines
8.0 KiB
C++
Executable File
349 lines
8.0 KiB
C++
Executable File
#include <stdio.h>
|
|
#include "disasm.h"
|
|
|
|
void disassembler::decode_modrm()
|
|
{
|
|
modrm = fetch_byte();
|
|
BX_DECODE_MODRM(modrm, mod, nnn, rm);
|
|
|
|
if (as_32)
|
|
{
|
|
/* use 32bit addressing modes. orthogonal base & index registers,
|
|
scaling available, etc. */
|
|
if (mod == 3) {
|
|
/* mod, reg, reg */
|
|
return;
|
|
}
|
|
else { /* mod != 3 */
|
|
if (rm != 4) { /* rm != 100b, no s-i-b byte */
|
|
// one byte modrm
|
|
switch (mod) {
|
|
case 0:
|
|
resolve_modrm = &disassembler::resolve32_mod0;
|
|
if (rm == 5) /* no reg, 32-bit displacement */
|
|
displacement.displ32 = fetch_dword();
|
|
break;
|
|
case 1:
|
|
/* reg, 8-bit displacement, sign extend */
|
|
resolve_modrm = &disassembler::resolve32_mod1or2;
|
|
displacement.displ32 = (Bit8s) fetch_byte();
|
|
break;
|
|
case 2:
|
|
/* reg, 32-bit displacement */
|
|
resolve_modrm = &disassembler::resolve32_mod1or2;
|
|
displacement.displ32 = fetch_dword();
|
|
break;
|
|
} /* switch (mod) */
|
|
} /* if (rm != 4) */
|
|
else { /* rm == 4, s-i-b byte follows */
|
|
sib = fetch_byte();
|
|
BX_DECODE_SIB(sib, scale, sib_index, sib_base);
|
|
|
|
switch (mod) {
|
|
case 0:
|
|
resolve_modrm = &disassembler::resolve32_mod0_rm4;
|
|
if (sib_base == 5)
|
|
displacement.displ32 = fetch_dword();
|
|
break;
|
|
case 1:
|
|
resolve_modrm = &disassembler::resolve32_mod1or2_rm4;
|
|
displacement.displ32 = (Bit8s) fetch_byte();
|
|
break;
|
|
case 2:
|
|
resolve_modrm = &disassembler::resolve32_mod1or2_rm4;
|
|
displacement.displ32 = fetch_dword();
|
|
break;
|
|
}
|
|
} /* s-i-b byte follows */
|
|
} /* if (mod != 3) */
|
|
}
|
|
else {
|
|
/* 16 bit addressing modes. */
|
|
switch (mod) {
|
|
case 0:
|
|
resolve_modrm = &disassembler::resolve16_mod0;
|
|
if(rm == 6)
|
|
displacement.displ16 = fetch_word();
|
|
break;
|
|
case 1:
|
|
/* reg, 8-bit displacement, sign extend */
|
|
resolve_modrm = &disassembler::resolve16_mod1or2;
|
|
displacement.displ16 = (Bit8s) fetch_byte();
|
|
break;
|
|
case 2:
|
|
resolve_modrm = &disassembler::resolve16_mod1or2;
|
|
displacement.displ16 = fetch_word();
|
|
break;
|
|
case 3:
|
|
/* mod, reg, reg */
|
|
return;
|
|
|
|
} /* switch (mod) ... */
|
|
}
|
|
}
|
|
|
|
void disassembler::resolve16_mod0(unsigned mode)
|
|
{
|
|
const char *seg;
|
|
|
|
if (seg_override)
|
|
seg = seg_override;
|
|
else
|
|
seg = sreg_mod00_rm16[rm];
|
|
|
|
if(rm == 6)
|
|
print_memory_access16(mode, seg, NULL, displacement.displ16);
|
|
else
|
|
print_memory_access16(mode, seg, index16[rm], 0);
|
|
}
|
|
|
|
void disassembler::resolve16_mod1or2(unsigned mode)
|
|
{
|
|
const char *seg;
|
|
|
|
if (seg_override)
|
|
seg = seg_override;
|
|
else
|
|
seg = sreg_mod01or10_rm16[rm];
|
|
|
|
print_memory_access16(mode, seg, index16[rm], displacement.displ16);
|
|
}
|
|
|
|
void disassembler::resolve32_mod0(unsigned mode)
|
|
{
|
|
const char *seg;
|
|
|
|
if (seg_override)
|
|
seg = seg_override;
|
|
else
|
|
seg = segment_name[DS_REG];
|
|
|
|
if (rm == 5) /* no reg, 32-bit displacement */
|
|
print_memory_access32(mode, seg, NULL, NULL, 0, displacement.displ32);
|
|
else
|
|
print_memory_access32(mode, seg, general_32bit_regname[rm], NULL, 0, 0);
|
|
}
|
|
|
|
void disassembler::resolve32_mod1or2(unsigned mode)
|
|
{
|
|
const char *seg;
|
|
|
|
if (seg_override)
|
|
seg = seg_override;
|
|
else
|
|
seg = sreg_mod01or10_rm32[rm];
|
|
|
|
print_memory_access32(mode, seg,
|
|
general_32bit_regname[rm], NULL, 0, displacement.displ32);
|
|
}
|
|
|
|
void disassembler::resolve32_mod0_rm4(unsigned mode)
|
|
{
|
|
const char *seg, *base = NULL, *index = NULL;
|
|
Bit32u disp32 = 0;
|
|
|
|
if (seg_override)
|
|
seg = seg_override;
|
|
else
|
|
seg = sreg_mod00_base32[sib_base];
|
|
|
|
if (sib_base != 5)
|
|
base = general_32bit_regname[sib_base];
|
|
else
|
|
disp32 = displacement.displ32;
|
|
|
|
if (sib_index != 4)
|
|
{
|
|
index = general_32bit_regname[sib_index];
|
|
}
|
|
|
|
print_memory_access32(mode, seg, base, index, scale, disp32);
|
|
}
|
|
|
|
void disassembler::resolve32_mod1or2_rm4(unsigned mode)
|
|
{
|
|
const char *seg, *index = NULL;
|
|
|
|
if (seg_override)
|
|
seg = seg_override;
|
|
else
|
|
seg = sreg_mod01or10_base32[sib_base];
|
|
|
|
if (sib_index != 4)
|
|
{
|
|
index = general_32bit_regname[sib_index];
|
|
}
|
|
|
|
print_memory_access32(mode, seg,
|
|
general_32bit_regname[sib_base], index, scale, displacement.displ32);
|
|
}
|
|
|
|
void disassembler::print_datasize(unsigned mode)
|
|
{
|
|
if (!intel_mode) return;
|
|
|
|
switch(mode)
|
|
{
|
|
case B_SIZE:
|
|
dis_sprintf("byte ptr ");
|
|
break;
|
|
case W_SIZE:
|
|
dis_sprintf("word ptr ");
|
|
break;
|
|
case D_SIZE:
|
|
dis_sprintf("dword ptr ");
|
|
break;
|
|
case V_SIZE:
|
|
if (os_32)
|
|
dis_sprintf("dword ptr ");
|
|
else
|
|
dis_sprintf("word ptr ");
|
|
break;
|
|
case Q_SIZE:
|
|
dis_sprintf("qword ptr ");
|
|
break;
|
|
case O_SIZE:
|
|
dis_sprintf("dqword ptr ");
|
|
break;
|
|
case T_SIZE:
|
|
dis_sprintf("tbyte ptr ");
|
|
break;
|
|
case P_SIZE:
|
|
break;
|
|
case S_SIZE:
|
|
break;
|
|
case X_SIZE:
|
|
break;
|
|
};
|
|
}
|
|
|
|
void disassembler::print_memory_access16(int datasize,
|
|
const char *seg, const char *index, Bit16u disp)
|
|
{
|
|
print_datasize(datasize);
|
|
|
|
if (intel_mode)
|
|
{
|
|
if (index == NULL)
|
|
{
|
|
dis_sprintf("%s:0x%x", seg, (unsigned) disp);
|
|
}
|
|
else
|
|
{
|
|
if (disp != 0)
|
|
dis_sprintf("%s:[%s+0x%x]", seg, index, (unsigned) disp);
|
|
else
|
|
dis_sprintf("%s:[%s]", seg, index);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (index == NULL)
|
|
{
|
|
dis_sprintf("%s:0x%x", seg, (unsigned) disp);
|
|
}
|
|
else
|
|
{
|
|
if (disp != 0)
|
|
dis_sprintf("%s:0x%x(%s,1)", seg, (unsigned) disp, index);
|
|
else
|
|
dis_sprintf("%s:(%s,1)", seg, index);
|
|
}
|
|
}
|
|
}
|
|
|
|
void disassembler::print_memory_access32(int datasize,
|
|
const char *seg, const char *base, const char *index, int scale, Bit32u disp)
|
|
{
|
|
print_datasize(datasize);
|
|
|
|
if (intel_mode)
|
|
{
|
|
if (base == NULL)
|
|
{
|
|
if (index == NULL)
|
|
{
|
|
dis_sprintf("%s:0x%x", seg, (unsigned) disp);
|
|
}
|
|
else
|
|
{
|
|
if (scale != 0)
|
|
{
|
|
if (disp != 0)
|
|
dis_sprintf("%s:[%s*%d+0x%x]", seg, index, 1<<scale, (unsigned) disp);
|
|
else
|
|
dis_sprintf("%s:[%s*%d]", seg, index, 1<<scale);
|
|
}
|
|
else
|
|
{
|
|
if (disp != 0)
|
|
dis_sprintf("%s:[%s+0x%x]", seg, index, (unsigned) disp);
|
|
else
|
|
dis_sprintf("%s:[%s]", seg, index);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (index == NULL)
|
|
{
|
|
if (disp != 0)
|
|
dis_sprintf("%s:[%s+0x%x]", seg, base, (unsigned) disp);
|
|
else
|
|
dis_sprintf("%s:[%s]", seg, base);
|
|
}
|
|
else
|
|
{
|
|
if (scale != 0)
|
|
{
|
|
if (disp != 0)
|
|
dis_sprintf("%s:[%s+%s*%d+0x%x]", seg, base, index, 1<<scale, (unsigned) disp);
|
|
else
|
|
dis_sprintf("%s:[%s+%s*%d]", seg, base, index, 1<<scale);
|
|
}
|
|
else
|
|
{
|
|
if (disp != 0)
|
|
dis_sprintf("%s:[%s+%s+0x%x]", seg, base, index, (unsigned) disp);
|
|
else
|
|
dis_sprintf("%s:[%s+%s]", seg, base, index);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (base == NULL)
|
|
{
|
|
if (index == NULL)
|
|
{
|
|
dis_sprintf("%s:0x%x", seg, (unsigned) disp);
|
|
}
|
|
else
|
|
{
|
|
if (disp != 0)
|
|
dis_sprintf("%s:0x%x(,%s,%d)", seg, (unsigned) disp, index, 1<<scale);
|
|
else
|
|
dis_sprintf("%s:(,%s,%d)", seg, index, 1<<scale);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (index == NULL)
|
|
{
|
|
if (disp != 0)
|
|
dis_sprintf("%s:0x%x(%s)", seg, (unsigned) disp, base);
|
|
else
|
|
dis_sprintf("%s:(%s)", seg, base);
|
|
}
|
|
else
|
|
{
|
|
if (disp != 0)
|
|
dis_sprintf("%s:0x%x(%s,%s,%d)", seg, (unsigned) disp, base, index, 1<<scale);
|
|
else
|
|
dis_sprintf("%s:(%s,%s,%d)", seg, base, index, 1<<scale);
|
|
}
|
|
}
|
|
}
|
|
}
|