转自:http://computerscience.ycool.com/post.1801408.html
Intel的IA32-x86体系结构CPU的每条指令都可能由以下六个域组成,并且它们在指令中的排列顺序是不能改变的。
  这六个域分别是:
            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]"。
                      
                      
    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位是列号。
关键词/Tags:  x86指令
相关文章:

  • » x86结构机器码识别及其反汇编

222222222222相关推荐

  1. 36 张图详解 ARP :网络世界没有我,你哪也别想去

    上帝视角 初识 ARP 从网络分层上看,我们知道二层网络中,使用 MAC 地址进行传输,MAC 地址做为数据链路层的设备标识符. 二层网络 三层网络中,使用 IP 地址进行传输,IP 地址做为网络层的 ...

  2. 区块链相关论文研读5:分布式隐私保护可审计的账本,zkLedger

    这篇文章首发于知乎专栏:https://zhuanlan.zhihu.com/p/87900715 这篇论文在2018年发表在顶会NSDI上面,题目为<zkLedger: Privacy-Pre ...

  3. some learning

    一.windows下迁移access到mysql Windows下 Access 数据 迁移到 Mysql(5.5)数据库1. 具体做法1. 在access的表中选择,文件->导出->保存 ...

  4. python 杀死一个线程

    "不要试图用强制方法杀掉一个python线程,这从服务设计上就存在不合理性. 多线程本用来任务的协作并发,如果你使用强制手段干掉线程,那么很大几率出现意想不到的bug." 话虽然这 ...

  5. 理解 OpenStack Swift (2):架构、原理及功能 [Architecture, Implementation and Features]...

    本系列文章着重学习和研究OpenStack Swift,包括环境搭建.原理.架构.监控和性能等. (1)OpenStack + 三节点Swift 集群+ HAProxy + UCARP 安装和配置 ( ...

  6. TC SRM 562 div2 B 题

    题意: 给你一个矩形的画布,此画布由'B'和'.'组成,画T次每次画的时候他的左上角的起始点是确定的几位(1,1),(2,2),(3,3)......(T,T); 在画的过程中可能会出现相互覆盖求画完 ...

  7. docker如何将运行中的容器保存为docker镜像?

    答: 使用docker commit和docker save保存镜像 $ sudo docker commit <当前运行的container id> <仓库名称>:<t ...

  8. 解决jmeter测试报告不显示后面的断言错误失败信息

    一.问题描述 使用jmeter进行自动测试了两个接口,该接口测试有4个断言,其中有3个断言是失败的,并且有相应的断言错误信息: 请求失败11111111111111 请求失败222222222222 ...

  9. Android Hander机制的理解

    总以为自己对Handler比较了解,但今天发现还是不了解,以后写代码得好好的看看android doc了,这样才能理解的更深. 一直以为Handler.post(Runnable)为开启一个线程,所以 ...

最新文章

  1. mysql5.7多实例安装_MySQL数据库5.7多实例安装
  2. 计算机上开发和运行应用程序与操作系统无关,计算机期中测验理论部分和答案-C.doc...
  3. python链接mysql系统结构设计_MySQLpython交互
  4. 多重继承java_Java中的多重继承与组合vs继承
  5. linux里工作目录的字体变蓝,netterm访问Linux时字体和背景颜色随目录发生改变的问题解决...
  6. C下的全局变量和指针 - C/C++ / C语言
  7. hibernate中主键的生成策略
  8. 友好的免抠图片素材| PNG设计元素集海量来袭
  9. Jupyter Notebook——如何显示目录的导航栏(安装 Jupyter Notebook extension)
  10. python上下文管理关键字_理解 Python 的上下文管理器
  11. php原生判断,JavaScript
  12. svn客户端(Windows版本)
  13. Python 修改图片的时候抗锯齿
  14. G729调用方法及使用wavlib播放出现颤音的解决方法
  15. 第九届“图灵杯”NEUQ-ACM部分汇总
  16. 基于springboot的生鲜门店配送管理系统(idea+springboot+html+thymeleaf)
  17. 花滑三周连跳_三周半+四周跳来势汹汹 花滑女单将迎难度巨变?
  18. 添加msg文件找不到目录add_message_files() directory not found:
  19. 三星I9220刷机包 新蜂ROM V4.1 高级设置 全透明天气插件
  20. 17岁高中生证明著名数学难题,因此被MIT录取

热门文章

  1. python list[list] or list[list, list, list]
  2. 频率与听感的对应关系
  3. 声音频率分类(二十一)
  4. marked.js讲解
  5. Java项目如何查找各种jar包
  6. 阿里云服务器 之 mqtt服务器搭建及使用
  7. PHP上传图片到服务器
  8. JavaPoet动态生成代码,高薪程序员必会
  9. idea Dmaven.multiModuleProjectDirectory=$M2_HOME报错!!!
  10. SpringMVC超详细入门