xde反汇编引擎源码

来源:互联网 发布:华为网络管理平台 编辑:程序博客网 时间:2024/05/09 00:04

这是用c语言写的经典XDE反汇编引擎源代码


1.写在前面的话
                       eXtended (XDE) disassembler engine
                       ----------------------------------
                                 version 1.02

  History:

    1.01 - 1st release
    1.02 - lock prefix bug is fixed, thanx to www.core-dump.com.hr

 


  Note: its better to read "Permutation conditions" article before.

  XDE is based on the LDE/ADE engines. It allows you to find length of any x86
  instruction, source/destination register usage for most commonly
  used instructions, and to split/merge instruction to/from some binary
  structure.

  From program's viewpoint, CPU operates with: different types of registers,
  memory and io-devices.
  As such, there are introduced "object set" concept,
  which means bitset of registers/memory/etc. being read/written by
  each instruction.

  However, some of bits forming "object set" corresponds to
  multiple objects, for example we dont distinguish between segment/FPU/MMX/...
  registers, so we have XSET_OTHER bit flag, which, when used, means
  any set of them.

  Also, we dont distinguish between memory addresses.
  For example, XDE will return XSET_MEM bit flag for both "mov [eax], ebx"
  and "push ecx" instructions.
  This is because we're focused on the static file analysis, where register
  values are unknown in most cases.
  Also, like in the example shown, if eax points to the stack,
  two memory addresses could be equal (eax==esp),
  but we cant determine it without complex analysis
  which is not required for our purposes.

  I've rejected an idea from the "Permutation conditions" article,
  where "destination" object set overrides "source" object set;
  in the XDE engine there is no any relation between these sets.

  There are two subroutines:

int __cdecl xde_disasm(/* IN */ unsigned char *opcode,
                       /* OUT */ struct xde_instr *diza);

int __cdecl xde_asm(/* OUT */ unsigned char* opcode,
                    /* IN */ struct xde_instr* diza);

  xde_disasm() splits given instruction into the xde_instr structure.

  xde_asm() performs inverse operation: merges instruction from the
  given xde_instr structure.

  Structure is the following:

struct xde_instr
{
  unsigned char  defaddr;        /* 2 or 4, depends on 0x67 prefix          */
  unsigned char  defdata;        /* 2 or 4, depends on 0x66 prefix          */
  unsigned long  len;            /* total instruction length                */
  unsigned long  flag;           /* set of C_xxx flags                      */
  unsigned long  addrsize;       /* size of address (or 0)                  */
  unsigned long  datasize;       /* size of data (or 0)                     */
  unsigned char  p_lock;         /* 0 or F0                                 */
  unsigned char  p_66;           /* 0 or 66                                 */
  unsigned char  p_67;           /* 0 or 67                                 */
  unsigned char  p_rep;          /* 0 or F2/F3                              */
  unsigned char  p_seg;          /* 0 or 26/2E/36/3E/64/65                  */
  unsigned char  opcode;         /* opcode byte (if 0x0F, opcode2 is set)   */
  unsigned char  opcode2;        /* if opcode==0x0F, contains 2nd opcode    */
  unsigned char  modrm;          /* modr/m byte (if C_MODRM)                */
  unsigned char  sib;            /* sib byte (if C_SIB)                     */
  unsigned long  src_set;        /* SRC object set (instr. will READ 'em)   */
  unsigned long  dst_set;        /* DST object set (instr. will WRITE 'em)  */
  union
  {
  unsigned char  addr_b[8];      /* address bytes, size = addrsize          */
  unsigned short addr_w[4];
  unsigned long  addr_d[2];
  signed char    addr_c[8];
  signed short   addr_s[4];
  signed long    addr_l[2];
  };
  union
  {
  unsigned char  data_b[8];      /* data (imm) bytes, size = datasize       */
  unsigned short data_w[4];
  unsigned long  data_d[2];
  signed char    data_c[8];
  signed short   data_s[4];
  signed long    data_l[2];
  };
}; /* struct xde_instr */

  As you can see, mostly all fields are the same as in ADE engine,
  except new src_set and dst_set fields.

  These two bitfields describes registers used;
  see XDE.H for possible bitfield values.

  XSET_FL flag means any bit of EFLAGS register.
  XSET_MEM flag means any memory address.
  XSET_OTHER flag means any register except eax-edi.
  XSET_DEV flag means io-port(s).

  For example, for 'REP INSB' instruction you will get

  src_set = { XSET_ECX(CX) | XSET_EDI(DI) | DX | XSET_DEV | XSET_FL }
  dst_set = { XSET_ECX(CX) | XSET_FL | XSET_MEM }

  Here is little error: for any REP prefix XSET_FL is included into dst_set,
  maybe i'll fix it later.

  Except these two fields, 'flag' field is slightly changed.
  Now it has 5 special bits which forms command id.
  Currently, only one id is defined, for CALL command.

#define C_CMD_CALL   ( 1 << C_x_shift)

  It can be extracted from the flags field using the following macro:

#define XDE_CMD(fl)  ((fl) & C_x_mask)      /* extract CMD from flags       */

  There can be combinations of src_set and dst_set:

  example: 'add eax, ebx'

  description        READ   WRITE  formula

  source regs         +       ?    src_set                      {eax|ebx}
  destination regs    ?       +    dst_set                      {eax|flags}
  modified regs       +       +    dst_set & src_set            {eax}
  read-only regs      +       -    src_set & ~dst_set           {ebx}
  write-only regs     -       +    dst_set & ~src_set           {flags}


  USAGE EXAMPLE
  =============


  The following example shows how XDE can be used to find
  "free registers set" at each position of the pe exe/dll file
  being disassembled using Mistfall engine.


int AnalyzeRegs(/* IN/OUT */ CMistfall* M)
{

  HOOY* h;   // current element of the file, instruction or anything else

  // step 1/3 -- mark all registers as "used"

  ForEachInList(M->HooyList, HOOY, h)
  {
    h->regused = XSET_UNDEF;
  }

  // step 2/3 -- for each instruction, clear dst_set&~src_set

  ForEachInList(M->HooyList, HOOY, h)
  {

    if (h->flags & FL_OPCODE)
    if ((h->flags & FL_ERROR) == 0)

    {
      xde_instr instr;
      xde_disasm(h->dataptr, &instr);

      // update h->regused

      h->regused &= ~(instr.dst_set & (~instr.src_set));

      //
      // incorrect, need to be replaced with recursive subroutine analysis.
      // however, the following means:
      //   "CALL'ed subroutines doesnt use FLAGS as a source_object"
      //
      if (XDE_CMD(instr.flag) == C_CMD_CALL)
        h->regused &= ~XSET_FL;
      //

    }

  }

  // step 3/3 -- propagate zero bits within freeset, until possible;
  // works similar to "wave" algo

  for(;;)
  {
    int modified = 0;

    ForEachInList(M->HooyList, HOOY, h)
    {

      if (h->flags & FL_OPCODE)
      if ((h->flags & FL_ERROR) == 0)

      if (h->next)
      if (h->next->flags & FL_OPCODE)
      if ((h->next->flags & (FL_LABEL|FL_ERROR)) == 0)

      {
        xde_instr instr;
        xde_disasm(h->dataptr, &instr);

        if (((instr.src_set|instr.dst_set) & (~h->next->regused)) == 0)
        {

          if ((h->regused & h->next->regused) != h->regused)
            modified++;

          h->regused &= h->next->regused;

        }
      }

    }

    if (!modified) break;
  }

  return 1;

} // AnalyzeRegs

  After such an analysis is performed, we know which registers are unused
  at the each position of the file.
  Then, corresponding code can be generated and injected into the executable.

  The only difference between old mistfall possibilities is that
  now it is not required to generate prolog/epilog push/pop pairs
  in the code snippet(s) being injected,
  since it is known which registers could be used.

<eof>


2.xde.h文件

/* XDE v1.02 eXtended length disassembler engine, based on LDE/ADE engines */

#ifndef __XDE_H__
#define __XDE_H__

/* table indexes */

#define TBL_NORMAL 0             /* table index: normal opcodes             */
#define TBL_0F     256           /* table index: 0F-prefixed opcodes        */
#define TBL_80_83  512           /* table index: 80/81/82/83 /ttt           */
#define TBL_F6     520           /* table index: F6 /ttt                    */
#define TBL_F7     528           /* table index: F7 /ttt                    */
#define TBL_FE     536           /* table index: FE /ttt                    */
#define TBL_FF     544           /* table index: FF /ttt                    */
#define TBL_max    552              /* total entries in the xde_table[]        */
#define TBL_size   (TBL_max*4)   /* total xde_table[] size, in BYTEs        */

/* instruction flags */

#define C_SPECIAL  0             /* NOT A FLAG, must be zero                */
#define C_ADDR1    0x00000001    /* }                                       */
#define C_ADDR2    0x00000002    /* } when OR'ed, we have total addr size   */
#define C_ADDR4    0x00000004    /* }                                       */
#define C_MODRM    0x00000008    /* there is MOD<reg|ttt>R/M                */
#define C_SIB      0x00000010    /* there is SIB                            */
#define C_ADDR67   0x00000020    /* address size = defaddr                  */
#define C_DATA66   0x00000040    /* data size = defdata                     */
#define C_UNDEF    0x00000080    /* register values become UNDEFINED        */
#define C_DATA1    0x00000100    /* }                                       */
#define C_DATA2    0x00000200    /* } when OR'ed, we have total data size   */
#define C_DATA4    0x00000400    /* }                                       */
#define C_BAD      0x00000800    /* "bad", i.e. rarely used instruction     */
#define C_REL      0x00001000    /* it is jxx/call/...                      */
#define C_STOP     0x00002000    /* it is ret/jmp/...                       */
#define C_OPSZ8    0x00004000    /* operand size is 8 bits, otherwise 16/32 */
#define C_SRC_FL   0x00008000    /* put XSET_FL to src_set                  */
#define C_DST_FL   0x00010000    /* put XSET_FL to dst_set                  */
#define C_MOD_FL   (C_SRC_FL+C_DST_FL)
#define C_SRC_REG  0x00020000    /* src_set |= f(REG)                       */
#define C_DST_REG  0x00080000    /* dst_set |= f(REG)                       */
#define C_MOD_REG  (C_SRC_REG+C_DST_REG)
#define C_SRC_RM   0x00040000    /* src_set |= f(R/M)  can be used w/o modrm*/
#define C_DST_RM   0x00100000    /* dst_set |= f(R/M)  can be used w/o modrm*/
#define C_MOD_RM   (C_SRC_RM+C_DST_RM)
#define C_SRC_ACC  0x00200000    /* src_set |= XSET_AL || AX || EAX         */
#define C_DST_ACC  0x00400000    /* dst_set |= XSET_AL || AX || EAX         */
#define C_MOD_ACC  (C_SRC_ACC+C_DST_ACC)
#define C_SRC_R0   0x00800000    /* src_set |= f(opcode & 0x07)             */
#define C_DST_R0   0x01000000    /* dst_set |= f(opcode & 0x07)             */
#define C_MOD_R0   (C_SRC_R0+C_DST_R0)
#define C_PUSH     0x02000000    /* dst_set |= XSET_ESP | XSET_MEM          */
#define C_POP      0x04000000    /* dst_set |= XSET_ESP, src_set |= XSET_MEM*/
#define C_x_shift  27
#define C_x_00001  0x08000000
#define C_x_00010  0x10000000
#define C_x_00100  0x20000000
#define C_x_01000  0x40000000
#define C_x_10000  0x80000000
#define C_x_mask   0xF8000000
#define C_ERROR    0xFFFFFFFF    /* invalid instruction                     */

