⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 i386-dis.c

📁 ReactOS是一些高手根据Windows XP的内核编写出的类XP。内核实现机理和API函数调用几乎相同。甚至可以兼容XP的程序。喜欢研究系统内核的人可以看一看。
💻 C
📖 第 1 页 / 共 5 页
字号:
	     following instruction.  */
	  if (prefixes)
	    {
	      prefixes |= PREFIX_FWAIT;
	      codep++;
	      return;
	    }
	  prefixes = PREFIX_FWAIT;
	  break;
	default:
	  return;
	}
      /* Rex is ignored when followed by another prefix.  */
      if (rex)
	{
	  oappend (prefix_name (rex, 0));
	  oappend (" ");
	}
      rex = newrex;
      codep++;
    }
}

/* Return the name of the prefix byte PREF, or NULL if PREF is not a
   prefix byte.  */

static const char *
prefix_name (pref, sizeflag)
     int pref;
     int sizeflag;
{
  switch (pref)
    {
    /* REX prefixes family.  */
    case 0x40:
      return "rex";
    case 0x41:
      return "rexZ";
    case 0x42:
      return "rexY";
    case 0x43:
      return "rexYZ";
    case 0x44:
      return "rexX";
    case 0x45:
      return "rexXZ";
    case 0x46:
      return "rexXY";
    case 0x47:
      return "rexXYZ";
    case 0x48:
      return "rex64";
    case 0x49:
      return "rex64Z";
    case 0x4a:
      return "rex64Y";
    case 0x4b:
      return "rex64YZ";
    case 0x4c:
      return "rex64X";
    case 0x4d:
      return "rex64XZ";
    case 0x4e:
      return "rex64XY";
    case 0x4f:
      return "rex64XYZ";
    case 0xf3:
      return "repz";
    case 0xf2:
      return "repnz";
    case 0xf0:
      return "lock";
    case 0x2e:
      return "cs";
    case 0x36:
      return "ss";
    case 0x3e:
      return "ds";
    case 0x26:
      return "es";
    case 0x64:
      return "fs";
    case 0x65:
      return "gs";
    case 0x66:
      return (sizeflag & DFLAG) ? "data16" : "data32";
    case 0x67:
      if (mode_64bit)
        return (sizeflag & AFLAG) ? "addr32" : "addr64";
      else
        return ((sizeflag & AFLAG) && !mode_64bit) ? "addr16" : "addr32";
    case FWAIT_OPCODE:
      return "fwait";
    default:
      return NULL;
    }
}

static char op1out[100], op2out[100], op3out[100];
static int op_ad, op_index[3];
static bfd_vma op_address[3];
static bfd_vma op_riprel[3];
static bfd_vma start_pc;

/*
 *   On the 386's of 1988, the maximum length of an instruction is 15 bytes.
 *   (see topic "Redundant prefixes" in the "Differences from 8086"
 *   section of the "Virtual 8086 Mode" chapter.)
 * 'pc' should be the address of this instruction, it will
 *   be used to print the target address if this is a relative jump or call
 * The function returns the length of this instruction in bytes.
 */

static char intel_syntax;
static char open_char;
static char close_char;
static char separator_char;
static char scale_char;

/* Here for backwards compatibility.  When gdb stops using
   print_insn_i386_att and print_insn_i386_intel these functions can
   disappear, and print_insn_i386 be merged into print_insn.  */
int
print_insn_i386_att (pc, info)
     bfd_vma pc;
     disassemble_info *info;
{
  intel_syntax = 0;

  return print_insn (pc, info);
}

int
print_insn_i386_intel (pc, info)
     bfd_vma pc;
     disassemble_info *info;
{
  intel_syntax = 1;

  return print_insn (pc, info);
}

int
print_insn_i386 (pc, info)
     bfd_vma pc;
     disassemble_info *info;
{
  intel_syntax = -1;

  return print_insn (pc, info);
}

