Example #1
0
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");
	}
}
Example #2
0
/*
 * 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;
}
Example #5
0
/*
 * 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);
}
Example #6
0
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");
	}
}
Example #7
0
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;
}
Example #8
0
/*
 * 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);
  }
}
Example #9
0
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;
}
Example #10
0
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;
}
Example #11
0
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;
}
Example #12
0
/* -----------------------------------------------------------------------------
 * 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;
}
Example #13
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;
  }
}
Example #14
0
/*------------------------------------------------------------------------*/
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(']');
}
Example #15
0
/* -----------------------------------------------------------------------------
 * 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;
}
Example #16
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);
  }
}
Example #17
0
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;
  }
}
Example #18
0
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;
	}
}
Example #19
0
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",']');
}
Example #20
0
int opext()
{
   return modrm();
}
Example #21
0
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(']');
}
Example #22
0
/*------------------------------------------------------------------------*/
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,"]");
}
Example #23
0
/* 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;
   }
}
Example #24
0
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;
}
Example #25
0
/*------------------------------------------------------------------------*/
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(']');
  }
}
Example #26
0
/* 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;
   }
}
Example #27
0
static char *GetOPGroup( char subtype )
  {
    SetFlags( group_flags[ subtype-'0' ][ REG(modrm()) ] );
 return groups[subtype-'0'][REG(modrm())];
}
Example #28
0
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;
	}
}