#define XDE_CMD(fl)  ((fl) & C_x_mask)      /* extract CMD from flags       */

#define C_CMD_other  ( 0 << C_x_shift)      /* 0=other, used if undefined   */
#define C_CMD_CALL   ( 1 << C_x_shift)
#define C_CMD_xxx    ( 2 << C_x_shift)
#define C_CMD_last   (31 << C_x_shift)

/* "object set", stored into src_set && dst_set */

#define XSET_AL    0x00000001
#define XSET_AH    0x00000002
#define XSET_AX    0x00000003
#define XSET_EAX   0x0000000F
#define XSET_CL    0x00000010
#define XSET_CH    0x00000020
#define XSET_CX    0x00000030
#define XSET_ECX   0x000000F0
#define XSET_DL    0x00000100
#define XSET_DH    0x00000200
#define XSET_DX    0x00000300
#define XSET_EDX   0x00000F00
#define XSET_BL    0x00001000
#define XSET_BH    0x00002000
#define XSET_BX    0x00003000
#define XSET_EBX   0x0000F000
#define XSET_SP    0x00010000
#define XSET_ESP   0x00030000
#define XSET_BP    0x00100000
#define XSET_EBP   0x00300000
#define XSET_SI    0x01000000
#define XSET_ESI   0x03000000
#define XSET_DI    0x10000000
#define XSET_EDI   0x30000000
#define XSET_ALL16 0x11113333
#define XSET_ALL32 0x3333FFFF
#define XSET_FL    0x00040000   /* flags                                    */
#define XSET_MEM   0x00080000   /* memory (any address)                     */
#define XSET_OTHER 0x00400000   /* other registers (seg,fpu,cr*,xmm,...)    */
#define XSET_DEV   0x00800000   /* io-ports                                 */
#define XSET_rsrv1 0x04000000
#define XSET_rsrv2 0x08000000
#define XSET_rsrv3 0x40000000
#define XSET_rsrv4 0x80000000
#define XSET_UNDEF 0xFFFFFFFF   /* all values become undefined              */

#pragma pack(push)
#pragma pack(1)

/* instruction is splitted into this structure by xde_disasm()              */
/* then, instruction can be merged from this structure by xde_asm()         */

struct xde_instr
{
  unsigned char  defaddr;        /* 2 or 4, depends on 0x67 prefix          */
  unsigned char  defdata;        /* 2 or 4, depends on 0x66 prefix          */
  unsigned long  len;            /* total instruction length                */
  unsigned long  flag;           /* set of C_xxx flags                      */
  unsigned long  addrsize;       /* size of address (or 0)                  */
  unsigned long  datasize;       /* size of data (or 0)                     */
  unsigned char  p_lock;         /* 0 or F0                                 */
  unsigned char  p_66;           /* 0 or 66                                 */
  unsigned char  p_67;           /* 0 or 67                                 */
  unsigned char  p_rep;          /* 0 or F2/F3                              */
  unsigned char  p_seg;          /* 0 or 26/2E/36/3E/64/65                  */
  unsigned char  opcode;         /* opcode byte (if 0x0F, opcode2 is set)   */
  unsigned char  opcode2;        /* if opcode==0x0F, contains 2nd opcode    */
  unsigned char  modrm;          /* modr/m byte (if C_MODRM)                */
  unsigned char  sib;            /* sib byte (if C_SIB)                     */
//
// example: add eax, ebx
//
// description        READ   WRITE  formula
//
// source regs        +      ?      src_set                      {eax|ebx}
// destination regs   ?      +      dst_set                      {eax|flags}
// modified regs      +      +      dst_set & src_set            {eax}
// read-only regs     +      -      src_set & ~dst_set           {ebx}
// write-only regs    -      +      dst_set & ~src_set           {flags}
//
  unsigned long  src_set;        /* SRC object set (instr. will READ 'em)   */
  unsigned long  dst_set;        /* DST object set (instr. will WRITE 'em)  */
//
  union
  {
  unsigned char  addr_b[8];      /* address bytes, size = addrsize          */
  unsigned short addr_w[4];
  unsigned long  addr_d[2];
  signed char    addr_c[8];
  signed short   addr_s[4];
  signed long    addr_l[2];
  };
  union
  {
  unsigned char  data_b[8];      /* data (imm) bytes, size = datasize       */
  unsigned short data_w[4];
  unsigned long  data_d[2];
  signed char    data_c[8];
  signed short   data_s[4];
  signed long    data_l[2];
  };
}; /* struct xde_instr */

#pragma pack(pop)

int __cdecl xde_disasm(/* IN */ unsigned char *opcode,
                       /* OUT */ struct xde_instr *diza);

int __cdecl xde_asm(/* OUT */ unsigned char* opcode,
                    /* IN */ struct xde_instr* diza);

#endif /* __XDE_H__ */

/* EOF */


3.xdetbl.c文件

/* XDE v1.02 eXtended length disassembler engine, based on LDE/ADE engines */

/* NOTE: opcodes marked with C_SPECIAL(==0) are also analyzed in the XDE.C */

