📄 i386-dis.c
字号:
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 + -