x86 机器指令编码依次由一下部分组成:

  • 指令前缀(prefix,非必需)
  • 操作码(opcode,必需)
  • 寻址方式 R/M(ModR/M,非必需)
  • 比例因子-变址-基址(SIB,非必需)
  • 地址偏移量(displacement,非必需)
  • 立即数(immediate,非必需)
指令前缀 操作码 寻址方式 R/M 比例因子-变址-基址 地址偏移量 立即数

一、指令前缀

  指令前缀(prefix)可有可无,可以有多个,每一个前缀都用一字节表示。指令前缀的名称和编码如下表所示。

种类 名称 二进制编码 说明
Lock Lock F0H 让指令在执行时先禁用数据线的复用特性,用在多核的处理器上,一般很少需要手动指定
rep repne/repnz F2H 用cx(16 位下)或ecx(32位下)或rcx(64位下)作为指令是否重复执行的依据
rep/repe/repz F3H 同上
Segment Override cs 2EH 段重载(默认数据使用 DS 段)
ss 36H 同上(强制指令使用该段寄存器)
ds 3EH 同上
es 26H 同上
fs 64H 同上
gs 65H 同上
rex 64 位 40H~4FH x86-64 位的指令前缀
Operand size Override Operand size Override 66H 用该前缀来区分访问 32 位或 16 位操作数;也用来区分 128 位和 64 位操作数
Address Override Address Override 67H 64 位下指定用 64 位还是 32 位寄存器作为索引

  rep 是串操作指令前缀,它又可细分为 rep、repz、repnz 等,重复执行操作指令,直到满足或者不满足某些条件。这三个前缀不会同时使用,最多只使用其中一个。

  Segment Override 是跨段前缀。在分段内存管理模式下,使用跨段前缀来强制改变当前指令要访问的段,而不使用该机器指令默认访问的段。在扁平内存管理模式下,依然能在语句中使用跨段前缀,但是指令的功能等同无前缀。例如:

mov ebx,offset x    ; x 是 data 段中定义的一个变量
mov eax,cs:[ebx] ; 机器码是 2E 8B 03
mov eax,[ebx] ; 机器码是 8B 03

后两条语句执行的结果是相同的。

  Operand size Override 为操作数类型重载。在 .model flat 下,默认的操作数 32 位的(如使用 32 位的寄存器来访问操作数),此时不需要前缀。但是该环境下能够使用 16 位的操作数,在机器指令编码中增加前缀 66H,以区分指令是 16 位的操作数还是 32 位的操作数。例如:

mov ax,[ebx]    ; 机器码是 66 8B 03
mov eax,[ebx] ; 机器码是 8B 03

  由于 eax 和 ax 的编码是相同的(寄存器编码规则,在下面),从 "8B 03" 中区分不出使用的是 eax 还是 ax,故在使用 16 位操作数时,增加了类型重载前缀 66H。

  al 的编码也与 eax、ax 的编码相同。"mov al,[ebx]" 的机器码是 8A 03,没有前缀。操作码(8AH)的最后一个二进制位为 0,表示是对字节进行操作;操作码(8BH)的最后一个二进制位为 1,表示是对字进行操作(32 位指令中默认的是 32 位的操作数)。

二、操作码

  操作码(opcode)是操作符的编码,指明了要进行什么操作,长度为 1 个字节、2 个字节或者 3 个字节。大多数通用指令的操作码是单字节的,最多 2 个字节,但有的 FPU 指令、SSE 指令的长度为 3 个字节。在大多数指令的操作符编码中,最后一个二进制位(从右向左的第一个)用于指明操作数的类型,0 表示字节操作,1 表示字操作(32 位指令系统中为双字操作),在有指令前缀 66H 时为对字操作,在大多数双操作数指令中,操作码的倒数第二个二进制位(从右向左的第二个)为 1,表明目的操作数是寄存器寻址,为 0 表明源操作数是寄存器寻址。在有些指令中(如立即数传送给一个寄存器),操作码包含有寄存器的编码。另外,一般在 opcode 的编码中会体现出源操作码是否为立即数。例如:

  mov byte ptr [ebx],al 的机器码是 88 03,其中 88H 的最后 2 位为 00,表明了字节运算和源操作数为寄存器。

  mov al,[ebx] 的机器码是 8A 03,其中 8A 的最后 2 位为 10,指明了字节运算和目的操作数为寄存器。

  mov al,11h 的机器码是 B0 11,在操作码中有使用的寄存器编码,同时也指明了源操作数是立即数。

三、寻址方式 R/M(ModR/M)

  如果要有“寻址方式 R/M”编码,则它占 1 个字节,并指明了操作数的寻址方式。该字节分为三个自成部分,Mod(2 个二进制位)、Reg/opcode(3 个二进制位)、R/M(3 个二进制位)。它们的摆放顺序如下。

Mod(6~7 位) Reg/opcode(3~5 位) R/M(0~2 位)

  Mod 和 R/M 用来共同确定一个操作数的寻址方式,对于基址加变址寻址方式,还要使用比例因子-变址-基址(SIB)。Reg/opcode 中的 opcode 是基本的指令操作码 opcode的扩展。Reg则是用来指明寄存器寻址方式中的寄存器编号。

  在上操作数指令中,有源操作数的寻址方式、目的操作数的寻址方式,规定两个操作数不能同时为存储器寻址方式,立即数不能作为目的操作数的寻址方式。若不考虑源操作数是立即寻址这种情况(有无立即寻址的操作码中体现出来),则在双操作数指令中,一个是寄存器寻址(Reg),另一个是寄存器或存储器寻址(R/M)。它们在指令中的顺序可为