unsigned long xde_table[ TBL_max ] =
{
          // add modrm
/* 00 */  C_MODRM+C_DST_FL+C_SRC_REG+C_MOD_RM+C_OPSZ8,
/* 01 */  C_MODRM+C_DST_FL+C_SRC_REG+C_MOD_RM,
/* 02 */  C_MODRM+C_DST_FL+C_MOD_REG+C_SRC_RM+C_OPSZ8,
/* 03 */  C_MODRM+C_DST_FL+C_MOD_REG+C_SRC_RM,
          // add al, c8
/* 04 */  C_DATA1+C_DST_FL+C_MOD_ACC+C_OPSZ8,
          // add ax/eax, c16/32
/* 05 */  C_DATA66+C_DST_FL+C_MOD_ACC,
          // push es
/* 06 */  C_BAD+C_PUSH+C_SPECIAL,
          // pop es
/* 07 */  C_BAD+C_POP+C_SPECIAL,
          // or modrm
/* 08 */  C_MODRM+C_DST_FL+C_SRC_REG+C_MOD_RM+C_OPSZ8,
/* 09 */  C_MODRM+C_DST_FL+C_SRC_REG+C_MOD_RM,
/* 0A */  C_MODRM+C_DST_FL+C_MOD_REG+C_SRC_RM+C_OPSZ8,
/* 0B */  C_MODRM+C_DST_FL+C_MOD_REG+C_SRC_RM,
          // or al, c8
/* 0C */  C_DATA1+C_DST_FL+C_MOD_ACC+C_OPSZ8,
          // or ax/eax, c16/32
/* 0D */  C_DATA66+C_DST_FL+C_MOD_ACC,
          // push cs
/* 0E */  C_BAD+C_PUSH+C_SPECIAL,
          // 0F-prefix
/* 0F */  C_SPECIAL,
          // adc modrm
/* 10 */  C_MODRM+C_BAD+C_MOD_FL+C_SRC_REG+C_MOD_RM+C_OPSZ8,
/* 11 */  C_MODRM+      C_MOD_FL+C_SRC_REG+C_MOD_RM,
/* 12 */  C_MODRM+C_BAD+C_MOD_FL+C_MOD_REG+C_SRC_RM+C_OPSZ8,
/* 13 */  C_MODRM+      C_MOD_FL+C_MOD_REG+C_SRC_RM,
          // adc al, c8
/* 14 */  C_DATA1+C_BAD+C_MOD_FL+C_MOD_ACC+C_OPSZ8,
          // adc ax/eax, c16/32
/* 15 */  C_DATA66+C_BAD+C_MOD_FL+C_MOD_ACC,
          // push ss
/* 16 */  C_BAD+C_PUSH+C_SPECIAL,
          // pop ss
/* 17 */  C_BAD+C_POP+C_SPECIAL,
          // sbb modrm
/* 18 */  C_MODRM+C_BAD+C_MOD_FL+C_SRC_REG+C_MOD_RM+C_OPSZ8,
/* 19 */  C_MODRM+      C_MOD_FL+C_SRC_REG+C_MOD_RM,
/* 1A */  C_MODRM+C_BAD+C_MOD_FL+C_MOD_REG+C_SRC_RM+C_OPSZ8,
/* 1B */  C_MODRM+      C_MOD_FL+C_MOD_REG+C_SRC_RM,
          // sbb al, c8
/* 1C */  C_DATA1+C_BAD+C_MOD_FL+C_MOD_ACC+C_OPSZ8,
          // sbb ax/eax, c16/32
/* 1D */  C_DATA66+C_BAD+C_MOD_FL+C_MOD_ACC,
          // push ds
/* 1E */  C_BAD+C_PUSH+C_SPECIAL,
          // pop ds
/* 1F */  C_BAD+C_POP+C_SPECIAL,
          // and modrm
/* 20 */  C_MODRM+C_DST_FL+C_SRC_REG+C_MOD_RM+C_OPSZ8,
/* 21 */  C_MODRM+C_DST_FL+C_SRC_REG+C_MOD_RM,
/* 22 */  C_MODRM+C_DST_FL+C_MOD_REG+C_SRC_RM+C_OPSZ8,
/* 23 */  C_MODRM+C_DST_FL+C_MOD_REG+C_SRC_RM,
          // and al, c8
/* 24 */  C_DATA1+C_DST_FL+C_MOD_ACC+C_OPSZ8,
          // and ax/eax, c16/32
/* 25 */  C_DATA66+C_DST_FL+C_MOD_ACC,
          // es:
/* 26 */  C_BAD+C_SPECIAL,
          // daa
/* 27 */  C_BAD+C_MOD_FL+C_OPSZ8+C_MOD_ACC,
          // sub modrm
/* 28 */  C_MODRM+C_DST_FL+C_SRC_REG+C_MOD_RM+C_OPSZ8,
/* 29 */  C_MODRM+C_DST_FL+C_SRC_REG+C_MOD_RM,
/* 2A */  C_MODRM+C_DST_FL+C_MOD_REG+C_SRC_RM+C_OPSZ8,
/* 2B */  C_MODRM+C_DST_FL+C_MOD_REG+C_SRC_RM,
          // sub al, c8
/* 2C */  C_DATA1+C_DST_FL+C_MOD_ACC+C_OPSZ8,
          // sub ax/eax, c16/32
/* 2D */  C_DATA66+C_DST_FL+C_MOD_ACC,
          // cs:
/* 2E */  C_BAD+C_SPECIAL,
          // das
/* 2F */  C_BAD+C_MOD_FL+C_OPSZ8+C_MOD_ACC,
          // xor modrm
/* 30 */  C_MODRM+C_DST_FL+C_SRC_REG+C_MOD_RM+C_OPSZ8,
/* 31 */  C_MODRM+C_DST_FL+C_SRC_REG+C_MOD_RM,
/* 32 */  C_MODRM+C_DST_FL+C_MOD_REG+C_SRC_RM+C_OPSZ8,
/* 33 */  C_MODRM+C_DST_FL+C_MOD_REG+C_SRC_RM,
          // xor al, c8
/* 34 */  C_DATA1+C_DST_FL+C_MOD_ACC+C_OPSZ8,
          // xor ax/eax, c16/32
/* 35 */  C_DATA66+C_DST_FL+C_MOD_ACC,
          // ss:
/* 36 */  C_BAD+C_SPECIAL,
          // aaa
/* 37 */  C_BAD+C_MOD_FL+C_OPSZ8+C_MOD_ACC+C_SPECIAL,
          // cmp modrm
/* 38 */  C_MODRM+C_DST_FL+C_SRC_REG+C_SRC_RM+C_OPSZ8,
/* 39 */  C_MODRM+C_DST_FL+C_SRC_REG+C_SRC_RM,
/* 3A */  C_MODRM+C_DST_FL+C_SRC_REG+C_SRC_RM+C_OPSZ8,
/* 3B */  C_MODRM+C_DST_FL+C_SRC_REG+C_SRC_RM,
          // cmp al, c8
/* 3C */  C_DATA1+C_DST_FL+C_SRC_ACC+C_OPSZ8,
          // cmp ax, c16/32
/* 3D */  C_DATA66+C_DST_FL+C_SRC_ACC,
          // ds:
/* 3E */  C_BAD+C_SPECIAL,
          // aas
/* 3F */  C_BAD+C_MOD_FL+C_OPSZ8+C_MOD_ACC+C_SPECIAL,
          // inc ax/eax
/* 40 */  0+C_MOD_FL+C_MOD_R0,
/* 41 */  0+C_MOD_FL+C_MOD_R0,
/* 42 */  0+C_MOD_FL+C_MOD_R0,
/* 43 */  0+C_MOD_FL+C_MOD_R0,
/* 44 */  C_BAD+C_MOD_FL+C_MOD_R0,
/* 45 */  0+C_MOD_FL+C_MOD_R0,
/* 46 */  0+C_MOD_FL+C_MOD_R0,
          // inc di/edi
/* 47 */  0+C_MOD_FL+C_MOD_R0,
          // dec ax/eax
/* 48 */  0+C_MOD_FL+C_MOD_R0,
/* 49 */  0+C_MOD_FL+C_MOD_R0,
/* 4A */  0+C_MOD_FL+C_MOD_R0,
/* 4B */  0+C_MOD_FL+C_MOD_R0,
/* 4C */  C_BAD+C_MOD_FL+C_MOD_R0,
/* 4D */  0+C_MOD_FL+C_MOD_R0,
/* 4E */  0+C_MOD_FL+C_MOD_R0,
          // dec di/edi
/* 4F */  0+C_MOD_FL+C_MOD_R0,
          // push ax/eax
/* 50 */  0+C_PUSH+C_SRC_R0,
/* 51 */  0+C_PUSH+C_SRC_R0,
/* 52 */  0+C_PUSH+C_SRC_R0,
/* 53 */  0+C_PUSH+C_SRC_R0,
/* 54 */  0+C_PUSH+C_SRC_R0,
/* 55 */  0+C_PUSH+C_SRC_R0,
/* 56 */  0+C_PUSH+C_SRC_R0,
          // push di/edi
/* 57 */  0+C_PUSH+C_SRC_R0,
          // pop ax/eax
/* 58 */  0+C_POP+C_DST_R0,
/* 59 */  0+C_POP+C_DST_R0,
/* 5A */  0+C_POP+C_DST_R0,
/* 5B */  0+C_POP+C_DST_R0,
/* 5C */  C_BAD+C_POP+C_DST_R0,
/* 5D */  0+C_POP+C_DST_R0,
/* 5E */  0+C_POP+C_DST_R0,
          // pop di/edi
/* 5F */  0+C_POP+C_DST_R0,
          // pusha/pushad
/* 60 */  C_BAD+C_PUSH+C_SPECIAL,
          // popa/popad
/* 61 */  C_BAD+C_POP+C_SPECIAL,
          // bound
/* 62 */  C_MODRM+C_BAD+C_UNDEF,
          // arpl
/* 63 */  C_MODRM+C_BAD+C_UNDEF,
          // fs:
/* 64 */  C_SPECIAL,
          // gs:
/* 65 */  C_BAD+C_SPECIAL,
          // 66-prefix
/* 66 */  C_SPECIAL,
          // 67-prefix
/* 67 */  C_SPECIAL,
          // push c16/32
/* 68 */  C_DATA66+C_PUSH,
          // imul r,r,c16/32
/* 69 */  C_MODRM+C_DATA66+C_DST_FL+C_MOD_REG+C_SRC_RM,
          // push c8
/* 6A */  C_DATA1+C_PUSH,
          // imul r,r,c8
/* 6B */  C_MODRM+C_DATA1+C_DST_FL+C_MOD_REG+C_SRC_RM,
          // insb
/* 6C */  C_BAD+C_SRC_FL+C_DST_RM+C_SPECIAL,
          // insd
/* 6D */  C_BAD+C_SRC_FL+C_DST_RM+C_SPECIAL,
          // outsb
/* 6E */  C_BAD+C_SRC_FL+C_SRC_RM+C_SPECIAL,
          // outsd
/* 6F */  C_BAD+C_SRC_FL+C_SRC_RM+C_SPECIAL,
          // jxx short
/* 70 */  C_DATA1+C_REL+C_BAD+C_UNDEF,
/* 71 */  C_DATA1+C_REL+C_BAD+C_UNDEF,
/* 72 */  C_DATA1+C_REL+C_UNDEF,
/* 73 */  C_DATA1+C_REL+C_UNDEF,
/* 74 */  C_DATA1+C_REL+C_UNDEF,
/* 75 */  C_DATA1+C_REL+C_UNDEF,
/* 76 */  C_DATA1+C_REL+C_UNDEF,
/* 77 */  C_DATA1+C_REL+C_UNDEF,
/* 78 */  C_DATA1+C_REL+C_UNDEF,
/* 79 */  C_DATA1+C_REL+C_UNDEF,
/* 7A */  C_DATA1+C_REL+C_BAD+C_UNDEF,
/* 7B */  C_DATA1+C_REL+C_BAD+C_UNDEF,
/* 7C */  C_DATA1+C_REL+C_UNDEF,
/* 7D */  C_DATA1+C_REL+C_UNDEF,
/* 7E */  C_DATA1+C_REL+C_UNDEF,
/* 7F */  C_DATA1+C_REL+C_UNDEF,
          // ttt: 0=add 1=or 2=adc 3=sbb 4=and 5=sub 6=xor 7=cmp
          // ttt [r/m]:8, imm8
/* 80 */  C_MODRM+C_DATA1+C_SPECIAL,
          // ttt [r/m]:16/32, imm16/32
/* 81 */  C_MODRM+C_DATA66+C_SPECIAL,
          // ttt [r/m]:8, imm8
/* 82 */  C_MODRM+C_DATA1+C_BAD+C_SPECIAL,
          // ttt [r/m]:16/32, imm8
/* 83 */  C_MODRM+C_DATA1+C_SPECIAL,
          // test [r/m]:8, r8
/* 84 */  C_MODRM+C_DST_FL+C_SRC_REG+C_SRC_RM+C_OPSZ8,
          // test [r/m]:16/32, r16/32
/* 85 */  C_MODRM+C_DST_FL+C_SRC_REG+C_SRC_RM,
          // xchg [r/m]:8, r8
/* 86 */  C_MODRM+C_MOD_REG+C_MOD_RM+C_OPSZ8,
          // xchg [r/m]:16/32, r16/32
/* 87 */  C_MODRM+C_MOD_REG+C_MOD_RM,
          // mov [r/m]:8, r8
/* 88 */  C_MODRM+C_DST_RM+C_SRC_REG+C_OPSZ8,
          // mov [r/m]:16/32, r16/32
/* 89 */  C_MODRM+C_DST_RM+C_SRC_REG,
          // mov r8, [r/m]:8
/* 8A */  C_MODRM+C_DST_REG+C_SRC_RM+C_OPSZ8,
          // mov r16/32, [r/m]:16/32
/* 8B */  C_MODRM+C_DST_REG+C_SRC_RM,
          // mov [r/m]:16, sreg
/* 8C */  C_MODRM+C_BAD+C_DST_RM+C_SPECIAL,
          // lea r16/32, [r/m]
/* 8D */  C_MODRM+C_DST_REG+C_SRC_RM+C_SPECIAL,
          // mov sreg, [r/m]:16
/* 8E */  C_MODRM+C_BAD+C_DST_RM+C_SPECIAL,
          // pop [r/m]:16/32
/* 8F */  C_MODRM+C_POP+C_DST_RM+C_SPECIAL,
          // nop
/* 90 */  0,
          // xchg ecx, eax
/* 91 */  0+C_MOD_R0+C_MOD_ACC,
/* 92 */  0+C_MOD_R0+C_MOD_ACC,
/* 93 */  C_BAD+C_MOD_R0+C_MOD_ACC,
/* 94 */  C_BAD+C_MOD_R0+C_MOD_ACC,
/* 95 */  C_BAD+C_MOD_R0+C_MOD_ACC,
/* 96 */  C_BAD+C_MOD_R0+C_MOD_ACC,
          // xchg edi, eax
/* 97 */  C_BAD+C_MOD_R0+C_MOD_ACC,
          // cwde
/* 98 */  C_BAD+C_SPECIAL,
          // cdq
/* 99 */  0+C_SPECIAL,
          // call far
/* 9A */  C_DATA66+C_DATA2+C_BAD+C_UNDEF+C_CMD_CALL,
          // fwait
/* 9B */  0+C_UNDEF,                                      /* fpu */
          // pushf
/* 9C */  C_BAD+C_PUSH+C_SRC_FL,
          // popf
/* 9D */  C_BAD+C_POP+C_DST_FL,
          // sahf
/* 9E */  C_BAD+C_DST_FL+C_SPECIAL,
          // lahf
/* 9F */  C_BAD+C_SRC_FL+C_SPECIAL,
          // mov al, [imm8]
/* A0 */  C_ADDR67+C_DST_ACC+C_SRC_RM+C_OPSZ8,
          // mov ax/eax, [imm16/32]
/* A1 */  C_ADDR67+C_DST_ACC+C_SRC_RM,
          // mov [imm8], al
/* A2 */  C_ADDR67+C_SRC_ACC+C_DST_RM+C_OPSZ8,
          // mov [imm16/32], ax/eax
/* A3 */  C_ADDR67+C_SRC_ACC+C_DST_RM,
          // movsb
/* A4 */  0+C_SRC_FL+C_MOD_RM+C_SPECIAL,
          // movsd
/* A5 */  0+C_SRC_FL+C_MOD_RM+C_SPECIAL,
          // cmpsb
/* A6 */  0+C_MOD_FL+C_SRC_RM+C_SPECIAL,
          // cmpsd
/* A7 */  0+C_MOD_FL+C_SRC_RM+C_SPECIAL,
          // test al, c8
/* A8 */  C_DATA1+C_DST_FL+C_SRC_ACC+C_OPSZ8,
          // test ax/eax, c16/32
/* A9 */  C_DATA66+C_DST_FL+C_SRC_ACC,
          // stosb
/* AA */  0+C_SRC_FL+C_DST_RM+C_OPSZ8+C_SRC_ACC+C_SPECIAL,
          // stosd
/* AB */  0+C_SRC_FL+C_DST_RM+C_SRC_ACC+C_SPECIAL,
          // lodsb
/* AC */  0+C_SRC_FL+C_SRC_RM+C_OPSZ8+C_DST_ACC+C_SPECIAL,
          // lodsd
/* AD */  C_BAD+C_SRC_FL+C_SRC_RM+C_DST_ACC+C_SPECIAL,
          // scasb
/* AE */  0+C_SRC_FL+C_DST_FL+C_SRC_RM+C_OPSZ8+C_SRC_ACC+C_SPECIAL,
          // scasd
/* AF */  C_BAD+C_SRC_FL+C_DST_FL+C_SRC_RM+C_SRC_ACC+C_SPECIAL,
          // mov al, c8
/* B0 */  C_DATA1+C_DST_R0+C_OPSZ8,
/* B1 */  C_DATA1+C_DST_R0+C_OPSZ8,
/* B2 */  C_DATA1+C_DST_R0+C_OPSZ8,
/* B3 */  C_DATA1+C_DST_R0+C_OPSZ8,
/* B4 */  C_DATA1+C_DST_R0+C_OPSZ8,
/* B5 */  C_DATA1+C_DST_R0+C_OPSZ8,
/* B6 */  C_DATA1+C_BAD+C_DST_R0+C_OPSZ8,
          // mov bh, c8
/* B7 */  C_DATA1+C_BAD+C_DST_R0+C_OPSZ8,
          // mov ax/eax, c16/32
/* B8 */  C_DATA66+C_DST_R0,
/* B9 */  C_DATA66+C_DST_R0,
/* BA */  C_DATA66+C_DST_R0,
/* BB */  C_DATA66+C_DST_R0,
/* BC */  C_DATA66+C_BAD+C_DST_R0,
/* BD */  C_DATA66+C_DST_R0,
/* BE */  C_DATA66+C_DST_R0,
          // mov di/edi, c16/32
/* BF */  C_DATA66+C_DST_R0,
          // ttt: 0=rol 1=ror 2=rcl 3=rcr 4=shl 5=shr 6=sal 7=sar
          // shift-ttt [r/m]:8, imm8
/* C0 */  C_MODRM+C_DATA1+C_DST_FL+C_DST_RM+C_OPSZ8+C_SPECIAL,
          // shift-ttt [r/m]:16/32, imm8
/* C1 */  C_MODRM+C_DATA1+C_DST_FL+C_DST_RM+C_SPECIAL,
          // retn c16
/* C2 */  C_DATA2+C_STOP+C_UNDEF,
          // retn
/* C3 */  C_STOP+C_UNDEF,
          // les
/* C4 */  C_MODRM+C_BAD+C_DST_REG+C_SRC_RM+C_SPECIAL,
          // lds
/* C5 */  C_MODRM+C_BAD+C_DST_REG+C_SRC_RM+C_SPECIAL,
          // ttt=000, other illegal
          // mov [r/m], imm8
/* C6 */  C_MODRM+C_DST_RM+C_DATA1+C_SPECIAL,
          // mov [r/m], imm16/32
/* C7 */  C_MODRM+C_DST_RM+C_DATA66+C_SPECIAL,
          // enter
/* C8 */  C_DATA2+C_DATA1+C_MOD_RM+C_SPECIAL,
          // leave
/* C9 */  0+C_SRC_RM+C_SPECIAL,
          // retf c16
/* CA */  C_DATA2+C_STOP+C_BAD+C_UNDEF,
          // retf
/* CB */  C_STOP+C_BAD+C_UNDEF,
          // int3
/* CC */  C_BAD,
          // int n
/* CD */  C_DATA1+C_UNDEF,
          // into
/* CE */  C_BAD+C_UNDEF,
          // iret
/* CF */  C_STOP+C_BAD+C_UNDEF,
          // ttt: 0=rol 1=ror 2=rcl 3=rcr 4=shl 5=shr 6=sal 7=sar
          // shift-ttt [r/m]:8, 1
/* D0 */  C_MODRM+C_DST_FL+C_MOD_RM+C_OPSZ8+C_SPECIAL,
          // shift-ttt [r/m]:16/32, 1
/* D1 */  C_MODRM+C_DST_FL+C_MOD_RM+C_SPECIAL,
          // shift-ttt [r/m]:8, cl
/* D2 */  C_MODRM+C_DST_FL+C_MOD_RM+C_OPSZ8+C_SPECIAL,
          // shift-ttt [r/m]:16/32, cl
/* D3 */  C_MODRM+C_DST_FL+C_MOD_RM+C_SPECIAL,
          // aam nn
/* D4 */  C_DATA1+C_BAD+C_DST_FL+C_SPECIAL,
          // aad nn
/* D5 */  C_DATA1+C_BAD+C_DST_FL+C_SPECIAL,
          // setalc
/* D6 */  C_BAD+C_SRC_FL+C_OPSZ8+C_DST_ACC,
          // xlat
/* D7 */  C_BAD+C_OPSZ8+C_MOD_ACC+C_SRC_RM+C_SPECIAL,
/* D8 */  C_MODRM+C_UNDEF,                   /* fpu */
/* D9 */  C_MODRM+C_UNDEF,                   /* fpu */
/* DA */  C_MODRM+C_UNDEF,                   /* fpu */
/* DB */  C_MODRM+C_UNDEF,                   /* fpu */
/* DC */  C_MODRM+C_UNDEF,                   /* fpu */
/* DD */  C_MODRM+C_UNDEF,                   /* fpu */
/* DE */  C_MODRM+C_UNDEF,                   /* fpu */
/* DF */  C_MODRM+C_UNDEF,                   /* fpu */
          // loopne
/* E0 */  C_DATA1+C_REL+C_BAD+C_UNDEF,
          // loope
/* E1 */  C_DATA1+C_REL+C_BAD+C_UNDEF,
          // loop
/* E2 */  C_DATA1+C_REL+C_UNDEF,
          // jecxz
/* E3 */  C_DATA1+C_REL+C_UNDEF,
          // in al, nn
/* E4 */  C_DATA1+C_BAD+C_OPSZ8+C_DST_ACC+C_SPECIAL,
          // in ax/eax, nn
/* E5 */  C_DATA1+C_BAD+C_DST_ACC+C_SPECIAL,
          // out nn, al
/* E6 */  C_DATA1+C_BAD+C_OPSZ8+C_SRC_ACC+C_SPECIAL,
          // out nn, ax/eax
/* E7 */  C_DATA1+C_BAD+C_SRC_ACC+C_SPECIAL,
          // call near
/* E8 */  C_DATA66+C_REL+C_UNDEF+C_CMD_CALL,
          // jmp near
/* E9 */  C_DATA66+C_REL+C_STOP+C_UNDEF,
          // jmp far
/* EA */  C_DATA66+C_DATA2+C_BAD+C_STOP+C_UNDEF,
          // jmp short
/* EB */  C_DATA1+C_REL+C_STOP+C_UNDEF,
          // in al, dx
/* EC */  C_BAD+C_OPSZ8+C_DST_ACC+C_SPECIAL,
          // in ax/eax, dx
/* ED */  C_BAD+C_DST_ACC+C_SPECIAL,
          // out dx, al
/* EE */  C_BAD+C_OPSZ8+C_SRC_ACC+C_SPECIAL,
          // out dx, ax/eax
/* EF */  C_BAD+C_SRC_ACC+C_SPECIAL,
          // lock prefix
/* F0 */  C_BAD+C_SPECIAL,
          //
/* F1 */  C_BAD+C_UNDEF,
          // repne
/* F2 */  C_SPECIAL,
          // repe
/* F3 */  C_SPECIAL,
          // hlt
/* F4 */  C_BAD,
          // cmc
/* F5 */  C_BAD+C_MOD_FL,
          // ttt: 0=test 1=??? 2=not 3=neg 4=mul 5=imul 6=div 7=idiv
/* F6 */  C_MODRM+C_SPECIAL,
/* F7 */  C_MODRM+C_SPECIAL,
          // clc
/* F8 */  0+C_DST_FL,
          // stc
/* F9 */  0+C_DST_FL,
          // cli
/* FA */  C_BAD+C_DST_FL,
          // sti
/* FB */  C_BAD+C_DST_FL,
          // cld
/* FC */  0+C_DST_FL,
          // std
/* FD */  0+C_DST_FL,
          // ttt: 0=inc 1=dec 2=??? 3=??? 4=??? 5=??? 6=??? 7=???
/* FE */  C_MODRM+C_SPECIAL,
          // ttt: 0=inc 1=dec 2=callnear 3=callfar 4=jmpnear 5=jmpfar 6=push 7=???
/* FF */  C_MODRM+C_SPECIAL,

/* 2nd half of the table, 0F-prefixed opcodes */

             // /0=SLDT /1=STR /2=LLDT /3=LTR /4=VERR /5=VERW /6=??? /7=???
/* 0F 00 */  C_MODRM+C_UNDEF,
             // /0=SGDT /1=SIDT /2=LGDT /3=LIDT /4=SMSW /5=??? /6=LMSW /7=INVPLG
/* 0F 01 */  C_MODRM+C_UNDEF,
             // LAR r16/32, [r/m]:16/32
/* 0F 02 */  C_MODRM+C_UNDEF,
             // LSL r16/32, [r/m]:16/32
/* 0F 03 */  C_MODRM+C_UNDEF,
/* 0F 04 */  C_ERROR,
/* 0F 05 */  C_ERROR,
             // CLTS
/* 0F 06 */  C_UNDEF,
/* 0F 07 */  C_ERROR,
             // INVD
/* 0F 08 */  C_UNDEF,
             // WBINVD
/* 0F 09 */  C_UNDEF,
             // ???
/* 0F 0A */  C_UNDEF,
             // UD2
/* 0F 0B */  C_UNDEF,
/* 0F 0C */  C_ERROR,
/* 0F 0D */  C_ERROR,
/* 0F 0E */  C_ERROR,
/* 0F 0F */  C_ERROR,
             //
/* 0F 10 */  C_ERROR,
/* 0F 11 */  C_ERROR,
/* 0F 12 */  C_ERROR,
/* 0F 13 */  C_ERROR,
/* 0F 14 */  C_ERROR,
/* 0F 15 */  C_ERROR,
/* 0F 16 */  C_ERROR,
/* 0F 17 */  C_ERROR,
/* 0F 18 */  C_ERROR,
/* 0F 19 */  C_ERROR,
/* 0F 1A */  C_ERROR,
/* 0F 1B */  C_ERROR,
/* 0F 1C */  C_ERROR,
/* 0F 1D */  C_ERROR,
/* 0F 1E */  C_ERROR,
/* 0F 1F */  C_ERROR,
/* 0F 20 */  C_ERROR,
/* 0F 21 */  C_ERROR,
/* 0F 22 */  C_ERROR,
/* 0F 23 */  C_ERROR,
/* 0F 24 */  C_ERROR,
/* 0F 25 */  C_ERROR,
/* 0F 26 */  C_ERROR,
/* 0F 27 */  C_ERROR,
/* 0F 28 */  C_ERROR,
/* 0F 29 */  C_ERROR,
/* 0F 2A */  C_ERROR,
/* 0F 2B */  C_ERROR,
/* 0F 2C */  C_ERROR,
/* 0F 2D */  C_ERROR,
/* 0F 2E */  C_ERROR,
/* 0F 2F */  C_ERROR,
             // WRMSR
/* 0F 30 */  C_UNDEF,
/* 0F 31 */  C_ERROR,
/* 0F 32 */  C_ERROR,
/* 0F 33 */  C_ERROR,
/* 0F 34 */  C_ERROR,
/* 0F 35 */  C_ERROR,
/* 0F 36 */  C_ERROR,
/* 0F 37 */  C_ERROR,
/* 0F 38 */  C_ERROR,
/* 0F 39 */  C_ERROR,
/* 0F 3A */  C_ERROR,
/* 0F 3B */  C_ERROR,
/* 0F 3C */  C_ERROR,
/* 0F 3D */  C_ERROR,
/* 0F 3E */  C_ERROR,
/* 0F 3F */  C_ERROR,
/* 0F 40 */  C_ERROR,
/* 0F 41 */  C_ERROR,
/* 0F 42 */  C_ERROR,
/* 0F 43 */  C_ERROR,
/* 0F 44 */  C_ERROR,
/* 0F 45 */  C_ERROR,
/* 0F 46 */  C_ERROR,
/* 0F 47 */  C_ERROR,
/* 0F 48 */  C_ERROR,
/* 0F 49 */  C_ERROR,
/* 0F 4A */  C_ERROR,
/* 0F 4B */  C_ERROR,
/* 0F 4C */  C_ERROR,
/* 0F 4D */  C_ERROR,
/* 0F 4E */  C_ERROR,
/* 0F 4F */  C_ERROR,
/* 0F 50 */  C_ERROR,
/* 0F 51 */  C_ERROR,
/* 0F 52 */  C_ERROR,
/* 0F 53 */  C_ERROR,
/* 0F 54 */  C_ERROR,
/* 0F 55 */  C_ERROR,
/* 0F 56 */  C_ERROR,
/* 0F 57 */  C_ERROR,
/* 0F 58 */  C_ERROR,
/* 0F 59 */  C_ERROR,
/* 0F 5A */  C_ERROR,
/* 0F 5B */  C_ERROR,
/* 0F 5C */  C_ERROR,
/* 0F 5D */  C_ERROR,
/* 0F 5E */  C_ERROR,
/* 0F 5F */  C_ERROR,
/* 0F 60 */  C_ERROR,
/* 0F 61 */  C_ERROR,
/* 0F 62 */  C_ERROR,
/* 0F 63 */  C_ERROR,
/* 0F 64 */  C_ERROR,
/* 0F 65 */  C_ERROR,
/* 0F 66 */  C_ERROR,
/* 0F 67 */  C_ERROR,
/* 0F 68 */  C_ERROR,
/* 0F 69 */  C_ERROR,
/* 0F 6A */  C_ERROR,
/* 0F 6B */  C_ERROR,
/* 0F 6C */  C_ERROR,
/* 0F 6D */  C_ERROR,
/* 0F 6E */  C_ERROR,
/* 0F 6F */  C_ERROR,
/* 0F 70 */  C_ERROR,
/* 0F 71 */  C_ERROR,
/* 0F 72 */  C_ERROR,
/* 0F 73 */  C_ERROR,
/* 0F 74 */  C_ERROR,
/* 0F 75 */  C_ERROR,
/* 0F 76 */  C_ERROR,
/* 0F 77 */  C_ERROR,
/* 0F 78 */  C_ERROR,
/* 0F 79 */  C_ERROR,
/* 0F 7A */  C_ERROR,
/* 0F 7B */  C_ERROR,
/* 0F 7C */  C_ERROR,
/* 0F 7D */  C_ERROR,
/* 0F 7E */  C_ERROR,
/* 0F 7F */  C_ERROR,
             // jxx near
/* 0F 80 */  C_DATA66+C_REL+C_UNDEF,
/* 0F 81 */  C_DATA66+C_REL+C_UNDEF,
/* 0F 82 */  C_DATA66+C_REL+C_UNDEF,
/* 0F 83 */  C_DATA66+C_REL+C_UNDEF,
/* 0F 84 */  C_DATA66+C_REL+C_UNDEF,
/* 0F 85 */  C_DATA66+C_REL+C_UNDEF,
/* 0F 86 */  C_DATA66+C_REL+C_UNDEF,
/* 0F 87 */  C_DATA66+C_REL+C_UNDEF,
/* 0F 88 */  C_DATA66+C_REL+C_UNDEF,
/* 0F 89 */  C_DATA66+C_REL+C_UNDEF,
/* 0F 8A */  C_DATA66+C_REL+C_UNDEF,
/* 0F 8B */  C_DATA66+C_REL+C_UNDEF,
/* 0F 8C */  C_DATA66+C_REL+C_UNDEF,
/* 0F 8D */  C_DATA66+C_REL+C_UNDEF,
/* 0F 8E */  C_DATA66+C_REL+C_UNDEF,
/* 0F 8F */  C_DATA66+C_REL+C_UNDEF,
             /* setxx */
/* 0F 90 */  C_MODRM+C_UNDEF,
/* 0F 91 */  C_MODRM+C_UNDEF,
/* 0F 92 */  C_MODRM+C_UNDEF,
/* 0F 93 */  C_MODRM+C_UNDEF,
/* 0F 94 */  C_MODRM+C_UNDEF,
/* 0F 95 */  C_MODRM+C_UNDEF,
/* 0F 96 */  C_MODRM+C_UNDEF,
/* 0F 97 */  C_MODRM+C_UNDEF,
/* 0F 98 */  C_MODRM+C_UNDEF,
/* 0F 99 */  C_MODRM+C_UNDEF,
/* 0F 9A */  C_MODRM+C_UNDEF,
/* 0F 9B */  C_MODRM+C_UNDEF,
/* 0F 9C */  C_MODRM+C_UNDEF,
/* 0F 9D */  C_MODRM+C_UNDEF,
/* 0F 9E */  C_MODRM+C_UNDEF,
/* 0F 9F */  C_MODRM+C_UNDEF,
             // push fs
/* 0F A0 */  C_PUSH+C_SPECIAL,
             // pop fs
/* 0F A1 */  C_POP+C_SPECIAL,
             // cpuid
/* 0F A2 */  C_SPECIAL,
             // bt [r/m]:16/32, r16/32
/* 0F A3 */  C_MODRM+C_DST_FL+C_SRC_REG+C_SRC_RM,
             // shld [r/m]:16/32, r16/32, imm8
/* 0F A4 */  C_MODRM+C_DST_FL+C_DATA1+C_MOD_RM+C_SRC_REG,
             // shld [r/m]:16/32, r16/32, CL
/* 0F A5 */  C_MODRM+C_DST_FL+C_MOD_RM+C_SRC_REG+C_SPECIAL,
/* 0F A6 */  C_ERROR,
/* 0F A7 */  C_ERROR,
             // push gs
/* 0F A8 */  C_PUSH+C_SPECIAL,
             // pop gs
/* 0F A9 */  C_POP+C_SPECIAL,
             // RSM
/* 0F AA */  C_UNDEF,
             // bts [r/m]:16/32, r16/32
/* 0F AB */  C_MODRM+C_DST_FL+C_MOD_RM+C_SRC_REG,
             // shrd [r/m]:16/32, r16/32, imm8
/* 0F AC */  C_MODRM+C_DST_FL+C_DATA1+C_MOD_RM+C_SRC_REG,
             // shrd [r/m]:16/32, r16/32, CL
/* 0F AD */  C_MODRM+C_DST_FL+C_MOD_RM+C_SRC_REG+C_SPECIAL,
/* 0F AE */  C_ERROR,
             // imul r16/32, [r/m]:16/32
/* 0F AF */  C_MODRM+C_DST_FL+C_MOD_REG+C_SRC_RM,
             // cmpxchg [r/m]:8, r8
/* 0F B0 */  C_MODRM+C_DST_FL+C_MOD_RM+C_SRC_REG+C_MOD_ACC+C_OPSZ8,
             // cmpxchg [r/m]:16/32, r16/32
/* 0F B1 */  C_MODRM+C_DST_FL+C_MOD_RM+C_SRC_REG+C_MOD_ACC,
             // lss reg, r/m
/* 0F B2 */  C_MODRM+C_BAD+C_DST_REG+C_SRC_RM+C_SPECIAL,
             // btr [r/m]:16/32, r16/32
/* 0F B3 */  C_MODRM+C_DST_FL+C_MOD_RM+C_SRC_REG,
             // lfs reg, r/m
/* 0F B4 */  C_MODRM+C_BAD+C_DST_REG+C_SRC_RM+C_SPECIAL,
             // lgs reg, r/m
/* 0F B5 */  C_MODRM+C_BAD+C_DST_REG+C_SRC_RM+C_SPECIAL,
             // movzx r16/32, [r/m]:8
/* 0F B6 */  C_MODRM+C_DST_REG+C_SRC_RM,
             // movzx 32, [r/m]:16
/* 0F B7 */  C_MODRM+C_DST_REG+C_SRC_RM,
/* 0F B8 */  C_ERROR,
/* 0F B9 */  C_ERROR,
             // ttt: 1=??? 2=??? 3=??? 4=bt 5=bts 6=btr 7=btc
             // ttt [r/m], imm8
/* 0F BA */  C_MODRM+C_DATA1+C_DST_FL+C_SRC_RM+C_SPECIAL,
             // btc [r/m]:16/32, r16/32
/* 0F BB */  C_MODRM+C_DST_FL+C_MOD_RM+C_SRC_REG,
             // bsf r16/32, [r/m]:16/32
/* 0F BC */  C_MODRM+C_DST_FL+C_DST_REG+C_SRC_RM,
             // bsr r16/32, [r/m]:16/32
/* 0F BD */  C_MODRM+C_DST_FL+C_DST_REG+C_SRC_RM,
             // movsx r16/32, [r/m]:8
/* 0F BE */  C_MODRM+C_DST_REG+C_SRC_RM,
             // movsx r32, [r/m]:16
/* 0F BF */  C_MODRM+C_DST_REG+C_SRC_RM,
             // xadd [r/m]:8, r8
/* 0F C0 */  C_MODRM+C_DST_FL+C_MOD_REG+C_MOD_RM+C_OPSZ8,
             // xadd [r/m]:16/32, r16/32
/* 0F C1 */  C_MODRM+C_DST_FL+C_MOD_REG+C_MOD_RM,
/* 0F C2 */  C_ERROR,
/* 0F C3 */  C_ERROR,
/* 0F C4 */  C_ERROR,
/* 0F C5 */  C_ERROR,
/* 0F C6 */  C_ERROR,
/* 0F C7 */  C_ERROR,
             // BSWAP r32
/* 0F C8 */  C_MOD_R0,
/* 0F C9 */  C_MOD_R0,
/* 0F CA */  C_MOD_R0,
/* 0F CB */  C_MOD_R0,
/* 0F CC */  C_MOD_R0,
/* 0F CD */  C_MOD_R0,
/* 0F CE */  C_MOD_R0,
/* 0F CF */  C_MOD_R0,
/* 0F D0 */  C_ERROR,
/* 0F D1 */  C_ERROR,
/* 0F D2 */  C_ERROR,
/* 0F D3 */  C_ERROR,
/* 0F D4 */  C_ERROR,
/* 0F D5 */  C_ERROR,
/* 0F D6 */  C_ERROR,
/* 0F D7 */  C_ERROR,
/* 0F D8 */  C_ERROR,
/* 0F D9 */  C_ERROR,
/* 0F DA */  C_ERROR,
/* 0F DB */  C_ERROR,
/* 0F DC */  C_ERROR,
/* 0F DD */  C_ERROR,
/* 0F DE */  C_ERROR,
/* 0F DF */  C_ERROR,
/* 0F E0 */  C_ERROR,
/* 0F E1 */  C_ERROR,
/* 0F E2 */  C_ERROR,
/* 0F E3 */  C_ERROR,
/* 0F E4 */  C_ERROR,
/* 0F E5 */  C_ERROR,
/* 0F E6 */  C_ERROR,
/* 0F E7 */  C_ERROR,
/* 0F E8 */  C_ERROR,
/* 0F E9 */  C_ERROR,
/* 0F EA */  C_ERROR,
/* 0F EB */  C_ERROR,
/* 0F EC */  C_ERROR,
/* 0F ED */  C_ERROR,
/* 0F EE */  C_ERROR,
/* 0F EF */  C_ERROR,
/* 0F F0 */  C_ERROR,
/* 0F F1 */  C_ERROR,
/* 0F F2 */  C_ERROR,
/* 0F F3 */  C_ERROR,
/* 0F F4 */  C_ERROR,
/* 0F F5 */  C_ERROR,
/* 0F F6 */  C_ERROR,
/* 0F F7 */  C_ERROR,
/* 0F F8 */  C_ERROR,
/* 0F F9 */  C_ERROR,
/* 0F FA */  C_ERROR,
/* 0F FB */  C_ERROR,
/* 0F FC */  C_ERROR,
/* 0F FD */  C_ERROR,
/* 0F FE */  C_ERROR,
/* 0F FF */  C_ERROR,

/* additional tables, added in XDE */

                /* ttt: 0=add 1=or 2=adc 3=sbb 4=and 5=sub 6=xor 7=cmp */
                /* x=0..3 */
/* 8x /0 */  C_DST_FL+C_MOD_RM,
/* 8x /1 */  C_DST_FL+C_MOD_RM,
/* 8x /2 */  C_MOD_FL+C_MOD_RM,
/* 8x /3 */  C_MOD_FL+C_MOD_RM,
/* 8x /4 */  C_DST_FL+C_MOD_RM,
/* 8x /5 */  C_DST_FL+C_MOD_RM,
/* 8x /6 */  C_DST_FL+C_MOD_RM,
/* 8x /7 */  C_DST_FL+C_SRC_RM,
                /* ttt: 0=test 1=??? 2=not 3=neg 4=mul 5=imul 6=div 7=idiv */
/* F6 /0 */  C_DATA1+C_DST_FL+C_SRC_RM,
/* F6 /1 */  C_BAD,
/* F6 /2 */  C_DST_FL+C_MOD_RM,
/* F6 /3 */  C_DST_FL+C_MOD_RM,
/* F6 /4 */  C_DST_FL+C_SRC_RM+C_SPECIAL,
/* F6 /5 */  C_DST_FL+C_SRC_RM+C_SPECIAL,
/* F6 /6 */  C_DST_FL+C_SRC_RM+C_SPECIAL,
/* F6 /7 */  C_DST_FL+C_SRC_RM+C_SPECIAL,
                /* ttt: 0=test 1=??? 2=not 3=neg 4=mul 5=imul 6=div 7=idiv */
/* F7 /0 */  C_DATA66+C_DST_FL+C_SRC_RM,
/* F7 /1 */  C_BAD,
/* F7 /2 */  C_DST_FL+C_MOD_RM,
/* F7 /3 */  C_DST_FL+C_MOD_RM,
/* F7 /4 */  C_DST_FL+C_SRC_RM+C_SPECIAL,
/* F7 /5 */  C_DST_FL+C_SRC_RM+C_SPECIAL,
/* F7 /6 */  C_DST_FL+C_SRC_RM+C_SPECIAL,
/* F7 /7 */  C_DST_FL+C_SRC_RM+C_SPECIAL,
                /* ttt: 0=inc 1=dec 2=??? 3=??? 4=??? 5=??? 6=??? 7=??? */
/* FE /0 */  C_MOD_FL+C_MOD_RM,
/* FE /1 */  C_MOD_FL+C_MOD_RM,
/* FE /2 */  C_BAD,
/* FE /3 */  C_BAD,
/* FE /4 */  C_BAD,
/* FE /5 */  C_BAD,
/* FE /6 */  C_BAD,
/* FE /7 */  C_BAD,
             /* ttt: 0=inc 1=dec 2=callnear 3=callfar 4=jmpnear 5=jmpfar 6=push 7=??? */
/* FF /0 */  C_MOD_FL+C_MOD_RM,
/* FF /1 */  C_MOD_FL+C_MOD_RM,
/* FF /2 */  C_UNDEF+C_CMD_CALL,
/* FF /3 */  C_UNDEF+C_CMD_CALL,
/* FF /4 */  C_STOP+C_UNDEF,
/* FF /5 */  C_STOP+C_UNDEF,
/* FF /6 */  C_PUSH+C_SRC_RM,
/* FF /7 */  C_BAD

}; /* unsigned long xde_table[512] */