static int
print_insn (pc, info)
     bfd_vma pc;
     disassemble_info *info;
{
  const struct dis386 *dp;
  int i;
  int two_source_ops;
  char *first, *second, *third;
  int needcomma;
  unsigned char uses_SSE_prefix;
  int sizeflag;
  /*const char *p;*/
  struct dis_private priv;

  mode_64bit = (info->mach == bfd_mach_x86_64_intel_syntax
		|| info->mach == bfd_mach_x86_64);

  if (intel_syntax == -1)
    intel_syntax = (info->mach == bfd_mach_i386_i386_intel_syntax
		    || info->mach == bfd_mach_x86_64_intel_syntax);

  if (info->mach == bfd_mach_i386_i386
      || info->mach == bfd_mach_x86_64
      || info->mach == bfd_mach_i386_i386_intel_syntax
      || info->mach == bfd_mach_x86_64_intel_syntax)
    priv.orig_sizeflag = AFLAG | DFLAG;
  else if (info->mach == bfd_mach_i386_i8086)
    priv.orig_sizeflag = 0;
  else
    abort ();

#if 0
  for (p = info->disassembler_options; p != NULL; )
    {
      if (strncmp (p, "x86-64", 6) == 0)
	{
	  mode_64bit = 1;
	  priv.orig_sizeflag = AFLAG | DFLAG;
	}
      else if (strncmp (p, "i386", 4) == 0)
	{
	  mode_64bit = 0;
	  priv.orig_sizeflag = AFLAG | DFLAG;
	}
      else if (strncmp (p, "i8086", 5) == 0)
	{
	  mode_64bit = 0;
	  priv.orig_sizeflag = 0;
	}
      else if (strncmp (p, "intel", 5) == 0)
	{
	  intel_syntax = 1;
	}
      else if (strncmp (p, "att", 3) == 0)
	{
	  intel_syntax = 0;
	}
      else if (strncmp (p, "addr", 4) == 0)
	{
	  if (p[4] == '1' && p[5] == '6')
	    priv.orig_sizeflag &= ~AFLAG;
	  else if (p[4] == '3' && p[5] == '2')
	    priv.orig_sizeflag |= AFLAG;
	}
      else if (strncmp (p, "data", 4) == 0)
	{
	  if (p[4] == '1' && p[5] == '6')
	    priv.orig_sizeflag &= ~DFLAG;
	  else if (p[4] == '3' && p[5] == '2')
	    priv.orig_sizeflag |= DFLAG;
	}
      else if (strncmp (p, "suffix", 6) == 0)
	priv.orig_sizeflag |= SUFFIX_ALWAYS;

      p = strchr (p, ',');
      if (p != NULL)
	p++;
    }
#else
  mode_64bit = 0;
  priv.orig_sizeflag = AFLAG | DFLAG;
  /*intel_syntax = 0;*/
#endif

  if (intel_syntax)
    {
      names64 = intel_names64;
      names32 = intel_names32;
      names16 = intel_names16;
      names8 = intel_names8;
      names8rex = intel_names8rex;
      names_seg = intel_names_seg;
      index16 = intel_index16;
      open_char = '[';
      close_char = ']';
      separator_char = '+';
      scale_char = '*';
    }
  else
    {
      names64 = att_names64;
      names32 = att_names32;
      names16 = att_names16;
      names8 = att_names8;
      names8rex = att_names8rex;
      names_seg = att_names_seg;
      index16 = att_index16;
      open_char = '(';
      close_char =  ')';
      separator_char = ',';
      scale_char = ',';
    }

  /* The output looks better if we put 7 bytes on a line, since that
     puts most long word instructions on a single line.  */
  info->bytes_per_line = 7;

  info->private_data = (PTR) &priv;
  priv.max_fetched = priv.the_buffer;
  priv.insn_start = pc;

  obuf[0] = 0;
  op1out[0] = 0;
  op2out[0] = 0;
  op3out[0] = 0;

  op_index[0] = op_index[1] = op_index[2] = -1;

  the_info = info;
  start_pc = pc;
  start_codep = priv.the_buffer;
  codep = priv.the_buffer;

  if (setjmp (priv.bailout) != 0)
    {
      const char *name;

      /* Getting here means we tried for data but didn't get it.  That
	 means we have an incomplete instruction of some sort.  Just
	 print the first byte as a prefix or a .byte pseudo-op.  */
      if (codep > priv.the_buffer)
	{
	  name = prefix_name (priv.the_buffer[0], priv.orig_sizeflag);
	  if (name != NULL)
	    (*info->fprintf_func) (info->stream, "%s", name);
	  else
	    {
	      /* Just print the first byte as a .byte instruction.  */
	      (*info->fprintf_func) (info->stream, ".byte 0x%x",
				     (unsigned int) priv.the_buffer[0]);
	    }

	  return 1;
	}

      return -1;
    }

  obufp = obuf;
  ckprefix ();

  insn_codep = codep;
  sizeflag = priv.orig_sizeflag;

  FETCH_DATA (info, codep + 1);
  two_source_ops = (*codep == 0x62) || (*codep == 0xc8);

  if ((prefixes & PREFIX_FWAIT)
      && ((*codep < 0xd8) || (*codep > 0xdf)))
    {
      const char *name;

      /* fwait not followed by floating point instruction.  Print the
         first prefix, which is probably fwait itself.  */
      name = prefix_name (priv.the_buffer[0], priv.orig_sizeflag);
      if (name == NULL)
	name = INTERNAL_DISASSEMBLER_ERROR;
      (*info->fprintf_func) (info->stream, "%s", name);
      return 1;
    }

  if (*codep == 0x0f)
    {
      FETCH_DATA (info, codep + 2);
      dp = &dis386_twobyte[*++codep];
      need_modrm = twobyte_has_modrm[*codep];
      uses_SSE_prefix = twobyte_uses_SSE_prefix[*codep];
    }
  else
    {
      dp = &dis386[*codep];
      need_modrm = onebyte_has_modrm[*codep];
      uses_SSE_prefix = 0;
    }
  codep++;

  if (!uses_SSE_prefix && (prefixes & PREFIX_REPZ))
    {
      oappend ("repz ");
      used_prefixes |= PREFIX_REPZ;
    }
  if (!uses_SSE_prefix && (prefixes & PREFIX_REPNZ))
    {
      oappend ("repnz ");
      used_prefixes |= PREFIX_REPNZ;
    }
  if (prefixes & PREFIX_LOCK)
    {
      oappend ("lock ");
      used_prefixes |= PREFIX_LOCK;
    }

  if (prefixes & PREFIX_ADDR)
    {
      sizeflag ^= AFLAG;
      if (dp->bytemode3 != loop_jcxz_mode || intel_syntax)
	{
	  if ((sizeflag & AFLAG) || mode_64bit)
	    oappend ("addr32 ");
	  else
	    oappend ("addr16 ");
	  used_prefixes |= PREFIX_ADDR;
	}
    }

  if (!uses_SSE_prefix && (prefixes & PREFIX_DATA))
    {
      sizeflag ^= DFLAG;
      if (dp->bytemode3 == cond_jump_mode
	  && dp->bytemode1 == v_mode
	  && !intel_syntax)
	{
	  if (sizeflag & DFLAG)
	    oappend ("data32 ");
	  else
	    oappend ("data16 ");
	  used_prefixes |= PREFIX_DATA;
	}
    }

  if (need_modrm)
    {
      FETCH_DATA (info, codep + 1);
      mod = (*codep >> 6) & 3;
      reg = (*codep >> 3) & 7;
      rm = *codep & 7;
    }

  if (dp->name == NULL && dp->bytemode1 == FLOATCODE)
    {
      dofloat (sizeflag);
    }
  else
    {
      int index;
      if (dp->name == NULL)
	{
	  switch (dp->bytemode1)
	    {
	    case USE_GROUPS:
	      dp = &grps[dp->bytemode2][reg];
	      break;

	    case USE_PREFIX_USER_TABLE:
	      index = 0;
	      used_prefixes |= (prefixes & PREFIX_REPZ);
	      if (prefixes & PREFIX_REPZ)
		index = 1;
	      else
		{
		  used_prefixes |= (prefixes & PREFIX_DATA);
		  if (prefixes & PREFIX_DATA)
		    index = 2;
		  else
		    {
		      used_prefixes |= (prefixes & PREFIX_REPNZ);
		      if (prefixes & PREFIX_REPNZ)
			index = 3;
		    }
		}
	      dp = &prefix_user_table[dp->bytemode2][index];
	      break;

	    case X86_64_SPECIAL:
	      dp = &x86_64_table[dp->bytemode2][mode_64bit];
	      break;

	    default:
	      oappend (INTERNAL_DISASSEMBLER_ERROR);
	      break;
	    }
	}

      if (putop (dp->name, sizeflag) == 0)
	{
	  obufp = op1out;
	  op_ad = 2;
	  if (dp->op1)
	    (*dp->op1) (dp->bytemode1, sizeflag);

	  obufp = op2out;
	  op_ad = 1;
	  if (dp->op2)
	    (*dp->op2) (dp->bytemode2, sizeflag);

	  obufp = op3out;
	  op_ad = 0;
	  if (dp->op3)
	    (*dp->op3) (dp->bytemode3, sizeflag);
	}
    }

  /* See if any prefixes were not used.  If so, print the first one
     separately.  If we don't do this, we'll wind up printing an
     instruction stream which does not pr

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -