#include #include "disasm.h" void disassembler::decode_modrm() { modrm = fetch_byte(); BX_DECODE_MODRM(modrm, mod, nnn, rm); if (i32bit_addrsize) { /* 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 (i32bit_opsize) 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<