/* EOF */


4.xde_text.c文件

void xde_sprintfl(/*OUT*/char* output, /*IN*/unsigned long fl)
{
  output[0] = 0;

//  if (fl & C_BAD ) strcat(output,"C_BAD|");
  if (fl & C_BAD ) strcat(output,"C_BAD");

//  if (output[0])
//  if (output[strlen(output)-1]=='|')
//    output[strlen(output)-1]=0;
}

void xde_sprintset(/*OUT*/char* output, /*IN*/unsigned long set)
{
  output[0] = 0;

  if (set==XSET_UNDEF)
  {
    strcat(output,"???|");
  }
  else
  {

    if ((set&XSET_EAX)==XSET_EAX) strcat(output,"EAX|"); else
    if ((set&XSET_EAX)==XSET_AX)  strcat(output,"AX|" ); else
    {
      if (set&XSET_AL) strcat(output,"AL|");
      if (set&XSET_AH) strcat(output,"AH|");
    }

    if ((set&XSET_ECX)==XSET_ECX) strcat(output,"ECX|"); else
    if ((set&XSET_ECX)==XSET_CX)  strcat(output,"CX|" ); else
    {
      if (set&XSET_CL) strcat(output,"CL|");
      if (set&XSET_CH) strcat(output,"CH|");
    }

    if ((set&XSET_EDX)==XSET_EDX) strcat(output,"EDX|"); else
    if ((set&XSET_EDX)==XSET_DX)  strcat(output,"DX|" ); else
    {
      if (set&XSET_DL) strcat(output,"DL|");
      if (set&XSET_DH) strcat(output,"DH|");
    }

    if ((set&XSET_EBX)==XSET_EBX) strcat(output,"EBX|"); else
    if ((set&XSET_EBX)==XSET_BX ) strcat(output,"BX|" ); else
    {
      if (set&XSET_BL) strcat(output,"BL|");
      if (set&XSET_BH) strcat(output,"BH|");
    }

    if ((set&XSET_ESP)==XSET_ESP) strcat(output,"ESP|"); else
    if ((set&XSET_ESP)==XSET_SP ) strcat(output,"SP|");

    if ((set&XSET_EBP)==XSET_EBP) strcat(output,"EBP|"); else
    if ((set&XSET_EBP)==XSET_BP ) strcat(output,"BP|");

    if ((set&XSET_ESI)==XSET_ESI) strcat(output,"ESI|"); else
    if ((set&XSET_ESI)==XSET_SI ) strcat(output,"SI|");

    if ((set&XSET_EDI)==XSET_EDI) strcat(output,"EDI|"); else
    if ((set&XSET_EDI)==XSET_DI ) strcat(output,"DI|");

    if (set&XSET_FL) strcat(output,"F|");
    if (set&XSET_MEM) strcat(output,"M|");

    if (set&XSET_OTHER) strcat(output,"other|");
    if (set&XSET_DEV) strcat(output,"dev|");

  }

  if (output[0])
  if (output[strlen(output)-1]=='|')
    output[strlen(output)-1]=0;
} /* strcat_set */

