这六个域分别是:
            prefixes (1 Byte)
            code (1/2/3 Bytes;2字节指令是第一个指令码为0x0f,而一般3字节指令的第3字节是ModR/M的一部分)
            ModR/M (1 Byte)
            SIB (1 Byte)
            displacement (1/2/4 Bytes)偏移量
            immediate (1/2/4 Bytes)立即数
  在任何一条指令中code域必须出现,其他的域都是可选的。
  由于这六个域在指令中的排列顺序是固定的,所以反汇编机器码,就是一个对它们的依次识别过程。
  1、对prefixes的识别  
  x86体系结构CPU的4类prefixes,它们分别为:
            lock/repeat prefix      :F0/F2,F3 (LOCK和REP)
            segment override prefixes      :2E,36,3E,26,64,65 (忽略段的前缀)
            operand-size override prefix        :66 (忽略操作数大小的前缀)
            address-size override prefix        :67 (忽略地址大小的前缀)  
  指令的prefixes可以由这几类prefixes组成,但是每类prefixes只能在指令中出现一次,至于每类prefixes在指令的出项顺序是没有要求的,这点和指令的六个域是不同的。当某类prefixes在同一指令中出现多次的时候,CPU在执行过程中,可能会出现不可预料的结果,至于会不会出现异常,Intel的官方手册中只用了这句话来说明:such use may cause unpredictable behavior.鬼知道会出项什么情况,因此算法必须对这类机器码具有识别能力。但是也可能异常情况不会发生,在反汇编过程,遇到同一类prefixes出现多次的情况,以最后出现的prefix为准,进行机器码识别。
  总结:
    (1)Prefixes是唯一的一个可能出现在code之前的域。
    (2)所有的Prefixes都只有1个字节。 
    (3)在一个OpCode中可能会有多个Prefixes
    (4)如果有多个Prefixes,那么它们的顺序可以打乱,不会有任何问题。
    (5)如果Prefixes不能对随它之后的OpCode起作用,那么它就会被忽略。
    2、对code和operand的识别 
    CPU在设计时,为了提高比特位的利用率,也为了保证一个code不是另一个code的前缀(否则CPU也无法译码),code的编码采用的是哈夫曼算法。code的最大长度是3个字节,当然可以是1个字节,也可以是2个字节,另外,对于某些特定的code,还有3个比特的信息也会用来表示code.这3比特在ModR/M的3、4和5位。当然每个code也最多只能有三个operand。
    对code的识别一般都是采用二维表格来驱动的。二维表格中记录了给各code的详细信息。
    ModR/M字节:这个字节指示了后面跟随的操作数的形式,它分成3个部分:第7-6位是Mod部分,第5-3位是Reg部分,第2-0位是R/M部分,其中Mod和R/M部分结合指示了指令操作数的寻址方式,而Reg部分主要是指示用到的寄存器,这个字节的解释要和主操作码结合起来。
    SIB字节:除了上面这个ModR/M字节外,有时候指令还需要一个字节来补充指操作数的寻址方式,这个字节也分成3个部分:第7-6位是scale部分,第5-3位是index部分,第2-0位是base部分;
    在翻译过程中,以指令的操作码为索引从相应的数组来输出对应的指令字符串,而接下来最主要的就是对操作数的翻译,所有的操作数都可以用:【寻址方式 + 操作数类型】来表示,寻址方式有A(直接地址),C(ModR/M字节的REG部分指示一个控制寄存器),D( ModR/M字节的REG部分指示一个调试寄存器),E(ModR/M字节指示的操作数是一个通用寄存器或一个内存地址),F(EFLAGS寄存器),G(ModR/M字节的REG部分指示一个通用寄存器),I(立即数),J(指令包含一个相对地址),M(ModR/M字节指示一个内存地址),O(没有ModR/M字节,后面的字或双字为偏移地址),P(ModR/M字节的REG部分指示一个4字节MMX寄存器),Q(ModR/M字节指示的操作数是一个MMX寄存器或一个内存地址),R(ModR/M字节的Mod部分指示一个通用寄存器),S(ModR/M字节的REG部分指示一个段寄存器),T(ModR/M字节的REG部分指示一个测试寄存器),V(ModR/M字节的REG部分指示一个128位XMM寄存器),W(ModR/M字节指示的操作数是一个128位XMM寄存器或一个内存地址),X(内存地址由DS:SI寄存器对表示),Y(内存地址由ES:DI寄存器对表示);操作数类型主要有b(字节),d(双字节),w(字),v(字或双字,根据操作数大小定)。 
    3、现在就可以根据下面的两个表来进行机器码识别了。例如,如果二进制序列是0x03,0x70,0xe8,则操作码是0x03,查指令表Table A-2是"add Gv,Ev",第2个字节0x70是ModR/M字节,二进制是01110000,则Mod部分是1,REG部分是6,R/M部分是0,查ModR/M字节表Table 2-2得到Gv操作数是esi,Ev操作数是[eax+disp8],disp8是8位的偏移量,则读下一个字节0xe8,由于这个字节是负数,取相反值是0x18,则Ev操作数是[eax-0x18],所以输出的最终指令是"add esi,[eax-0x18]"。
                      image
                      image
    4、扩展指令
    除了单字节指令和二字节指令外还有一部分指令是三字节的,这些指令称作扩展指令,扩展指令是把ModR/M字节当作操作码的一部分,根据指令属于的不同group和REG部分的值来查Intel Manual中表Table A-4翻译指令的,如操作码为0x80-0x83的指令就是属于group 1,然后根据REG的值来确定操作码的字符串,如REG为5则是"sub"指令。
    5、浮点数指令
    浮点数指令又叫逃逸码指令(escape opcode instructions。它是主操作码为0xd8-0xdf的指令,并且用这个主操作码分成几组,每组指令中又根据ModR/M字节的值分成值在0x00-0xbf范围中和不在这个范围中两部分,在这个范围中的指令根据ModR/M字节字节中的REG部分进行索引,得到相应的指令;不在这个范围中的指令则按照ModR/M字节的值查找相应的表得到指令,ModR/M字节中的高4位是行号,低4位是列号。