x86 机器指令编码规则的更多相关文章

  1. 【翻译】运行于x86机器上的FreeBSD的PCI中断

    来源 http://people.freebsd.org/~jhb/papers/bsdcan/2007/article/article.html 摘要 在拥有多个独立设备的计算机里一个重要的元素是一 ...

  2. Detours简介 (拦截x86机器上的任意的win32 API函数)

    Detours 当然是用detours,微软明显高腾讯一筹,同上,至今没失败过.写这种HOOK一定要再写个测试程序,不要直接HOOK你的目的程序,例如QQ,因为这样不方面更灵活的测试.说明一下:Det ...

  3. DELL、HP、IBM X86服务器命名规则

    DELL.HP.IBM X86服务器命名规则 各大服务器厂家对于自己的服务器命名都有一定的规则,通常会根据服务器的外观(如塔式.机架式.刀片等).处理器(如Intel或者AMD等).架构等信息来命名. ...

  4. 通过反汇编理解函数调用机制(x86和ARM)

    如下,一个简单的程序 #include <stdio.h> int add(int a, int b) { return a + b; } void main() { , b = ; in ...

  5. linux上配置bochs,搭建基于X86架构操作系统的开发环境

    学习操作系统最好的方法就是自己编写新的操作系统,或者修改已有的操作系统.但是如果在真机上完成这个过程,调试会成为一个很大的问题.利用虚拟机来完成,可以使调试过程变得简单,而且能节约很多开关机的时间. ...

  6. debian6保存iptables规则

    iptables规则不保存,一旦机器重启规则就清空了,所以需要保存: iptables-save >/etc/iptables-script vi /etc/rc.local 然后在文件中输入: ...

  7. mips32和x86下的大小端模式判定

    一.背景 1.1 mips32搭载32bit vxworks操作系统 1.2 x86搭载64bit windows10操作系统 二.大小端模式判定前的准备 2.1 先要知道各种架构上各种整型数占据的b ...

  8. Risc-V简要概括

    1.Risc-V硬件平台术语 一个RiscV硬件平台可以包含一个或多个RiscV兼容的核心.其它非RiscV兼容的核心.固定功能的加速器.各种物理存储器结构.I/O设备以及允许这些部件相互连通的互联结 ...

  9. 基于ARM处理器的反汇编器软件简单设计及实现

    写在前面 2012年写的毕业设计,仅供参考 反汇编的目的 缺乏某些必要的说明资料的情况下, 想获得某些软件系统的源代码.设计思想及理念, 以便复制, 改造.移植和发展: 从源码上对软件的可靠性和安全性 ...

  10. MIT 6.828 JOS学习笔记10. Lab 1 Part 3: The kernel

    Lab 1 Part 3: The kernel 现在我们将开始具体讨论一下JOS内核了.就像boot loader一样,内核开始的时候也是一些汇编语句,用于设置一些东西,来保证C语言的程序能够正确的 ...

随机推荐

  1. 分享我通过 API 赚钱的思路

    写在最前 我们经常看到非常多的 API 推荐,但又经常收藏到收藏夹里吃灰,仿佛收藏了就是用了. 很多时候没有用起来,可能是因为想不到某类 API 可以用来做什么或者能应用在哪里. 下面我将我思考的一些 ...

  2. 2023年数字化经济与管理科学国际学术会议(CDEMS2023)

    基本信息 大会官网:www.cdems.org 大会时间:2023年4月21-23日 大会地点:中国开封 截稿时间:2023年4月16日(此处有变动) 接受/拒稿通知:投稿后1周 收录检索:CPCI, ...

  3. 使用Electron-builder将web项目封装客户端安装包 发布

    背景:之前用electron-packager将web项目打包成客户端时,exe文件只能在当前文件夹下运行,如果发送给别人使用 极不方便.所以我们可以用electron-builder将web项目封装 ...

  4. 从0开始学杂项 第三期:隐写分析(2) PNG图片隐写

    Misc 学习(三) - 隐写分析:PNG 图片隐写 在上一期,我主要讲了讲自己对于隐写分析.信息搜集和直接附加的一些浅薄理解,这一期我们继续对隐写分析的学习,开始讲隐写分析最喜欢考的一项--图片隐写 ...

  5. python入门教程之二十一json操作

    JSON (JavaScript Object Notation) 是一种轻量级的数据交换格式 python3 中可以使用 json 模块来对 JSON 数据进行编解码,它包含了两个函数: json. ...

  6. [Linux]CPU架构/指令集:RISC / CISC | arm | amd | X86/i386 | aarch64

    1 前言 本文是解决在软件开发.软件交付过程中,常常需要找寻与服务器硬件的CPU架构适配的软件包时,开发者和交付者又时常摸不着头脑.[迷迷糊糊]地就下载了某个所谓"适配".&quo ...

  7. AQS源码学习

    抽象队列同步器AQS AQS介绍 AQS提供一套框架用于实现锁同步机制,其通过一个 FIFO队列 维护线程的同步状态,实现类只需要继承 AbstractQueuedSynchronizer ,并重写指 ...

  8. Mysql中如果建立了索引,索引所占的空间随着数据量增长而变大,这样无论写入还是查询,性能都会有所下降,怎么处理?

    索引所占空间的增长确实会对MySQL数据库的写入性能和查询性能造成影响,这主要是由于索引数据过多时会导致磁盘I/O操作变得非常频繁,从而使性能下降.为此,可以采取以下几种方式来减缓这种影响: 1. 限 ...

  9. Ajax 方法返回值无效

    遇到错误为再ajax 中返回数据不起作用 原来是因为在阿贾克斯success中不能直接return 需要执行完再进行返回 以下代码为正确代码        function TestAction(id ...

  10. HDCTF_2023

    pwnner 附件 有后门函数,seed是一个固定值, //伪随机数 #include <stdio.h> #include <stdlib.h> int main() { i ...