5.xde.c文件

/* XDE v1.02 eXtended length disassembler engine, based on LDE/ADE engines */

#include "xde.h"
#include "xdetbl.c"

#define XDE32_DEFAULT_ADDR      32      /* 16 or 32, changed by 0x67 prefix */
#define XDE32_DEFAULT_DATA      32      /* 16 or 32, changed by 0x66 prefix */

unsigned long /*__inline*/ reg2xset(int reg_sz /*1,2,4*/, unsigned long reg)
{
  if (reg_sz == 1)
    return reg == 0 ? XSET_AL :
           reg == 1 ? XSET_CL :
           reg == 2 ? XSET_DL :
           reg == 3 ? XSET_BL :
           reg == 4 ? XSET_AH :
           reg == 5 ? XSET_CH :
           reg == 6 ? XSET_DH :
                      XSET_BH;
  else
  if (reg_sz == 2)
    return reg == 0 ? (XSET_AX|XSET_AL|XSET_AH) :
           reg == 1 ? (XSET_CX|XSET_CL|XSET_CH) :
           reg == 2 ? (XSET_DX|XSET_DL|XSET_DH) :
           reg == 3 ? (XSET_BX|XSET_BL|XSET_BH) :
           reg == 4 ? XSET_SP :
           reg == 5 ? XSET_BP :
           reg == 6 ? XSET_SI :
                      XSET_DI;
  else /* if (reg_sz == 4) */
    return reg == 0 ? (XSET_EAX|XSET_AX|XSET_AL|XSET_AH) :
           reg == 1 ? (XSET_ECX|XSET_CX|XSET_CL|XSET_CH) :
           reg == 2 ? (XSET_EDX|XSET_DX|XSET_DL|XSET_DH) :
           reg == 3 ? (XSET_EBX|XSET_BX|XSET_BL|XSET_BH) :
           reg == 4 ? (XSET_ESP|XSET_SP) :
           reg == 5 ? (XSET_EBP|XSET_BP) :
           reg == 6 ? (XSET_ESI|XSET_SI) :
                      (XSET_EDI|XSET_DI);
} /* reg2xset() */

