static void floating_point(int e1) { int esc = e1*8 + reg(modrm()); if (mod(modrm()) == 3) { if (fspecial[esc]) { if(fspecial[esc][0] && fspecial[esc][0][0] == '*') { ua_str(fspecial[esc][0]+1); } else { if(fspecial[esc][rm(modrm())]) ua_str(fspecial[esc][rm(modrm())]); } } else { ua_str(floatops[esc]); ua_str(" %EF"); } } else { ua_str(floatops[esc]); ua_str(" %EF"); } }
/* * decode_ext() * * Decode opcode extensions (if any) */ static int decode_ext(struct ud *u, uint16_t ptr) { uint8_t idx = 0; if ((ptr & 0x8000) == 0) { return decode_insn(u, ptr); } u->le = &ud_lookup_table_list[(~0x8000 & ptr)]; if (u->le->type == UD_TAB__OPC_3DNOW) { return decode_3dnow(u); } switch (u->le->type) { case UD_TAB__OPC_MOD: /* !11 = 0, 11 = 1 */ idx = (MODRM_MOD(modrm(u)) + 1) / 4; break; /* disassembly mode/operand size/address size based tables. * 16 = 0,, 32 = 1, 64 = 2 */ case UD_TAB__OPC_MODE: idx = u->dis_mode / 32; break; case UD_TAB__OPC_OSIZE: idx = eff_opr_mode(u->dis_mode, REX_W(u->pfx_rex), u->pfx_opr) / 32; break; case UD_TAB__OPC_ASIZE: idx = eff_adr_mode(u->dis_mode, u->pfx_adr) / 32; break; case UD_TAB__OPC_X87: idx = modrm(u) - 0xC0; break; case UD_TAB__OPC_VENDOR: if (u->vendor == UD_VENDOR_ANY) { /* choose a valid entry */ idx = (u->le->table[idx] != 0) ? 0 : 1; } else if (u->vendor == UD_VENDOR_AMD) { idx = 0; } else { idx = 1; } break; case UD_TAB__OPC_RM: idx = MODRM_RM(modrm(u)); break; case UD_TAB__OPC_REG: idx = MODRM_REG(modrm(u)); break; case UD_TAB__OPC_SSE: return decode_ssepfx(u); default: assert(!"not reached"); break; } return decode_ext(u, u->le->table[idx]); }
inline Modrm make_modrm(const UntypedRegister& r,int i) { Modrm modrm(3,i,r.get_code()); return modrm; }
inline Modrm make_modrm (const PtrData& r,int i) { Modrm modrm(r,i); return modrm; }
/* * decode_modrm_reg * * Decodes reg field of mod/rm byte * */ static inline void decode_modrm_reg(struct ud *u, struct ud_operand *operand, unsigned int type, unsigned int size) { uint8_t reg = (REX_R(u->pfx_rex) << 3) | MODRM_REG(modrm(u)); decode_reg(u, operand, type, reg, size); }
static void floating_point(int e1) { int esc = e1*8 + REG(modrm()); if(MOD(modrm()) == 3) { if(fspecial[esc]) { if(fspecial[esc][0][0] == '*') { ua_str(fspecial[esc][0]+1); } else { ua_str(fspecial[esc][RM(modrm())]); } } else { ua_str(floatops[esc]); ua_str(" %EF"); } } else { ua_str(floatops[esc]); ua_str(" %EF"); } }
int twobyteinstr() { int r, b, x, y; b=PeekOneByte(); switch(opcode2Table[b]) { case 0: r=op(); if(!r) return 0; x=result; i_opclass=0; i_opcode=x; break; case 1: r=op(); if(!r) return 0; x=result; r=adword(); if(!r) return 0; y=result; i_opclass=1; i_opcode=x; i_dword=y; break; case 2: r=op(); if(!r) return 0; x=result; r=modrm(); if(!r) return 0; i_opclass=2; i_opcode=x; break; case 3: r=op(); if(!r) return 0; x=result; r=modrm(); if(!r) return 0; r=byte(); if(!r) return 0; y=result; i_opclass=3; i_opcode=x; i_byte=y; break; case 4: r=op(); if(!r) return 0; x=result; r=opext(); if(!r) return 0; i_opclass=4; i_opcode=x; break; case 5: r=op(); if(!r) return 0; x=result; r=opext(); if(!r) return 0; r=byte(); if(!r) return 0; y=result; i_opclass=5; i_opcode=x; i_byte=y; break; default: return 0; } return 1; }
/* * decode_modrm_reg * * Decodes reg field of mod/rm byte * */ static void decode_modrm_reg(struct ud *u, struct ud_operand *operand, unsigned int type, unsigned int size) { uint8_t reg = (REX_R(u->pfx_rex) << 3) | MODRM_REG(modrm(u)); operand->type = UD_OP_REG; operand->size = resolve_operand_size(u, size); if (type == T_GPR) { operand->base = decode_gpr(u, operand->size, reg); } else { operand->base = resolve_reg(u, type, reg); } }
size_t ins_digit(int opcode, int digit, struct asm_ins *ins, char *out, int no_rex) { const int MODRM_REG_OFF = 3; char *p = out; if (ins->op1.gen.size == 8) { int rex = REX | REX_B_M[ins->op1.reg.name] | (no_rex ? 0 : REX_W); if (!no_rex || rex == 0x41) *p++ = rex; } *p++ = opcode; *p++ = modrm(&ins->op2, &ins->op1) | (digit << MODRM_REG_OFF); return p - out; }
size_t ins_rr_mr(int opcode, struct asm_ins *ins, char *out) { char *p = out; if (ins->op2.gen.size == 8) *p++ = REX | REX_W | REX_B_M[ins->op2.reg.name] << 2 | REX_B_M[ins->op1.reg.name]; *p++ = opcode; *p++ = modrm(&(ins->op2), &(ins->op1)); if ( ins->op1.gen.type == ASM_OPERAND_ADDR && ins->op1.addr.disp != 0) { memcpy(p, &ins->op1.addr.disp, ins->op1.addr.disp_size); p += ins->op1.addr.disp_size; } return p - out; }
size_t ins_mi(int opcode, struct asm_ins *ins, char *out) { char *p = out; if (ins->op1.gen.size == 8) { uint8_t rex = REX | REX_W; if (ins->op1.gen.type == ASM_OPERAND_REG) rex |= REX_B_M[ins->op1.reg.name]; *p++ = rex; } *p++ = opcode; *p++ = modrm(&ins->op2, &ins->op1); memcpy(p, &ins->op2.imme.value.u64, ins->op1.gen.size); p += ins->op1.gen.size; return p - out; }
/* ----------------------------------------------------------------------------- * decode_operands() - Disassembles Operands. * ----------------------------------------------------------------------------- */ static int decode_operand(struct ud *u, struct ud_operand *operand, enum ud_operand_code type, unsigned int size) { switch (type) { case OP_A : decode_a(u, operand); break; case OP_MR: if (MODRM_MOD(modrm(u)) == 3) { decode_modrm_rm(u, operand, T_GPR, size == SZ_DY ? SZ_MDQ : SZ_V); } else if (size == SZ_WV) { decode_modrm_rm( u, operand, T_GPR, SZ_W); } else if (size == SZ_BV) { decode_modrm_rm( u, operand, T_GPR, SZ_B); } else if (size == SZ_DY) { decode_modrm_rm( u, operand, T_GPR, SZ_D); } else { assert(!"unexpected size"); } break; case OP_M: if (MODRM_MOD(modrm(u)) == 3) { u->error = 1; } /* intended fall through */ case OP_E: decode_modrm_rm(u, operand, T_GPR, size); break; break; case OP_G: decode_modrm_reg(u, operand, T_GPR, size); break; case OP_I: decode_imm(u, size, operand); break; case OP_I1: operand->type = UD_OP_CONST; operand->lval.udword = 1; break; case OP_PR: if (MODRM_MOD(modrm(u)) != 3) { u->error = 1; } decode_modrm_rm(u, operand, T_MMX, size); break; case OP_P: decode_modrm_reg(u, operand, T_MMX, size); break; case OP_VR: if (MODRM_MOD(modrm(u)) != 3) { u->error = 1; } /* intended fall through */ case OP_W: decode_modrm_rm(u, operand, T_XMM, size); break; case OP_V: decode_modrm_reg(u, operand, T_XMM, size); break; case OP_S: decode_modrm_reg(u, operand, T_SEG, size); break; case OP_AL: case OP_CL: case OP_DL: case OP_BL: case OP_AH: case OP_CH: case OP_DH: case OP_BH: operand->type = UD_OP_REG; operand->base = UD_R_AL + (type - OP_AL); operand->size = 8; break; case OP_DX: operand->type = UD_OP_REG; operand->base = UD_R_DX; operand->size = 16; break; case OP_O: decode_o(u, size, operand); break; case OP_rAXr8: case OP_rCXr9: case OP_rDXr10: case OP_rBXr11: case OP_rSPr12: case OP_rBPr13: case OP_rSIr14: case OP_rDIr15: case OP_rAX: case OP_rCX: case OP_rDX: case OP_rBX: case OP_rSP: case OP_rBP: case OP_rSI: case OP_rDI: operand->type = UD_OP_REG; operand->base = resolve_gpr64(u, type, &operand->size); break; case OP_ALr8b: case OP_CLr9b: case OP_DLr10b: case OP_BLr11b: case OP_AHr12b: case OP_CHr13b: case OP_DHr14b: case OP_BHr15b: { ud_type_t gpr = (type - OP_ALr8b) + UD_R_AL + (REX_B(u->pfx_rex) << 3); if (UD_R_AH <= gpr && u->pfx_rex) { gpr = gpr + 4; } operand->type = UD_OP_REG; operand->base = gpr; break; } case OP_eAX: case OP_eCX: case OP_eDX: case OP_eBX: case OP_eSP: case OP_eBP: case OP_eSI: case OP_eDI: operand->type = UD_OP_REG; operand->base = resolve_gpr32(u, type); operand->size = u->opr_mode == 16 ? 16 : 32; break; case OP_ES: case OP_CS: case OP_DS: case OP_SS: case OP_FS: case OP_GS: /* in 64bits mode, only fs and gs are allowed */ if (u->dis_mode == 64) { if (type != OP_FS && type != OP_GS) { u->error= 1; } } operand->type = UD_OP_REG; operand->base = (type - OP_ES) + UD_R_ES; operand->size = 16; break; case OP_J : decode_imm(u, size, operand); operand->type = UD_OP_JIMM; break ; case OP_Q: decode_modrm_rm(u, operand, T_MMX, size); break; case OP_R : decode_modrm_rm(u, operand, T_GPR, size); break; case OP_C: decode_modrm_reg(u, operand, T_CRG, size); break; case OP_D: decode_modrm_reg(u, operand, T_DBG, size); break; case OP_I3 : operand->type = UD_OP_CONST; operand->lval.sbyte = 3; break; case OP_ST0: case OP_ST1: case OP_ST2: case OP_ST3: case OP_ST4: case OP_ST5: case OP_ST6: case OP_ST7: operand->type = UD_OP_REG; operand->base = (type - OP_ST0) + UD_R_ST0; operand->size = 0; break; case OP_AX: operand->type = UD_OP_REG; operand->base = UD_R_AX; operand->size = 16; break; default : operand->type = UD_NONE; break; } return 0; }
/* * decode_modrm_rm * * Decodes rm field of mod/rm byte * */ static void decode_modrm_rm(struct ud *u, struct ud_operand *op, unsigned char type, unsigned int size) { unsigned char mod, rm, reg; /* get mod, r/m and reg fields */ mod = MODRM_MOD(modrm(u)); rm = (REX_B(u->pfx_rex) << 3) | MODRM_RM(modrm(u)); reg = (REX_R(u->pfx_rex) << 3) | MODRM_REG(modrm(u)); op->size = resolve_operand_size(u, size); /* * If mod is 11b, then the modrm.rm specifies a register. * */ if (mod == 3) { op->type = UD_OP_REG; if (type == T_GPR) { op->base = decode_gpr(u, op->size, rm); } else { op->base = resolve_reg(u, type, (REX_B(u->pfx_rex) << 3) | (rm & 7)); } return; } /* * !11 => Memory Address */ op->type = UD_OP_MEM; if (u->adr_mode == 64) { op->base = UD_R_RAX + rm; if (mod == 1) { op->offset = 8; } else if (mod == 2) { op->offset = 32; } else if (mod == 0 && (rm & 7) == 5) { op->base = UD_R_RIP; op->offset = 32; } else { op->offset = 0; } /* * Scale-Index-Base (SIB) */ if ((rm & 7) == 4) { inp_next(u); op->scale = (1 << SIB_S(inp_curr(u))) & ~1; op->index = UD_R_RAX + (SIB_I(inp_curr(u)) | (REX_X(u->pfx_rex) << 3)); op->base = UD_R_RAX + (SIB_B(inp_curr(u)) | (REX_B(u->pfx_rex) << 3)); /* special conditions for base reference */ if (op->index == UD_R_RSP) { op->index = UD_NONE; op->scale = UD_NONE; } if (op->base == UD_R_RBP || op->base == UD_R_R13) { if (mod == 0) { op->base = UD_NONE; } if (mod == 1) { op->offset = 8; } else { op->offset = 32; } } } } else if (u->adr_mode == 32) { op->base = UD_R_EAX + rm; if (mod == 1) { op->offset = 8; } else if (mod == 2) { op->offset = 32; } else if (mod == 0 && rm == 5) { op->base = UD_NONE; op->offset = 32; } else { op->offset = 0; } /* Scale-Index-Base (SIB) */ if ((rm & 7) == 4) { inp_next(u); op->scale = (1 << SIB_S(inp_curr(u))) & ~1; op->index = UD_R_EAX + (SIB_I(inp_curr(u)) | (REX_X(u->pfx_rex) << 3)); op->base = UD_R_EAX + (SIB_B(inp_curr(u)) | (REX_B(u->pfx_rex) << 3)); if (op->index == UD_R_ESP) { op->index = UD_NONE; op->scale = UD_NONE; } /* special condition for base reference */ if (op->base == UD_R_EBP) { if (mod == 0) { op->base = UD_NONE; } if (mod == 1) { op->offset = 8; } else { op->offset = 32; } } } } else { const unsigned int bases[] = { UD_R_BX, UD_R_BX, UD_R_BP, UD_R_BP, UD_R_SI, UD_R_DI, UD_R_BP, UD_R_BX }; const unsigned int indices[] = { UD_R_SI, UD_R_DI, UD_R_SI, UD_R_DI, UD_NONE, UD_NONE, UD_NONE, UD_NONE }; op->base = bases[rm & 7]; op->index = indices[rm & 7]; if (mod == 0 && rm == 6) { op->offset= 16; op->base = UD_NONE; } else if (mod == 1) { op->offset = 8; } else if (mod == 2) { op->offset = 16; } } /* * extract offset, if any */ switch (op->offset) { case 8 : op->lval.ubyte = inp_uint8(u); break; case 16: op->lval.uword = inp_uint16(u); break; case 32: op->lval.udword = inp_uint32(u); break; case 64: op->lval.uqword = inp_uint64(u); break; default: break; } }
/*------------------------------------------------------------------------*/ static void do_modrm(char subtype) { int mod = MOD(modrm()); int rm = RM(modrm()); int extend = (addrsize == 32) ? 4 : 2; if (mod == 3) { /* specifies two registers */ reg_name(rm, subtype); return; } if (must_do_size) { if (wordop) { if (addrsize==32 || opsize==32) { /* then must specify size */ ua_str("dword ptr "); } else { ua_str("word ptr "); } } else { ua_str("byte ptr "); } } if ((mod == 0) && (rm == 5) && (addrsize == 32)) {/* mem operand with 32 bit ofs */ ua_str("%p:["); outhex('d', extend, 0, addrsize, 0); uputchar(']'); return; } if ((mod == 0) && (rm == 6) && (addrsize == 16)) { /* 16 bit dsplcmnt */ ua_str("%p:["); outhex('w', extend, 0, addrsize, 0); uputchar(']'); return; } if ((addrsize != 32) || (rm != 4)) ua_str("%p:["); if (addrsize == 16) { switch (rm) { case 0: uprintf("bx+si"); break; case 1: uprintf("bx+di"); break; case 2: uprintf("bp+si"); break; case 3: uprintf("bp+di"); break; case 4: uprintf("si"); break; case 5: uprintf("di"); break; case 6: uprintf("bp"); break; case 7: uprintf("bx"); break; } } else { switch (rm) { case 0: uprintf("eax"); break; case 1: uprintf("ecx"); break; case 2: uprintf("edx"); break; case 3: uprintf("ebx"); break; case 4: do_sib(mod); break; case 5: uprintf("ebp"); break; case 6: uprintf("esi"); break; case 7: uprintf("edi"); break; } } switch (mod) { case 1: outhex('b', extend, 1, addrsize, 0); break; case 2: outhex('v', extend, 1, addrsize, 1); break; } uputchar(']'); }
/* ----------------------------------------------------------------------------- * decode_operands() - Disassembles Operands. * ----------------------------------------------------------------------------- */ static int decode_operand(struct ud *u, struct ud_operand *operand, enum ud_operand_code type, unsigned int size) { operand->_oprcode = type; switch (type) { case OP_A : decode_a(u, operand); break; case OP_MR: decode_modrm_rm(u, operand, REGCLASS_GPR, MODRM_MOD(modrm(u)) == 3 ? Mx_reg_size(size) : Mx_mem_size(size)); break; case OP_F: u->br_far = 1; /* intended fall through */ case OP_M: if (MODRM_MOD(modrm(u)) == 3) { UDERR(u, "expected modrm.mod != 3\n"); } /* intended fall through */ case OP_E: decode_modrm_rm(u, operand, REGCLASS_GPR, size); break; case OP_G: decode_modrm_reg(u, operand, REGCLASS_GPR, size); break; case OP_sI: case OP_I: decode_imm(u, size, operand); break; case OP_I1: operand->type = UD_OP_CONST; operand->lval.udword = 1; break; case OP_N: if (MODRM_MOD(modrm(u)) != 3) { UDERR(u, "expected modrm.mod == 3\n"); } /* intended fall through */ case OP_Q: decode_modrm_rm(u, operand, REGCLASS_MMX, size); break; case OP_P: decode_modrm_reg(u, operand, REGCLASS_MMX, size); break; case OP_U: if (MODRM_MOD(modrm(u)) != 3) { UDERR(u, "expected modrm.mod == 3\n"); } /* intended fall through */ case OP_W: decode_modrm_rm(u, operand, REGCLASS_XMM, size); break; case OP_V: decode_modrm_reg(u, operand, REGCLASS_XMM, size); break; case OP_MU: decode_modrm_rm(u, operand, REGCLASS_XMM, MODRM_MOD(modrm(u)) == 3 ? Mx_reg_size(size) : Mx_mem_size(size)); break; case OP_S: decode_modrm_reg(u, operand, REGCLASS_SEG, size); break; case OP_O: decode_moffset(u, size, operand); break; case OP_R0: case OP_R1: case OP_R2: case OP_R3: case OP_R4: case OP_R5: case OP_R6: case OP_R7: decode_reg(u, operand, REGCLASS_GPR, (REX_B(u->pfx_rex) << 3) | (type - OP_R0), size); break; case OP_AL: case OP_AX: case OP_eAX: case OP_rAX: decode_reg(u, operand, REGCLASS_GPR, 0, size); break; case OP_CL: case OP_CX: case OP_eCX: decode_reg(u, operand, REGCLASS_GPR, 1, size); break; case OP_DL: case OP_DX: case OP_eDX: decode_reg(u, operand, REGCLASS_GPR, 2, size); break; case OP_ES: case OP_CS: case OP_DS: case OP_SS: case OP_FS: case OP_GS: /* in 64bits mode, only fs and gs are allowed */ if (u->dis_mode == 64) { if (type != OP_FS && type != OP_GS) { UDERR(u, "invalid segment register in 64bits\n"); } } operand->type = UD_OP_REG; operand->base = (type - OP_ES) + UD_R_ES; operand->size = 16; break; case OP_J : decode_imm(u, size, operand); operand->type = UD_OP_JIMM; break ; case OP_R : if (MODRM_MOD(modrm(u)) != 3) { UDERR(u, "expected modrm.mod == 3\n"); } decode_modrm_rm(u, operand, REGCLASS_GPR, size); break; case OP_C: decode_modrm_reg(u, operand, REGCLASS_CR, size); break; case OP_D: decode_modrm_reg(u, operand, REGCLASS_DB, size); break; case OP_I3 : operand->type = UD_OP_CONST; operand->lval.sbyte = 3; break; case OP_ST0: case OP_ST1: case OP_ST2: case OP_ST3: case OP_ST4: case OP_ST5: case OP_ST6: case OP_ST7: operand->type = UD_OP_REG; operand->base = (type - OP_ST0) + UD_R_ST0; operand->size = 80; break; default : break; } return 0; }
/* * decode_modrm_rm * * Decodes rm field of mod/rm byte * */ static void decode_modrm_rm(struct ud *u, struct ud_operand *op, unsigned char type, /* register type */ unsigned int size) /* operand size */ { size_t offset = 0; unsigned char mod, rm; /* get mod, r/m and reg fields */ mod = MODRM_MOD(modrm(u)); rm = (REX_B(u->pfx_rex) << 3) | MODRM_RM(modrm(u)); /* * If mod is 11b, then the modrm.rm specifies a register. * */ if (mod == 3) { decode_reg(u, op, type, rm, size); return; } /* * !11b => Memory Address */ op->type = UD_OP_MEM; op->size = resolve_operand_size(u, size); if (u->adr_mode == 64) { op->base = UD_R_RAX + rm; if (mod == 1) { offset = 8; } else if (mod == 2) { offset = 32; } else if (mod == 0 && (rm & 7) == 5) { op->base = UD_R_RIP; offset = 32; } else { offset = 0; } /* * Scale-Index-Base (SIB) */ if ((rm & 7) == 4) { inp_next(u); op->scale = (1 << SIB_S(inp_curr(u))) & ~1; op->index = UD_R_RAX + (SIB_I(inp_curr(u)) | (REX_X(u->pfx_rex) << 3)); op->base = UD_R_RAX + (SIB_B(inp_curr(u)) | (REX_B(u->pfx_rex) << 3)); /* special conditions for base reference */ if (op->index == UD_R_RSP) { op->index = UD_NONE; op->scale = UD_NONE; } if (op->base == UD_R_RBP || op->base == UD_R_R13) { if (mod == 0) { op->base = UD_NONE; } if (mod == 1) { offset = 8; } else { offset = 32; } } } } else if (u->adr_mode == 32) { op->base = UD_R_EAX + rm; if (mod == 1) { offset = 8; } else if (mod == 2) { offset = 32; } else if (mod == 0 && rm == 5) { op->base = UD_NONE; offset = 32; } else { offset = 0; } /* Scale-Index-Base (SIB) */ if ((rm & 7) == 4) { inp_next(u); op->scale = (1 << SIB_S(inp_curr(u))) & ~1; op->index = UD_R_EAX + (SIB_I(inp_curr(u)) | (REX_X(u->pfx_rex) << 3)); op->base = UD_R_EAX + (SIB_B(inp_curr(u)) | (REX_B(u->pfx_rex) << 3)); if (op->index == UD_R_ESP) { op->index = UD_NONE; op->scale = UD_NONE; } /* special condition for base reference */ if (op->base == UD_R_EBP) { if (mod == 0) { op->base = UD_NONE; } if (mod == 1) { offset = 8; } else { offset = 32; } } } } else { const unsigned int bases[] = { UD_R_BX, UD_R_BX, UD_R_BP, UD_R_BP, UD_R_SI, UD_R_DI, UD_R_BP, UD_R_BX }; const unsigned int indices[] = { UD_R_SI, UD_R_DI, UD_R_SI, UD_R_DI, UD_NONE, UD_NONE, UD_NONE, UD_NONE }; op->base = bases[rm & 7]; op->index = indices[rm & 7]; if (mod == 0 && rm == 6) { offset = 16; op->base = UD_NONE; } else if (mod == 1) { offset = 8; } else if (mod == 2) { offset = 16; } } if (offset) { decode_mem_disp(u, offset, op); } }
void escape(char c, char t) { U32 v; S32 delta, vofs, tmp; S8 vofsb; S16 vofsw; char *name; int extend; U8 b2, w; extend = (addrsize == 32) ? 4 : 2; switch (c) { case 'A': /* Direct Address */ ohex(t, extend, 0, addrsize); break; case 'C': /* Reg of R/M picks control reg */ fprintf(out_fh, "CR%d",reg(modrm())); break; case 'D': /* Reg of R/M pick debug reg */ fprintf(out_fh, "DR%d",modrm()); break; case 'E': /* R/M picks operand */ do_modrm(t); break; case 'G': /* Reg of R/M picks general reg */ if (t == 'F') reg_name(rm(modrm()), t); else reg_name(reg(modrm()), t); break; case 'I': /* Immediate data */ ohex(t, 0, 0, opsize); break; case 'J': /* Relative IP offset */ switch (bytes(t)) { case 1: vofsb = getbyte(); /* must remian signed! */ vofs = vofsb; break; case 2: vofsb = getbyte(); /*Must be Signed bytes/Words */ vofsw = getbyte()<<8; vofs = vofsw + vofsb; break; case 4: vofs = getbyte(); tmp = getbyte(); vofs |= tmp << 8; tmp = getbyte(); vofs |= tmp << 16; tmp = getbyte(); vofs |= tmp << 24; break; } delta = addrIn + vofs; fprintf(out_fh, "%08lX", delta); break; case 'M': /* R/M picks memory */ do_modrm(t); break; case 'O': /* NO R/M, Offset only */ expand_out("%p:["); ohex(t, extend, 0, addrsize); fprintf(out_fh,"]"); break; case 'R': /* Mod of R/M pick REG only */ do_modrm(t); break; case 'S': /* Reg of R/M picks seg reg */ fprintf(out_fh, "%s", seg_names[reg(modrm())]); break; case 'T': /* Reg of R/M picks test reg */ fprintf(out_fh, "TR%d",modrm()); break; case 'X': /* DS:ESI */ fprintf(out_fh,"DS:["); if (addrsize == 32) fprintf(out_fh,"E"); fprintf(out_fh,"SI]"); break; case 'Y': /* ES:EDI */ fprintf(out_fh,"ES:["); if (addrsize == 32) fprintf(out_fh,"E"); fprintf(out_fh,"DI]"); break; case '2': /* Prefix of 2 byte opcode */ b2 = getbyte(); if (b2 < 0x10) expand_out(SecOp00[b2]); else if ((b2 > 0x1F) && (b2 < 0x30)) expand_out(SecOp20[b2-0x20]); else if ((b2 > 0x7F) && (b2 < 0xC0)) expand_out(SecOp80[b2-0x80]); else fprintf(out_fh, "<invalid>"); break; case 'e': /* If "USE32" t is part of reg name */ if (opsize == 32) { if (t == 'w') /* put out "d" if t is "w" on USE32 segs*/ fprintf(out_fh,"D"); else { fprintf(out_fh,"E"); /* put out "E" if not t <> "w" then put t */ fputc(t, out_fh); } } else { fputc(t, out_fh); /* when USE16 just put out esc char */ } break; case 'f': /* floating point */ fprintf(out_fh,"<Float Op>"); /* floating_point(t-'0'); */ break; case 'g': /* do R/M group 'n' */ expand_out(groups[t-'0'][reg(modrm())]); break; case 'p': /* Segment prefix */ switch (t) { case 'C': /* CS */ case 'D': /* DS */ case 'E': /* ES */ case 'F': /* FS */ case 'G': /* GS */ case 'S': /* SS */ prefix = t; expand_out(opmap1[getbyte()]); break; case ':': if (prefix) { fputc(prefix, out_fh); fprintf(out_fh,"S:"); } break; case ' ': expand_out(opmap1[getbyte()]); break; } break; case 's': /* Size override */ switch (t) { case 'a': addrsize = 48 - addrsize; /* a is address */ expand_out(opmap1[getbyte()]); break; case 'o': /* o is operand */ opsize = 48 - opsize; expand_out(opmap1[getbyte()]); break; } break; } }
static void percent(char type, char subtype) { unsigned int vofs = 0; char *name; int extend = (addrsize == 32) ? 4 : 2; unsigned char c; switch(type) { case 'A': /* Direct address */ outhex(subtype, extend, 0, addrsize, 0); break; case 'C': /* reg(r/m) picks control reg */ uprintf("CR%d", REG(modrm())); must_do_size = 0; break; case 'D': /* reg(r/m) picks debug reg */ uprintf("DR%d", REG(modrm())); must_do_size = 0; break; case 'E': /* r/m picks operand */ do_modrm(subtype); break; case 'G': /* reg(r/m) picks register */ if(subtype == 'f') reg_name(RM(modrm()), subtype); else reg_name(REG(modrm()), subtype); must_do_size = 0; break; case 'I': /* Immediate data */ outhex(subtype, 0, 0, opsize, 0); break; case 'J': /* Relative IP offset */ switch(bytes(subtype)) {/* Size of offset value */ case 1: vofs = (unsigned int) (signed char) getbyte(); break; case 2: vofs = getbyte(); vofs += getbyte() << 8; vofs = (unsigned int) (signed short) vofs; break; case 4: vofs = (unsigned int) getbyte(); vofs |= (unsigned int) getbyte() << 8; vofs |= (unsigned int) getbyte() << 16; vofs |= (unsigned int) getbyte() << 24; break; } name = addr_to_hex((int) (vofs + inst_offset)); uprintf("%s", name); break; case 'K': switch(subtype) { case 'f': ua_str("FAR@"); break; case 'n': ua_str("NEAR@"); break; case 's': ua_str("SHORT@"); break; } break; case 'M': /* r/m picks memory */ do_modrm(subtype); break; case 'O': /* Offset only */ ua_str("%p:["); outhex(subtype, extend, 0, addrsize, 0); uputchar(']'); break; case 'P': /* Prefix byte */ ua_str("%p:"); break; case 'R': /* mod(r/m) picks register */ reg_name(REG(modrm()), subtype); must_do_size = 0; break; case 'S': /* reg(r/m) picks segment register */ uputchar("ECSDFG"[REG(modrm())]); uputchar('S'); must_do_size = 0; break; case 'T': /* reg(r/m) picks T reg */ uprintf("TR%d", REG(modrm())); must_do_size = 0; break; case 'X': /* DS:SI type operator */ uprintf("DS:["); if(addrsize == 32) uputchar('E'); uprintf("SI]"); break; case 'Y': /* ES:DI type operator */ uprintf("ES:["); if(addrsize == 32) uputchar('E'); uprintf("DI]"); break; case '2': /* Extended decode with second byte */ ua_str(second[getbyte()]); break; case 'g': /* modrm group 'subtype' (0--7) */ ua_str(groups[subtype-'0'][REG(modrm())]); break; case 'd': /* Size of operand == dword? */ if(opsize == 32) uputchar('D'); uputchar(subtype);/* No real subtype; following char */ break; case 'w': /* Insert explicit size specifier */ if(opsize == 32) uputchar('D'); else uputchar('W'); uputchar(subtype);/* No real subtype; following char */ break; case 'e': /* Extended reg name */ if(opsize == 32) { if(subtype == 'w') uputchar('D'); else { uputchar('E'); uputchar(subtype); } } else uputchar(subtype); break; case 'f': /* 80x87 opcode */ floating_point(subtype-'0'); break; case 'j': if(addrsize == 32 || opsize == 32) /* both of them?! */ uputchar('E'); break; case 'p': /* Prefix byte */ switch(subtype) { case 'C': case 'D': case 'E': case 'F': case 'G': case 'S': prefix = subtype; c = getbyte(); wordop = c & 1; ua_str(opmap1[c]); break; case ':': if(prefix) uprintf("%cS:", prefix); break; case ' ': c = getbyte(); wordop = c & 1; ua_str(opmap1[c]); break; } break; case 's': /* Size override */ switch(subtype) { case 'a': addrsize = 48 - addrsize; c = getbyte(); wordop = c & 1; ua_str(opmap1[c]); /* ua_str(opmap1[getbyte()]); */ break; case 'o': opsize = 48 - opsize; c = getbyte(); wordop = c & 1; ua_str(opmap1[c]); /* ua_str(opmap1[getbyte()]); */ break; } break; } }
void do_modrm(char t) { int m = mod(modrm()); int r = rm(modrm()); int extend = (addrsize == 32) ? 4 : 2; if (m == 3) { reg_name(r, t); return; } switch(bytes(t)) { case 1 : ua_str("byte ptr "); break; case 2 : ua_str("word ptr "); break; case 4 : ua_str("dword ptr "); break; default : ua_str("?word ptr "); break; } if ((m == 0) && (r == 5) && (addrsize == 32)) { ua_str("%p:["); ohex('d', extend, 0, addrsize); uprintf("%c",']'); return; } if ((m == 0) && (r == 6) && (addrsize == 16)) { ua_str("%p:["); ohex('w', extend, 0, addrsize); uprintf("%c",']'); return; } if ((addrsize != 32) || (r != 4)) ua_str("%p:["); if (addrsize == 16) { switch (r) { case 0: uprintf("bx+si"); break; case 1: uprintf("bx+di"); break; case 2: uprintf("bp+si"); break; case 3: uprintf("bp+di"); break; case 4: uprintf("si"); break; case 5: uprintf("di"); break; case 6: uprintf("bp"); break; case 7: uprintf("bx"); break; } } else { switch (r) { case 0: uprintf("eax"); break; case 1: uprintf("ecx"); break; case 2: uprintf("edx"); break; case 3: uprintf("ebx"); break; case 4: do_sib(m); break; case 5: uprintf("ebp"); break; case 6: uprintf("esi"); break; case 7: uprintf("edi"); break; } } switch (m) { case 1: ohex('b', extend, 1, addrsize); break; case 2: uprintf("+"); ohex('v', extend, 1, addrsize); break; } uprintf("%c",']'); }
int opext() { return modrm(); }
static void do_modrm(char subtype) { int mod = MOD(modrm()); int rm = RM(modrm()); int extend = (addrsize == 32) ? 4 : 2; if(mod == 3) { /* Specifies two registers */ reg_name(rm, subtype); return; } if(must_do_size) { if(wordop) { if(addrsize == 32 || opsize == 32) ua_str("DWORD@PTR@"); else ua_str("WORD@PTR@"); } else ua_str("BYTE@PTR@"); } if((mod == 0) && (rm == 5) && (addrsize == 32)) { /* Mem operand with 32 bit offset */ ua_str("%p:["); outhex('d', extend, 0, addrsize, 0); uputchar(']'); return; } if((mod == 0) && (rm == 6) && (addrsize == 16)) { /* 16 bit displacement */ ua_str("%p:["); outhex('w', extend, 0, addrsize, 0); uputchar(']'); return; } if((addrsize != 32) || (rm != 4)) ua_str("%p:["); if(addrsize == 16) { switch(rm) { case 0: uprintf("BX+SI"); break; case 1: uprintf("BX+DI"); break; case 2: uprintf("BP+SI"); break; case 3: uprintf("BP+DI"); break; case 4: uprintf("SI"); break; case 5: uprintf("DI"); break; case 6: uprintf("BP"); break; case 7: uprintf("BX"); break; } } else { switch(rm) { case 0: uprintf("EAX"); break; case 1: uprintf("ECX"); break; case 2: uprintf("EDX"); break; case 3: uprintf("EBX"); break; case 4: do_sib(mod); break; case 5: uprintf("EBP"); break; case 6: uprintf("ESI"); break; case 7: uprintf("EDI"); break; } } switch(mod) { case 1: outhex('b', extend, 1, addrsize, 0); break; case 2: outhex('v', extend, 1, addrsize, 1); break; } uputchar(']'); }
/*------------------------------------------------------------------------*/ void do_modrm(char t) { int m; int r; int extend; m = mod(modrm()); r = rm(modrm()); extend = (addrsize == 32) ? 4 : 2; if (m == 3) { reg_name(r, t); return; } if ((m == 0) && (r == 5) && (addrsize == 32)) { expand_out("%p:["); ohex('d', extend, 0, addrsize); fprintf(out_fh,"]"); return; } if ((m == 0) && (r == 6) && (addrsize == 16)) { expand_out("%p:["); ohex('w', extend, 0, addrsize); fprintf(out_fh,"]"); return; } if ((addrsize != 32) || (r != 4)) expand_out("%p:["); if (addrsize == 16) { switch (r) { case 0: fprintf(out_fh,"BX+SI"); break; case 1: fprintf(out_fh,"BX+DI"); break; case 2: fprintf(out_fh,"BP+SI"); break; case 3: fprintf(out_fh,"BP+DI"); break; case 4: fprintf(out_fh,"SI"); break; case 5: fprintf(out_fh,"DI"); break; case 6: fprintf(out_fh,"BP"); break; case 7: fprintf(out_fh,"BX"); break; } } else { switch (r) { case 0: fprintf(out_fh,"EAX"); break; case 1: fprintf(out_fh,"ECX"); break; case 2: fprintf(out_fh,"EDX"); break; case 3: fprintf(out_fh,"EBX"); break; case 4: do_sib(m); break; case 5: fprintf(out_fh,"EBP"); break; case 6: fprintf(out_fh,"ESI"); break; case 7: fprintf(out_fh,"EDI"); break; } } switch (m) { case 1: ohex('b', extend, 0, addrsize); /* was 1 */ break; case 2: fprintf(out_fh,"+"); ohex('v', extend, 0, addrsize); /* was 1 */ break; } fprintf(out_fh,"]"); }
/* Main table driver */ static void percent( char type, char subtype ) { DWORD vofs; int extend = (addrsize == 32) ? 4 : 2; BYTE c; switch (type) { case 'A': /* direct address */ SET_FLAG( Info->CurrentFlags,DISASM_FL_CODE ); outhex(subtype, extend, 0, addrsize, 0); CLR_FLAG( Info->CurrentFlags,DISASM_FL_CODE ); break; case 'C': /* reg(r/m) picks control reg */ uprintf("C%d", REG(modrm())); must_do_size = 0; break; case 'D': /* reg(r/m) picks debug reg */ uprintf("D%d", REG(modrm())); must_do_size = 0; break; case 'E': /* r/m picks operand */ do_modrm(subtype); break; case 'G': /* reg(r/m) picks register */ if (subtype == 'F') /* 80*87 operand? */ reg_name(RM(modrm()), subtype); else reg_name(REG(modrm()), subtype); must_do_size = 0; break; case 'I': /* immed data */ SET_FLAG( Info->CurrentFlags,DISASM_FL_DATA ); outhex(subtype, 0, 0, opsize, 0); CLR_FLAG( Info->CurrentFlags,DISASM_FL_DATA ); break; case 'J': /* relative IP offset */ vofs = 0; switch(bytes(subtype)) { /* sizeof offset value */ case 1: vofs = (DWORD)getbyte(); break; case 2: vofs = (DWORD)getbyte(); vofs |= (DWORD)getbyte() << 8; vofs &= 0xFFFFu; break; case 4: vofs = (DWORD)getbyte(); /* yuk! */ vofs |= (DWORD)getbyte() << 8; vofs |= (DWORD)getbyte() << 16; vofs |= (DWORD)getbyte() << 24; break; } SET_FLAG( Info->CurrentFlags,DISASM_FL_CODE|DISASM_FL_OFFSET ); uprintf("%s", addr_to_hex(vofs + Info->instruction_length,1,bytes(subtype)) ); CLR_FLAG( Info->CurrentFlags,DISASM_FL_CODE|DISASM_FL_OFFSET ); break; case 'K': if (do_distance==0) break; switch (subtype) { case 'f': uprintf( Info->GetStringName(DISASM_ID_FAR) ); uputchar(' '); break; case 'n': uprintf( Info->GetStringName(DISASM_ID_NEAR) ); uputchar(' '); break; case 's': uprintf( Info->GetStringName(DISASM_ID_SHORT) ); uputchar(' '); break; } break; case 'M': /* r/m picks memory */ do_modrm(subtype); break; case 'O': /* offset only */ ua_str("%p:["); SET_FLAG( Info->CurrentFlags,DISASM_FL_REF ); outhex(subtype, extend, 0, addrsize, 0); CLR_FLAG( Info->CurrentFlags,DISASM_FL_REF ); uputchar(']'); break; case 'P': /* prefix byte (rh) */ ua_str("%p:"); break; case 'R': /* mod(r/m) picks register */ reg_name(REG(modrm()), subtype); /* rh */ must_do_size = 0; break; case 'S': /* reg(r/m) picks segment reg */ uputchar("ecsdfg"[REG(modrm())]); uputchar('s'); must_do_size = 0; break; case 'T': /* reg(r/m) picks T reg */ uprintf("tr%d", REG(modrm())); must_do_size = 0; break; case 'X': /* ds:si type operator */ uprintf("ds:["); if (addrsize == 32) uputchar('e'); uprintf("si]"); break; case 'Y': /* es:di type operator */ uprintf("es:["); if (addrsize == 32) uputchar('e'); uprintf("di]"); break; case '2': /* old [pop cs]! now indexes */ ua_str(second[getbyte()]); /* instructions in 386/486 */ break; case 'g': /* modrm group `subtype' (0--7) */ ua_str( GetOPGroup(subtype) ); break; case 'd': /* sizeof operand==dword? */ if (opsize == 32) uputchar('d'); uputchar(subtype); break; case 'w': /* insert explicit size specifier */ if (opsize == 32) uputchar('d'); else uputchar('w'); uputchar(subtype); break; case 'e': /* extended reg name */ if (opsize == 32) { if (subtype == 'w') uputchar('d'); else { uputchar('e'); uputchar(subtype); } } else uputchar(subtype); break; case 'f': /* '87 opcode */ floating_point(subtype-'0'); break; case 'j': if (addrsize==32 || opsize==32) /* both of them?! */ uputchar('e'); break; case 'p': /* prefix byte */ switch (subtype) { case 'c': case 'd': case 'e': case 'f': case 'g': case 's': prefix = subtype; c = getbyte(); wordop = c & 1; ua_str( GetOP(c) ); break; case ':': if (prefix) uprintf("%cs:", prefix); break; case ' ': c = getbyte(); wordop = c & 1; ua_str( GetOP(c) ); break; } break; case 's': /* size override */ switch (subtype) { case 'a': addrsize = 48 - addrsize; c = getbyte(); wordop = c & 1; ua_str( GetOP(c) ); break; case 'o': opsize = 48 - opsize; c = getbyte(); wordop = c & 1; ua_str( GetOP(c) ); break; } break; } }
int onebyteinstr() { int r, b, x, y, y1, y2; b=PeekOneByte(); //fprintf(stderr, "b=%02X",b),getch(); switch(opcodeTable[b]) { case 0: r=op(); if(!r) return 0; x=result; //fprintf(stderr, "x=%02X",x),getch(); i_opclass=0; i_opcode=x; break; case 1: r=op(); if(!r) return 0; x=result; r=byte(); if(!r) return 0; y=result; i_opclass=1; i_opcode=x; i_byte=y; break; case 2: r=op(); if(!r) return 0; x=result; r=word(); if(!r) return 0; y=result; i_opclass=2; i_opcode=x; i_word=y; break; case 3: r=op(); if(!r) return 0; x=result; r=word(); if(!r) return 0; y1=result; r=byte(); if(!r) return 0; y2=result; i_opclass=3; i_opcode=x; i_word=y1; i_byte=y2; break; case 4: r=op(); if(!r) return 0; x=result; r=wdword(); if(!r) return 0; y=result; i_opclass=4; i_opcode=x; i_dword=y; break; case 44: r=op(); if(!r) return 0; x=result; r=adword(); if(!r) return 0; y=result; i_opclass=4; i_opcode=x; i_dword=y; break; case 5: r=op(); if(!r) return 0; x=result; r=pword(); if(!r) return 0; i_opclass=5; i_opcode=x; break; case 6: r=op(); if(!r) return 0; x=result; r=modrm(); if(!r) return 0; i_opclass=6; i_opcode=x; break; case 7: r=op(); if(!r) return 0; x=result; r=modrm(); if(!r) return 0; r=byte(); if(!r) return 0; y=result; i_opclass=7; i_opcode=x; i_byte=y; break; case 8: r=op(); if(!r) return 0; x=result; r=modrm(); if(!r) return 0; r=wdword(); if(!r) return 0; y=result; i_opclass=8; i_opcode=x; i_dword=y; break; case 9: r=op(); if(!r) return 0; x=result; r=opext(); if(!r) return 0; i_opclass=9; i_opcode=x; break; case 10: r=op(); if(!r) return 0; x=result; r=opext(); if(!r) return 0; r=byte(); if(!r) return 0; y=result; i_opclass=10; i_opcode=x; i_byte=y; break; case 11: r=op(); if(!r) return 0; x=result; r=opext(); if(!r) return 0; r=wdword(); if(!r) return 0; y=result; i_opclass=11; i_opcode=x; i_dword=y; break; case 12: r=op(); if(!r) return 0; x=result; r=opextg(); if(!r) return 0; i_opclass=12; i_opcode=x; break; case 13: r=op(); if(!r) return 0; x=result; // case jump block b=PeekOneByte(); if (b==36) { b=PeekSecondByte(); if (rmTable[b]==5) { r=op(); if(!r) return 0; y1=result; r=op(); if(!r) return 0; y2=result; i_opclass=13; i_opcode=x; i_mod=y1; i_sib=y2; r=labelstartposition(); if(!r) return 0; // .................................................................. if (nextMode) { r=label1(); finished=1; if(!r) return 1; // need to be careful ... } return 1; } } //else { b=PeekOneByte(); if (regTable[b]<7) { r=opext(); if(!r) return 0; i_opclass=13; i_opcode=x; } else return 0; } break; case 14: r=op(); if(!r) return 0; x=result; // test group if (x==246) { b=PeekOneByte(); if (regTable[b]==0) { r=opext(); if(!r) return 0; r=byte(); if(!r) return 0; y=result; i_opclass=14; i_opcode=x; i_byte=y; } else if (regTable[b]>1) { r=opext(); if(!r) return 0; i_opclass=14; i_opcode=x; } else return 0; } else { b=PeekOneByte(); if (regTable[b]==0) { r=opext(); if(!r) return 0; r=wdword(); if(!r) return 0; y=result; i_opclass=14; i_opcode=x; i_dword=y; } else { r=opext(); if(!r) return 0; i_opclass=14; i_opcode=x; } } break; case 15: r=op(); if(!r) return 0; x=result; // wait group i_opclass=15; i_opcode=x; b=PeekOneByte(); if (b==217) { b=PeekSecondByte(); if (regTable[b]==6||regTable[b]==7) { r=op(); if(!r) return 0; y=result; r=opext(); if(!r) return 0; i_opcode=y; prefixStack[i_psp++]=x; } } else if (b==219) { b=PeekSecondByte(); if (b==226||b==227) { r=op(); if(!r) return 0; y1=result; r=op(); if(!r) return 0; y2=result; i_opcode=y1; i_mod=y2; prefixStack[i_psp++]=x; } } else if (b==221) { b=PeekSecondByte(); if (regTable[b]==6||regTable[b]==7) { r=op(); if(!r) return 0; y=result; r=opext(); if(!r) return 0; i_opcode=y; prefixStack[i_psp++]=x; } } else if (b==223) { b=PeekSecondByte(); if (b==224) { r=op(); if(!r) return 0; y1=result; r=op(); if(!r) return 0; y2=result; i_opcode=y1; i_mod=y2; prefixStack[i_psp++]=x; } } break; case 16: r=op(); if(!r) return 0; x=result; // repeat group if (x==242) { while(prefixes()); b=PeekOneByte(); if (repeatgroupTable[b]==1) { r=op(); if(!r) return 0; y=result; i_opclass=16; i_opcode=y; prefixStack[i_psp++]=x; } else return 0; } else { while(prefixes()); b=PeekOneByte(); if (repeatgroupTable[b]>0) { r=op(); if(!r) return 0; y=result; i_opclass=16; i_opcode=y; prefixStack[i_psp++]=x; } else return 0; } break; default: return 0; } return 1; }
/*------------------------------------------------------------------------*/ static void do_modrm(char subtype) { int mod = MOD(modrm()); int rm = RM(modrm()); int extend = (addrsize == 32) ? 4 : 2; /* specifies two registers */ if (mod == 3) { reg_name(rm, subtype); return; } if (must_do_size) { if (wordop) { if (addrsize==32 || opsize==32) /* then must specify size */ uprintf( Info->GetStringName(DISASM_ID_DWORD_PTR) ); else uprintf( Info->GetStringName(DISASM_ID_WORD_PTR) ); } else uprintf( Info->GetStringName(DISASM_ID_BYTE_PTR) ); uputchar(' '); } /* mem operand with 32 bit ofs */ if ((mod == 0) && (rm == 5) && (addrsize == 32)) { ua_str("%p:["); SET_FLAG( Info->CurrentFlags,DISASM_FL_REF ); outhex('d', extend, 0, addrsize, 0); CLR_FLAG( Info->CurrentFlags,DISASM_FL_REF ); uputchar(']'); } else /* 16 bit dsplcmnt */ if ((mod == 0) && (rm == 6) && (addrsize == 16)) { ua_str("%p:["); SET_FLAG( Info->CurrentFlags,DISASM_FL_REF ); outhex('w', extend, 0, addrsize, 0); CLR_FLAG( Info->CurrentFlags,DISASM_FL_REF ); uputchar(']'); } else { /*All other*/ if ( (addrsize != 32) || (rm != 4) ) ua_str("%p:["); SET_FLAG( Info->CurrentFlags,DISASM_FL_REF | DISASM_FL_REFADD ); if (addrsize == 16) switch (rm) { case 0: uprintf("bx+si"); break; case 1: uprintf("bx+di"); break; case 2: uprintf("bp+si"); break; case 3: uprintf("bp+di"); break; case 4: uprintf("si"); break; case 5: uprintf("di"); break; case 6: uprintf("bp"); break; case 7: uprintf("bx"); break; } else switch (rm) { case 0: uprintf("eax"); break; case 1: uprintf("ecx"); break; case 2: uprintf("edx"); break; case 3: uprintf("ebx"); break; case 4: do_sib(mod); break; case 5: uprintf("ebp"); break; case 6: uprintf("esi"); break; case 7: uprintf("edi"); break; } switch (mod) { case 1: outhex('b', extend, 1, addrsize, 0); break; case 2: outhex('v', extend, 1, addrsize, 1); break; } CLR_FLAG( Info->CurrentFlags,DISASM_FL_REF | DISASM_FL_REFADD ); uputchar(']'); } }
/* Main table driver */ static void percent(char type, char subtype) { int32 vofs; char *name; int extend = (addrsize == 32) ? 4 : 2; char c; switch (type) { case 'A': /* direct address */ outhex(subtype, extend, 0, addrsize, 0); break; case 'C': /* reg(r/m) picks control reg */ uprintf("C%d", REG(modrm())); must_do_size = 0; break; case 'D': /* reg(r/m) picks debug reg */ uprintf("D%d", REG(modrm())); must_do_size = 0; break; case 'E': /* r/m picks operand */ do_modrm(subtype); break; case 'G': /* reg(r/m) picks register */ if (subtype == 'F') /* 80*87 operand? */ reg_name(RM(modrm()), subtype); else reg_name(REG(modrm()), subtype); must_do_size = 0; break; case 'I': /* immed data */ outhex(subtype, 0, 0, opsize, 0); break; case 'J': /* relative IP offset */ switch(bytes(subtype)) { /* sizeof offset value */ case 1: vofs = (int8)getbyte(); break; case 2: vofs = getbyte(); vofs += getbyte()<<8; vofs = (int16)vofs; break; case 4: vofs = (word32)getbyte(); /* yuk! */ vofs |= (word32)getbyte() << 8; vofs |= (word32)getbyte() << 16; vofs |= (word32)getbyte() << 24; break; } name = addr_to_hex(vofs+instruction_offset,1); uprintf("%s", name); break; case 'K': if (do_distance==0) break; switch (subtype) { case 'f': ua_str("far "); break; case 'n': ua_str("near "); break; case 's': ua_str("short "); break; } break; case 'M': /* r/m picks memory */ do_modrm(subtype); break; case 'O': /* offset only */ ua_str("%p:["); outhex(subtype, extend, 0, addrsize, 0); uputchar(']'); break; case 'P': /* prefix byte (rh) */ ua_str("%p:"); break; case 'R': /* mod(r/m) picks register */ reg_name(REG(modrm()), subtype); /* rh */ must_do_size = 0; break; case 'S': /* reg(r/m) picks segment reg */ uputchar("ecsdfg"[REG(modrm())]); uputchar('s'); must_do_size = 0; break; case 'T': /* reg(r/m) picks T reg */ uprintf("tr%d", REG(modrm())); must_do_size = 0; break; case 'X': /* ds:si type operator */ uprintf("ds:["); if (addrsize == 32) uputchar('e'); uprintf("si]"); break; case 'Y': /* es:di type operator */ uprintf("es:["); if (addrsize == 32) uputchar('e'); uprintf("di]"); break; case '2': /* old [pop cs]! now indexes */ ua_str(second[getbyte()]); /* instructions in 386/486 */ break; case 'g': /* modrm group `subtype' (0--7) */ ua_str(groups[subtype-'0'][REG(modrm())]); break; case 'd': /* sizeof operand==dword? */ if (opsize == 32) uputchar('d'); uputchar(subtype); break; case 'w': /* insert explicit size specifier */ if (opsize == 32) uputchar('d'); else uputchar('w'); uputchar(subtype); break; case 'e': /* extended reg name */ if (opsize == 32) { if (subtype == 'w') uputchar('d'); else { uputchar('e'); uputchar(subtype); } } else uputchar(subtype); break; case 'f': /* '87 opcode */ floating_point(subtype-'0'); break; case 'j': if (addrsize==32 || opsize==32) /* both of them?! */ uputchar('e'); break; case 'p': /* prefix byte */ switch (subtype) { case 'c': case 'd': case 'e': case 'f': case 'g': case 's': prefix = subtype; c = getbyte(); wordop = c & 1; ua_str(opmap1[(unsigned char)c]); break; case ':': if (prefix) uprintf("%cs:", prefix); break; case ' ': c = getbyte(); wordop = c & 1; ua_str(opmap1[(unsigned char)c]); break; } break; case 's': /* size override */ switch (subtype) { case 'a': addrsize = 48 - addrsize; c = getbyte(); wordop = c & 1; ua_str(opmap1[(unsigned char)c]); /* ua_str(opmap1[getbyte()]); */ break; case 'o': opsize = 48 - opsize; c = getbyte(); wordop = c & 1; ua_str(opmap1[(unsigned char)c]); /* ua_str(opmap1[getbyte()]); */ break; } break; } }
static char *GetOPGroup( char subtype ) { SetFlags( group_flags[ subtype-'0' ][ REG(modrm()) ] ); return groups[subtype-'0'][REG(modrm())]; }
static void percent(char c, char t) { word32 vofs; long l; int extend = (addrsize == 32) ? 4 : 2; switch (c) { case 'A': ohex(t, extend, 0, addrsize); break; case 'C': uprintf("C%d", reg(modrm())); break; case 'D': uprintf("D%d", reg(modrm())); break; case 'E': do_modrm(t); break; case 'G': if (t == 'F') reg_name(rm(modrm()), t); else reg_name(reg(modrm()), t); break; case 'I': ohex(t, 0, 0, opsize); break; case 'J': switch (bytes(t)) { case 1: vofs = (int8)getbyte(); break; case 2: vofs = getbyte(); vofs += getbyte()<<8; vofs = (int16)vofs; break; case 4: vofs = (word32)getbyte(); vofs |= (word32)getbyte() << 8; vofs |= (word32)getbyte() << 16; vofs |= (word32)getbyte() << 24; break; } l=vofs+codeoff; if(l<0x10000L) uprintf("%s%04lx%s %c", hex1, l, hex2, (vofs & 0x80000000L) ? 0x18 : 0x19); else uprintf("%s%08lX%s %c", hex1, l, hex2, (vofs & 0x80000000L) ? 0x18 : 0x19); break; case 'M': do_modrm(t); break; case 'O': ua_str("%p:["); ohex(t, extend, 0, addrsize); uprintf("%c",']'); break; case 'R': reg_name(reg(modrm()), t); //do_modrm(t); break; case 'S': uprintf("%c","ecsdfg"[reg(modrm())]); uprintf("%c",'s'); break; case 'T': uprintf("tr%d", reg(modrm())); break; case 'X': uprintf("ds:["); if (addrsize == 32) uprintf("%c",'e'); uprintf("si]"); break; case 'Y': uprintf("es:["); if (addrsize == 32) uprintf("%c",'e'); uprintf("di]"); break; case '2': ua_str(second[getbyte()]); break; case 'e': if (opsize == 32) { if (t == 'w') uprintf("%c",'d'); else { uprintf("%c",'e'); uprintf("%c",t); } } else uprintf("%c",t); break; case 'f': floating_point(t-'0'); break; case 'g': ua_str(groups[t-'0'][reg(modrm())]); break; case 'p': switch (t) { case 'c': case 'd': case 'e': case 'f': case 'g': case 's': prefix = t; ua_str(opmap1[getbyte()]); break; case ':': if (prefix) uprintf("%cs:", prefix); break; case ' ': ua_str(opmap1[getbyte()]); break; } break; case 's': switch (t) { case 'a': addrsize = 48 - addrsize; ua_str(opmap1[getbyte()]); break; case 'o': opsize = 48 - opsize; ua_str(opmap1[getbyte()]); break; } break; } }