/* returns:                                                                 */
/*   0 if error                                                             */
/*   instruction length (== diza.len) if OK                                 */

int __cdecl xde_disasm(/* IN */ unsigned char *opcode,
                       /* OUT */ struct xde_instr *diza)
{
  unsigned char c, *p;
  unsigned long flag, a, d, i, xset;
  unsigned long mod, reg, rm, index, base;

  p = opcode;

  memset(diza, 0x00, sizeof(struct xde_instr));

  diza->defdata = XDE32_DEFAULT_ADDR/8;
  diza->defaddr = XDE32_DEFAULT_DATA/8;

  flag = 0;

  if (*(unsigned short*)p == 0x0000) flag |= C_BAD;
  if (*(unsigned short*)p == 0xFFFF) flag |= C_BAD;

  while(1)
  {

    c = *p++;

    if (c == 0x66)
    {
      if (diza->p_66 != 0) flag |= C_BAD;        /* twice */
      diza->p_66 = 0x66;
      diza->defdata = (XDE32_DEFAULT_DATA^32^16)/8;
      continue;
    }

    if (c == 0x67)
    {
      if (diza->p_67 != 0) flag |= C_BAD;        /* twice */
      diza->p_67 = 0x67;
      diza->defaddr = (XDE32_DEFAULT_ADDR^32^16)/8;
      continue;
    }

    if ((c == 0x26) || (c == 0x2E) || (c == 0x36) || (c == 0x3E) ||
        (c == 0x64) || (c == 0x65))
    {
      if (diza->p_seg != 0) flag |= C_BAD;       /* twice */
      diza->p_seg = c;
      continue;
    }

    if ((c == 0xF2) || (c == 0xF3))
    {
      if (diza->p_rep != 0) flag |= C_BAD;       /* twice */
      diza->p_rep = c;
      continue;
    }

    if (c == 0xF0)
    {
      if (diza->p_lock != 0) flag |= C_BAD;      /* twice */
      diza->p_lock = c;
      continue;
    }

    break;

  } /* do while prefix found */

  /* check after all prefixes, because 66 and F2/F3 can be swapped */
  if (diza->p_rep)
  {
    xset = XSET_FL | (diza->defdata == 2 ? XSET_CX : XSET_ECX);
    diza->src_set |= xset;
    diza->dst_set |= xset;
  }

  /* instruction flags by opcode */
  flag |= xde_table[ TBL_NORMAL + c ];

  if (flag == C_ERROR) return 0;

  diza->opcode = c;

  if (c == 0x0F)
  {
    c = *p++;

    /* 2nd opcode */

    flag |= xde_table[ TBL_0F + c ]; /* from the 2nd half of the table */

    if (flag == C_ERROR) return 0;

    diza->opcode2 = c;

    /* 0F-prefixed "special" opcodes */

    if ( (c == 0xB2) || (c == 0xB4) || (c == 0xB5) || /* lss/lfs/lgs reg,r/m */
         (c == 0xA1) || (c == 0xA9) )                 /* pop fs, gs */
      diza->dst_set |= XSET_OTHER;

    if ((c == 0xA0) || (c == 0xA8))  /* push fs, gs */
      diza->src_set |= XSET_OTHER;

    if (c == 0xA2) /* cpuid */
    {
      diza->src_set |= XSET_EAX;
      diza->dst_set |= XSET_EAX|XSET_EBX|XSET_ECX|XSET_EDX;
    }

    if ((c == 0xA5) || (c == 0xAD))   /* shld/shrd r/m, reg, CL */
      diza->src_set |= XSET_CL;

  }
  else
  {
    /* "special" opcodes */

    if ((c == 0xA4) || (c == 0xA5) || /* movsb, movsd */
        (c == 0xA6) || (c == 0xA7))   /* cmpsb, cmpsd */
    {
      /* 66 or 67 ? */
      xset = diza->defaddr == 2 ? (XSET_SI | XSET_DI) : (XSET_ESI | XSET_EDI);
      diza->src_set |= xset;
      diza->dst_set |= xset;
    }

    if ((c == 0xAC) || (c == 0xAD)) /* lodsb, lodsd */
    {
      xset = diza->defaddr == 2 ? XSET_SI : XSET_ESI;
      diza->src_set |= xset;
      diza->dst_set |= xset;
    }

    if ((c == 0xAA) || (c == 0xAB) || /* stosb, stosd */
        (c == 0xAE) || (c == 0xAF))   /* scasb, scasd */
    {
      xset = diza->defaddr == 2 ? XSET_DI : XSET_EDI;
      diza->src_set |= xset;
      diza->dst_set |= xset;
    }

    if ((c == 0x6C) || (c == 0x6D)) /* insb, insd */
    {
      /* 66/67 ? */
      xset = XSET_DEV | (diza->defaddr == 2 ? XSET_DI : XSET_EDI);
      diza->src_set |= xset | XSET_DX;
      diza->dst_set |= xset;
    }
    if ((c == 0x6E) || (c == 0x6F)) /* outsb, outsd */
    {
      xset = XSET_DEV | (diza->defaddr == 2 ? XSET_SI : XSET_ESI);
      diza->src_set |= xset | XSET_DX;
      diza->dst_set |= xset;
    }

    if (c == 0x9E) /* sahf */
      diza->src_set |= XSET_AH;
    if (c == 0x9F) /* lahf */
      diza->dst_set |= XSET_AH;

    if (c == 0x98) /* cbw, cwde */
    {
      diza->src_set |= diza->defdata == 2 ? XSET_AL : XSET_AX;
      diza->dst_set |= diza->defdata == 2 ? XSET_AX : XSET_EAX;
    }
    if (c == 0x99) /* cwd, cdq */
    {
      diza->src_set |= diza->defdata == 2 ? XSET_AX : XSET_EAX;
      diza->dst_set |= diza->defdata == 2 ? XSET_DX : XSET_EDX;
    }

    if ((c == 0x37) || (c == 0x3F)) /* aaa, aas */
    {
      diza->src_set |= XSET_AH;
      diza->dst_set |= XSET_AH;
    }

    if ((c == 0xD4) || (c == 0xD5)) /* aam xx, aad xx */
    {
      diza->src_set |= c == 0xD4 ? XSET_AL : XSET_AX;
      diza->dst_set |= XSET_AX;
    }

    if (c == 0x60) /* pusha */
      diza->src_set |= diza->defdata == 2 ? XSET_ALL16 : XSET_ALL32;
    if (c == 0x61) /* popa */
      diza->dst_set |= diza->defdata == 2 ? XSET_ALL16 : XSET_ALL32;

    if ((c == 0xE4) || (c == 0xE5) || /* in al|(e)ax, NN */
        (c == 0xE6) || (c == 0xE7))   /* out NN, al|(e)ax */
    {
      /* 66,67 ? */
      diza->src_set |= XSET_DEV;
      diza->dst_set |= XSET_DEV;
    }

    if ((c == 0xEC) || (c == 0xED)) /* in al|(e)ax, dx */
    {
      /* 66,67 ? */
      diza->src_set |= XSET_DEV | XSET_DX;
      diza->dst_set |= XSET_DEV;
    }
    if ((c == 0xEE) || (c == 0xEF)) /* out dx, al|(e)ax */
    {
      /* 66,67 ? */
      diza->src_set |= XSET_DEV;
      diza->dst_set |= XSET_DEV | XSET_DX;
    }

    /* push es, cs, ss, ds */
    if ((c == 0x06) || (c == 0x0E) || (c == 0x16) || (c == 0x1E))
      diza->src_set |= XSET_OTHER;

    if ((c == 0x07) || (c == 0x17) || (c == 0x1F) ||  /* pop es, ss, ds */
        (c == 0xC4) || (c == 0xC5)) /* les/lds reg, r/m */
      diza->dst_set |= XSET_OTHER;

    if (c == 0xD7) /* xlat */
      diza->src_set |= diza->defaddr == 2 ? XSET_BX : XSET_EBX;

    if ((c == 0xC8) || (c == 0xC9)) /* enter xxxx, yy || leave */
    {
      xset = diza->defaddr == 2 ? (XSET_SP | XSET_BP) : (XSET_ESP | XSET_EBP);
      diza->src_set |= xset;
      diza->dst_set |= xset;
    }

    if (c == 0x8C)  /* mov [r/m]:16, sreg */
      diza->src_set |= XSET_OTHER;
    if (c == 0x8E)  /* mov sreg, [r/m]:16 */
      diza->dst_set |= XSET_OTHER;
  }

  if (flag & C_MODRM)
  {
    c = *p++;

    diza->modrm = c;

    mod = c & 0xC0;
    reg = (c & 0x38) >> 3;       /* reg or ttt */
    rm  = c & 0x07;

    c = diza->opcode;

    /* ttt-opcodes (reg==ttt) */

    /* shift */
    if ((c == 0xC0) || (c == 0xC1) || ((c >= 0xD0) && (c <= 0xD3)))
    {
      // ttt: 0=rol 1=ror 2=rcl 3=rcr 4=shl 5=shr 6=sal 7=sar
      if ((reg == 2) || (reg == 3)) /* rcl, rcr -- uses CF */
        diza->src_set |= XSET_FL;
      if ((c == 0xD2) || (c == 0xD3))
        diza->src_set |= XSET_CL;
    }

    if ( (c == 0xC6) || (c == 0xC7) ||  /* mov [r/m], imm8/16/32 */
         (c == 0x8F) )                  /* pop [r/m] */
      // ttt=000, other illegal
      if (reg != 0) flag |= C_BAD;

    if ((c >= 0x80) && (c <= 0x83)) flag |= xde_table[ TBL_80_83  + reg ];

    if (c == 0xBA)
      if (reg >= 5)                 /* bts/btr/btc [r/m], imm8 */
        flag |= C_DST_RM;

    if (c == 0xF6) flag |= xde_table[ TBL_F6 + reg ];
    if (c == 0xF7) flag |= xde_table[ TBL_F7 + reg ];
    if (c == 0xFE) flag |= xde_table[ TBL_FE + reg ];
    if (c == 0xFF) flag |= xde_table[ TBL_FF + reg ];

    if ((c == 0xF6) || (c == 0xF7))
    {
      if ((reg == 4) || (reg == 5)) /* mul/imul r/m */
      {
        if (c == 0xF6)
        {
          diza->src_set |= XSET_AL;
          diza->dst_set |= XSET_AX;
        }
        else
        if (diza->defaddr == 2)
        {
          diza->src_set |= XSET_AX;
          diza->dst_set |= XSET_DX | XSET_AX;
        }
        else
        {
          diza->src_set |= XSET_EAX;
          diza->dst_set |= XSET_EDX | XSET_EAX;
        }
      }
      if ((reg == 6) || (reg == 7)) /* div/idiv r/m */
      {
        if (c == 0xF6)
        {
          diza->src_set |= XSET_AX;
          diza->dst_set |= XSET_AX;
        }
        else
        if (diza->defaddr == 2)
        {
          diza->src_set |= XSET_DX | XSET_AX;
          diza->dst_set |= XSET_DX | XSET_AX;
        }
        else
        {
          diza->src_set |= XSET_EDX | XSET_EAX;
          diza->dst_set |= XSET_EDX | XSET_EAX;
        }
      }
    } /* F6/F7 */

    if (flag == C_ERROR) return 0;

    xset = reg2xset(flag & C_OPSZ8 ? 1 : diza->defdata, reg);
    if (flag & C_SRC_REG) diza->src_set |= xset;
    if (flag & C_DST_REG) diza->dst_set |= xset;

    if (mod == 0xC0)
    {
      xset = reg2xset(flag & C_OPSZ8 ? 1 : diza->defdata, rm);
      /* defaddr (0x67) prefix --> ??? */
      if (flag & C_DST_RM) diza->dst_set |= xset;

      if ( (diza->opcode == 0x0F) &&
           ( (diza->opcode2 == 0xB6) ||  /* movzx, movsx */
             (diza->opcode2 == 0xB7) ||
             (diza->opcode2 == 0xBE) ||
             (diza->opcode2 == 0xBF) ) )
        xset = reg2xset(diza->defdata==4?2:1, rm);

      if (flag & C_SRC_RM) diza->src_set |= xset;
    }
    else
    {
      if (diza->opcode != 0x8D) /* LEA: doesnt access memory contents */
      {
        diza->src_set |= XSET_OTHER;  /* since we have sreg:[xxx] */
        if (flag & C_SRC_RM) diza->src_set |= XSET_MEM;
      }

      if (flag & C_DST_RM) diza->dst_set |= XSET_MEM;

      if (diza->defaddr == 4)
      {
        /* 32-bit MODR/M */

        if (mod == 0x40)
        {
          flag |= C_ADDR1;
        }
        else
        if (mod == 0x80)
        {
          flag |= C_ADDR4;
        }

        if (rm == 4)
        {

          /* SIB */

          flag |= C_SIB;
          c = *p++;
          diza->sib = c;

          //scale = c & 0xC0;
          index = (c & 0x38) >> 3;
          base  = c & 0x07;

          if (base == 5)
          {
            xset = (mod == 0 ? 0 : XSET_EBP) | reg2xset(4, index);
            if (mod == 0) flag |= C_ADDR4;
            if (flag & C_SRC_RM) diza->src_set |= xset;
            if (flag & C_DST_RM) diza->src_set |= xset;
          }
          else
          {
            xset = reg2xset(4, base);
            if (flag & C_SRC_RM) diza->src_set |= xset;
            if (flag & C_DST_RM) diza->src_set |= xset;

            if (index != 0x05)
            {
              xset = reg2xset(4, index);
              if (flag & C_SRC_RM) diza->src_set |= xset;
              if (flag & C_DST_RM) diza->src_set |= xset;
            }
          }

        }
        else
        {
          /* no sib, just modr/m 32 */

          if ((mod == 0x00) && (rm == 0x05))
            flag |= C_ADDR4;
          else
          {
            xset = reg2xset(4, rm);
            if (flag & C_SRC_RM) diza->src_set |= xset;
            if (flag & C_DST_RM) diza->src_set |= xset;
          }

        }
      }
      else
      {
        /* 16-bit MODR/M */

        if (mod == 0x40)
        {
          flag |= C_ADDR1;
        }
        else
        if (mod == 0x80)
        {
          flag |= C_ADDR2;
        }
        else /* mod == 0x00 */
        {
          if (rm == 0x06)
            flag |= C_ADDR2;
        }

        if ((mod != 0x00) || (rm != 0x06))
        {
          xset = rm == 0 ? (XSET_BX | XSET_SI) :
                 rm == 1 ? (XSET_BX | XSET_DI) :
                 rm == 2 ? (XSET_BP | XSET_SI) :
                 rm == 3 ? (XSET_BP | XSET_DI) :
                 rm == 4 ? XSET_SI :
                 rm == 5 ? XSET_DI :
                 rm == 6 ? XSET_BP :
                           XSET_BX;
          if (flag & C_SRC_RM) diza->src_set |= xset;
          if (flag & C_DST_RM) diza->src_set |= xset;
        }

      }
    }
  } /* C_MODRM */
  else
  {
    /* its not modr/m, check for mem ref */

    if (flag & C_SRC_RM) diza->src_set |= XSET_MEM;
    if (flag & C_DST_RM) diza->dst_set |= XSET_MEM;

  }

  if (flag & C_UNDEF)
  {
    diza->src_set = XSET_UNDEF;
    diza->dst_set = XSET_UNDEF;
  }

  xset = reg2xset(diza->defdata, c & 0x07);
  if (flag & C_SRC_R0) diza->src_set |= xset;
  if (flag & C_DST_R0) diza->dst_set |= xset;

  if (flag & C_SRC_FL) diza->src_set |= XSET_FL;
  if (flag & C_DST_FL) diza->dst_set |= XSET_FL;

  xset = diza->defaddr == 2 ? XSET_SP : XSET_ESP; // incorrect, need stk seg sz
  if (flag & C_PUSH)
  {
    diza->src_set |= xset;                              // +
    diza->dst_set |= xset | XSET_MEM;
  }
  if (flag & C_POP)
  {
    diza->src_set |= xset | XSET_MEM;                   // +
    diza->dst_set |= xset;
  }

  xset = flag & C_OPSZ8 ? XSET_AL : diza->defdata == 2 ? XSET_AX : XSET_EAX;
  if (flag & C_SRC_ACC) diza->src_set |= xset;
  if (flag & C_DST_ACC) diza->dst_set |= xset;

  a =  flag & (C_ADDR1 | C_ADDR2 | C_ADDR4);
  d = (flag & (C_DATA1 | C_DATA2 | C_DATA4)) >> 8;

  if (flag & C_ADDR67) a += diza->defaddr;
  if (flag & C_DATA66) d += diza->defdata;

  for(i=0; i<a; i++)
    diza->addr_b[i] = *p++;

  for(i=0; i<d; i++)
    diza->data_b[i] = *p++;

  diza->flag     = flag;
  diza->addrsize = a;
  diza->datasize = d;
  diza->len      = p - opcode;

  return diza->len;

} /* int __cdecl xde_disasm() */

/* returns: diza.len                                                        */

int __cdecl xde_asm(/* OUT */ unsigned char* opcode,
                    /* IN */ struct xde_instr* diza)
{
  unsigned char* p;
  int i;

  p = opcode;

  if (diza->p_seg )               *p++ = diza->p_seg;
  if (diza->p_lock)               *p++ = diza->p_lock;
  if (diza->p_rep )               *p++ = diza->p_rep;
  if (diza->p_67  )               *p++ = diza->p_67;
  if (diza->p_66  )               *p++ = diza->p_66;
  *p++ = diza->opcode;
  if (diza->opcode == 0x0F)       *p++ = diza->opcode2;
  if (diza->flag & C_MODRM)       *p++ = diza->modrm;
  if (diza->flag & C_SIB)         *p++ = diza->sib;
  for(i=0; i<diza->addrsize; i++) *p++ = diza->addr_b[i];
  for(i=0; i<diza->datasize; i++) *p++ = diza->data_b[i];

  return p - opcode;

} /* int __cdecl xde_asm() */

/* EOF */

来源:http://www.woodmann.com/collaborative/tools/index.php
原创粉丝点击