opcode从零开始
参考资料:
-
Intel® 64 and IA-32 ArchitecturesSoftware Developer’s Manual Combined Volumes: 1, 2A, 2B, 2C, 2D, 3A, 3B, 3C, 3D, and 4()
Intel®64和IA-32架构软件开发人员手册组合卷:1,2a, 2B, 2C, 2D, 3A, 3B, 3C, 3D,和4 -
罗聪–cvjark.github.io/My-Save-Pages/技术贴/learningopcode/doc/前言.htm
-
海哥-硬编码
-
邓志–指令的 operand size (17woo.com) 原博客已经无法阅读,此链接部分内容已经无法查看
-
其他热心网友博客
CHAPTER 1 概述
从:Intel® 64 and IA-32 ArchitecturesSoftware Developer’s Manual Volume 2 (2A, 2B, 2C, & 2D): Instruction Set Reference, A-Z
(Intel®64和IA-32架构软件开发人员手册卷2 (2A, 2B, 2C和2D):指令集参考,A-Z)
本节内容 将参考手册 并说明一些重要的内容. 标题按照手册的标题命名,以便读者 可以快速定位并阅读英文原内容版
1.3.1 Bit and Byte Order
主要介绍IA-32处理器是小端字节序 机器, 有关小端字节序可参考各 操作系统书籍 都有介绍
1.3.3 Instruction Operands
[!NOTE]
本节主要介绍在手册中指令的书写方式
label: mnemonic argument1, argument2, argument3
-
label是一个标识符,后面跟一个冒号。
-
mnemonic (助记符) 是一类具有相同功能的指令操作码的保留名称.
-
Operands (操作数)argument1、argument2和argument3是可选的。根据操作码的不同,可以有0到3个操作数。当出现时,它们采用数据项的字面量或标识符的形式。
操作数标识符要么是寄存器的保留名称,要么被假定分配给在程序的另一部分声明的数据项(在示例中可能没有显示)
例子:
LOADREG: MOV EAX, SUBTOTAL
LOADREG是一个label,MOV是opcode(操作码)的mnemonic (助记符) 标识符,EAX是 destination operand(目的操作数),SUBTOTAL是 source operand(源操作数)。有些汇编语言将源和目标按相反的顺序排列。
1.3.4 Hexadecimal and Binary Numbers
[!NOTE]
本节主要介绍在手册中16进制数和2进制数的表达方式
十六进制数由后跟字符H的一串十六进制数字表示(例如,F82EH)
基数2(二进制)数由1和0组成的字符串表示,有时后面跟着字符B(例如1010B)。“B”标识仅在可能出现数字类型混淆的情况下使用。
1.3.5 Segmented Addressing
[!NOTE]
本节粗略介绍 段寻址的概念,
详细参考Intel® 64 and IA-32 Architectures Software Developer’s Manual Volume 3 (3A, 3B, 3C, & 3D): System Programming Guide 中的 3.1 MEMORY MANAGEMENT OVERVIEW(内存管理概述)
1.3.6 Exceptions
[!NOTE]
本节粗略讲解异常的表示方法
异常通常是指令导致错误时发生的事件。例如,尝试除以0会产生异常。但是,在其他条件下会出现一些异常,例如断点。某些类型的异常可能提供错误代码。错误代码报告有关错误的附加信息。下面是一个用于显示异常和错误代码的表示法示例:#PF(错误代码)这个示例指的是在报告错误代码命名故障类型的情况下的页面错误异常。在某些情况下,产生错误代码的异常可能无法报告准确的代码。在这种情况下,错误代码为零,如下面的通用保护异常所示:#GP(0)
1.3.7 A New Syntax for CPUID, CR, and MSR Values
[!NOTE]
本节粗略介绍CPUID指令 CR寄存器和MSR寄存器
CPUID指令:请直接查阅 第2卷指令集参考
CR寄存器: 请阅读 第3卷系统编程指南 2.5节控制寄存器内容
MSR寄存器:请阅读第4卷Volume 4: Model-Specific Registers
CHAPTER 2 指令格式
2.1 INSTRUCTION FORMAT FOR PROTECTED MODE, REAL-ADDRESS MODE, AND VIRTUAL-8086 MODE
[!NOTE]
本节开始介绍 保护模式、实地址模式和虚拟8086模式的指令格式
Intel 64和IA-32架构的指令编码是图2-1所示格式的子集。。指令由可选的指令前缀(顺序不限)、Opcode(最多三个字节)、一个寻址形式说明符(如果需要的话),该说明符由 ModR/M 字段组成,有时还包括 SIB(比例-索引-基址)字段,偏移量(如果需要的话),以及立即数字段(如果需要的话)构成。
指令前缀(InstructionPrefixes) | Opcode | ModR/M | SIB | 偏移量(Displacement) | 立即数(Immediate) |
---|---|---|---|---|---|
每个前缀1字节(可选)¹ ² | 1、2或3字节 | 1字节(如果需要) | 1字节(如果需要) | 地址位移为1、2或4字节或没有³ | 1、2、4字节或者没有³ |
- REX前缀是可选的,但如果使用,必须紧接在操作码之前;参见第2.2.1节,“REX前缀”了解更多信息。
- 有关VEX编码信息,请参见第2.3节“Intel®Advanced Vector Extensions (Intel®AVX)”。
- 一些罕见的指令可能需要8字节立即数或8字节偏移量。
2.1.1 Instruction Prefixes
[!NOTE]
本节开始介绍指令前缀
指令前缀分为四组,每组都有一组允许的前缀代码。对于每条指令,从四组(组1、组2、组3、组4)中每组最多包含一个前缀代码是有用的。组1到组4可以以任何相对顺序排列。
-
Group 1
— Lock(锁定) 和 repeat(重复) 前缀:
- LOCK前缀使用F0H编码。
- REPNE/REPNZ前缀使用F2H编码。Repeat-Not-Zero前缀仅适用于字符串和输入/输出指令。(F2H也用作某些指令的强制前缀。)
- REP或REPE/REPZ使用F3H编码。repeat前缀仅适用于字符串和输入/输出指令。(F3H也用作某些指令的强制前缀。)
[!IMPORTANT]
说明: :LOCK前缀
定义:用于确保对内存操作的原子性。它通常在多处理器或多线程环境中使用,以防止数据竞争和确保数据一致性。
功能: 原子性:在执行前缀指示的操作时,
LOCK
确保其他处理器无法访问被修改的内存地址,直到当前操作完成。 禁止中断:使用
LOCK
前缀时,处理器会确保在执行过程中不会被中断,从而保证操作的完整性。
[!IMPORTANT]
–说明: 重复前缀(F2H, F3H)导致对字符串的每个元素重复一条指令。这些前缀仅用于字符串和I/O指令(MOVS、CMPS、SCAS、LODS、STOS、INS和out)。保留使用重复前缀和/或未定义的操作码与其他Intel 64或IA-32指令;这样的使用可能会导致不可预测的行为
— 满足以下条件时,BND前缀使用F2H编码:
-
CPUID.(EAX=07H, ECX=0):EBX.MPX[bit 14] 被置位
-
`BNDCFGU.EN and/or IA32_BNDCFGS.EN 被置位
-
当F2前缀位于near CALL、near RET、near JMP、short Jcc或near Jcc指令之前时(参见Intel®64和IA-32架构软件开发人员手册第1卷的附录E,“Intel®内存保护扩展”)。
[!IMPORTANT]
–说明:将这段理解为一个函数
CPUID.(EAX=07H, ECX=0) : EBX.MPX[bit 14]
CPUID.(EAX=07H, ECX=0)
:这部分指定了在调用CPUID
时,EAX寄存器
中的值位07H
,ECX寄存器
中的值位0
EBX.MPX[bit 14]
:这部分说明CPUID指令执行
完成后在EBX
寄存器的第 14 位(bit 14)用于指示是否支持 MPX 特性[!IMPORTANT]
–说明:BNDCFGU和IA32_BNDCFGS 都是寄存器
[!IMPORTANT]
–说明:“Intel® Memory Protection Extensions(Intel®内存保护扩展)简称MPX,已经被弃用
-
Group 2
— 段覆盖前缀:
- 2EH—CS segment override (use with any branch instruction is reserved).
- 36H—SS segment override prefix (use with any branch instruction is reserved).
- 3EH—DS segment override prefix (use with any branch instruction is reserved).
- 26H—ES segment override prefix (use with any branch instruction is reserved).
- 64H—FS segment override prefix (use with any branch instruction is reserved).
- 65H—GS segment override prefix (use with any branch instruction is reserved)
— 分支提示前缀:
2EH
—Branch Not Taken 是一个分支提示,用于指示处理器在执行条件跳转指令(Jcc)时,预期该分支 不被采取。- 3EH — Branch taken 这个指令指示处理器在执行
Jcc
指令时应该假定该分支将被采取
[!IMPORTANT]
分支提示是用于优化处理器分支预测的指令。当程序执行分支指令(如
Jcc
指令)时,处理器可能会根据预测的结果进行操作。通过使用分支提示,可以提供关于分支可能结果的额外信息,以帮助提高性能 -
Group 3
- 操作数大小覆盖前缀使用66H编码(66H也用作某些指令的强制前缀)
[!IMPORTANT]
操作数大小覆盖前缀允许程序在16位和32位操作数大小之间切换。任何一个大小都可以是默认值;使用前缀选择非默认大小。
-
Group 4
- 67H -地址大小覆盖前缀
[!IMPORTANT]
地址大小覆盖前缀(67H)允许程序在16位和32位寻址之间切换。任何一个大小都可以是默认值;前缀选择非默认大小。当指令的操作数不在内存中时,使用该前缀和/或其他未定义的操作码是保留的;这样的使用可能会导致不可预测的行为。
2.1.2 Opcodes
主操作码的长度可以是1、2或3个字节。一个额外的3位操作码字段有时被编码在ModR/M字节中。较小的字段可以在主操作码中定义。这些字段定义了操作方向、位移大小、寄存器编码、条件码或符号扩展。操作码使用的编码字段因操作的类别而异。
通用指令和SIMD指令的双字节操作码格式由以下内容之一组成:
- 转义操作码字节0FH作为主操作码,加上两个额外的操作码字节。
- 一个强制前缀(66H、F2H或F3H)、一个转义操作码字节,加上两个额外的操作码字节(与前面的项目符号相同)。
有效的操作码表达式定义在附录A和附录B中
2.1.3 ModR/M and SIB Bytes
许多引用内存中操作数的指令在主操作码后面有一个寻址形式说明符字节(称为ModR/M字节)。ModR/M字节包含三个信息字段:
- mod字段与r/m字段组合形成32个可能的值:8个寄存器和24种寻址模式 (一个字节 8位 可以表示2的8次方可能)
- reg/opcode字段指定一个寄存器号或三个以上的操作码信息。reg/opcode字段的目的在主操作码中指定
- r/m字段可以将寄存器指定为操作数,也可以与mod字段结合使用以编码寻址模式。有时,使用mod字段和r/m字段的特定组合来表示某些指令的操作码信息
ModR/M字节的某些编码需要第二个寻址字段(SIB字段)。32位寻址的基本加索引和缩放加索引形式需要SIB字节。SIB字节包括以下字段:
- scale字段指定比例因子
- index字段指定索引寄存器的寄存器号。
- base字段 指定 基寄存器 的寄存器号
ModR/M和SIB字节的编码参见2.1.5节
2.1.4 Displacement and Immediate Bytes
一些寻址形式包括 紧跟在ModR/M字节(或SIB字节,如果有的话)之后的displacement(偏移量)。如果需要一个displacement(偏移量),它可以是1、2或4字节。
如果指令指定了 immediate (立即数),则操作数总是跟在任何移位字节后面。 immediate(立即数)操作数 可以是1、2或4字节。
2.1.5 Addressing-Mode Encoding of ModR/M and SIB Bytes
ModR/M和SIB字节的值和对应的寻址形式如 Table 2-1 ~ Table2-3所示:ModR/M字节指定的16位寻址形式如 Table2-1所示,32位寻址形式如 Table2-2所示。 Table2-3显示了由SIB字节指定的32位寻址形式。在ModR/M字节中的reg/opcode字段表示扩展操作码的情况下,有效编码显示在附录B中。
在Table2-1和Table2-2中,Effective Address列出了32个有效地址,这些地址可以通过ModR/M字节的Mod和R/M字段分配给指令的第一个操作数。前24个选项提供指定存储器位置的方法;最后八个(Mod = 11B)提供了指定通用、MMX技术和XMM寄存器的方法
Table2-1和Table2-2中的 Mod 和R/M 列给出了获取第一列有效地址所需的Mod和R/M字段的二进制编码。例如:见Mod = 11B, R/M = 000B所示行。这一行标识通用寄存器EAX、AX或AL;MMX技术寄存器MM0;或XMM注册XMM0。所使用的寄存器由操作码字节和操作数大小属性决定。
现在看看这两个表中的第七行(标记为“REG =”)。这一行指定了3位Reg/Opcode字段用于给出第二个操作数的位置时的使用。第二个操作数必须是通用的、MMX技术的或XMM寄存器。第一行到第五行列出了可能与表中的值对应的寄存器。同样,所使用的寄存器由操作码字节和操作数大小属性决定。
如果指令不需要第二个操作数,那么Reg/Opcode字段可以用作操作码扩展。这种用法由表中的第六行表示(标记为“/digit (Opcode)”)。注意,第6行中的值以十进制形式表示。
Table2-1和Table2-2的主体(在“Value of ModR/M Byte (in Hexadecimal)”标签下)包含一个32 * 8的数组,表示ModR/M字节(in Hexadecimal)的全部256个值。位3、位4和位5是由字节所在表的列指定的。这一行指定了0、1和2位 第6位和第7位。下图展示了对一个表值的解释。
[!NOTE]
- **[–][–]**表示法意味着在 ModR/M 字节之后跟随一个 SIB(Scale-Index-Base)字节
- disp32 表示法指的是一个 32 位的位移量,它跟在 ModR/M 字节(如果有 SIB 字节的话,则跟在 SIB 字节后面)之后。这个位移值会被直接加到有效地址计算的索引或基址中。
- disp8 表示法指的是一个 8 位的位移量,它跟在 ModR/M 字节(如果有 SIB 字节的话,则跟在 SIB 字节后面)之后。这个位移值会被符号扩展(sign-extended)为 32 位,并加到有效地址计算的索引或基址中。
表2-3给出了SIB字节的256个可能值(十六进制)。用作基寄存器的通用寄存器在表的顶部表示,以及SIB字节基字段的相应值。
表体中的表行表示用作索引的寄存器(SIB字节位3,4,5)和缩放因子(由SIB字节位6和7决定)
[!NOTE]
如果MOD为 00B,则
[*]
命名法是指不带基的dis32。否则,[*]
表示dis8或dis32 + [EBP]。这提供了以下地址模式MOD bits Effective Address
00 [scaled index] + disp32
01 [scaled index] + disp8 + [EBP]
10 [scaled index] + disp32 + [EBP]
2.2 IA-32E MODE
IA-32e模式有两个子模式。这些都是:
- Compatibility Mode (兼容模式)。使64位操作系统能够不经修改地运行大多数旧的 legacy protected mode (保护模式)软件。
- 64-Bit Mode (纯64位模式)。使64位操作系统能够运行为访问64位地址空间而编写的应用程序。
2.2.1 REX Prefixes
REX前缀是64位模式下使用的指令前缀字节。他们做的是:
- 指定GPRs 和SSE 寄存器
- 指定64位操作数大小
- 指定extended control registers.(扩展控制寄存器)。
在64位模式下,并非所有指令都需要REX前缀。只有当指令引用扩展寄存器之一或使用64位操作数时,才需要前缀。如果在没有意义的情况下使用REX前缀,则会忽略它,就像前缀中没有意义的单个位一样。
每条指令只允许使用一个有意义的REX前缀。如果使用,REX前缀字节必须紧接在 opcode 或**escape opcode(**转义操作码)字段(*0FH)*之前。当REX前缀与包含 mandatory prefix(强制前缀)的指令一起使用时,强制前缀必须位于REX之前,因此REX前缀可以立即位于操作码或转义字节之前。例如,带有REX前缀的CVTDQ2PD应该将REX放置在F3和0fe6之间。其他位置将被忽略。15字节的指令大小限制仍然适用于带有REX前缀的指令。如图2-3所示。
2.2.1.1 Encoding
Intel 64和IA-32指令格式通过在编码中使用3位字段指定最多三个寄存器,具体取决于格式:
- ModR/M字段: reg 字段 和r/m 字段
- ModR/M字段后跟 SIB字段: ModR/M字节的reg字段,SIB (scale, index, base)字段的base字段和index字段
- 没有ModR/M字段的指令:opcode中的reg字段
在64位模式下,这些格式不会改变。在64位上下文中定义字段所需的位是通过添加REX前缀来提供的
2.2.1.2 More on REX Prefix Fields
REX前缀是一组16个操作码,它们横跨 opcode map (操作码映射表)的一行,占用40H到4FH项。这些操作码表示IA-32模式和兼容模式下的有效指令(INC或DEC)。在64位模式下,相同的操作码表示指令前缀REX,并且不被视为单独的指令。
在64位模式下,INC/DEC指令的单字节操作码形式不可用。使用相同指令的ModR/M形式(操作码FF/0和FF/1)仍然可以使用INC/DEC功能。
对REX前缀格式的总结请参见 Table 2-4 。REX前缀字段的使用示例如图2-4 ~图2-7所示。某些REX前缀字段的组合无效。在这种情况下,前缀将被忽略。以下是一些附加资料:
-
设置 REX.W 可用于确定操作数的大小,但不能单独确定操作数的宽度。与66H大小前缀一样,64位操作数大小覆盖对特定于字节的操作没有影响。
-
对于non-byte(非字节)操作:如果66H前缀与 (REX.W = 1) 前缀一起使用 , 66H将被忽略。
-
REX.R 修改 ModR/M 字节中的 reg 字段,当该字段编码为通用寄存器(GPR)、SSE 寄存器、控制寄存器或调试寄存器时,REX.R 起作用。当 ModR/M 指定其他寄存器或定义了一个扩展操作码时,REX.R 会被忽略。
-
EX.X 位修改 SIB 字节中的索引(index)字段。
-
REX.B 可以修改 ModR/M 字节中的 r/m 字段中的基址,或者修改 SIB 字节中的基址字段;或者它也可以修改用于访问通用寄存器(GPRs)的操作码中的 reg 字段。
在 IA-32 架构中,字节寄存器(AH、AL、BH、BL、CH、CL、DH 和 DL)在 ModR/M 字节的 reg 字段、r/m 字段或操作码的 reg 字段中编码为寄存器 0 到 7。REX 前缀提供了对字节寄存器的额外寻址能力,使得通用寄存器(GPRs)中最低有效字节可以用于字节操作。
ModR/M 字节和 SIB 字节的某些字段组合对寄存器编码具有特殊含义。对于某些组合,REX 前缀扩展的字段不会被解码。 Table 2-5 描述了每种情况的行为。
[!NOTE]
不必关注 REX.B 的值
2.2.1.3 Displacement
64位模式下的寻址使用现有的32位ModR/M和SIB编码。ModR/M和SIB位移大小没有变化。它们仍然是8位或32位,并且符号扩展到64位
2.2.1.4 Direct Memory-Offset MOVs
在64位模式下,MOV指令的直接内存偏移形式被扩展为指定64位直接绝对地址。这个地址称为moffset。不需要前缀来指定这个64位内存偏移量。对于这些MOV指令,内存偏移量的大小遵循地址大小的默认值(64位模式下的64位)。如Table 2-6所示。
2.2.1.5 Immediates
在64位模式下, immediate(立即数) 的典型大小仍然是32位。当操作数的大小为64位时,处理器在使用它们之前将所有的直接数符号扩展为64位。
对64位直接操作数的支持是通过扩展现有move (MOV reg, imm16/32)指令的语义来实现的。这些指令(操作码B8H - BFH)将16位或32位的直接数据(取决于有效操作数的大小)移动到GPR中。当有效操作数大小为64位时,这些指令可用于将一个立即数加载到GPR中。需要REX前缀将32位默认操作数大小覆盖为64位操作数大小
For example:
48 B8 8877665544332211 MOV RAX,1122334455667788H
2.2.1.6 RIP-Relative Addressing RIP 相对寻址
在64位模式下实现了一种新的寻址形式----rip相对(相对指令指针)寻址。有效的地址是通过在下一条指令的64位RIP
加displacement(偏移)
来形成的。
在IA-32体系结构和compatibility(兼容)模式下,相对于指令指针的寻址只适用于**control-transfer (控制转移)**指令。在64位模式下,使用ModR/M寻址的指令可以使用rip相对寻址。没有rip相对寻址,所有ModR/M模式的寻址内存相对于零。
RIP 相对寻址允许特定的 ModR/M 模式使用带符号的 32 位displacement来相对于 64 位的 RIP 地址访问内存。这提供了从 RIP 的 ±2GB 的偏移范围。 **Table 2-7.**显示了用于 RIP 相对寻址的 ModR/M 和 SIB 编码。目前的 ModR/M 和 SIB 编码中存在冗余的 32 位位移寻址形式。RIP 相对寻址使用了一种冗余的编码形式,包括一个 ModR/M 编码和多个 SIB 编码。
RIP 相对寻址的 ModR/M 编码不依赖于使用前缀。具体来说,r/m 位字段编码为 101B(用于选择 RIP 相对寻址)不会受到 REX 前缀的影响。例如,选择 R13(REX.B = 1,r/m = 101B)并且 mod = 00B 仍然会导致使用 RIP 相对寻址。REX.B 的 4 位 r/m 字段与 ModR/M 结合后并不是完全解码的。为了在没有位移的情况下访问 R13,软件必须使用一个值为零的 1 字节位移编码为 R13 + 0。
RIP 相对寻址在 64 位模式下启用,而不是通过 64 位地址大小来启用。使用地址大小前缀不会禁用 RIP 相对寻址。地址大小前缀的效果是将计算出的有效地址截断并零扩展到 32 位。
2.2.1.7 Default 64-Bit Operand Size
在64位模式下,两组指令的默认操作数大小为64位(不需要为该操作数大小添加REX前缀)。这些都是:
-
近跳转(Near branches):这是指在当前代码段内进行跳转的指令,比如条件跳转和无条件跳转。这些指令使用 64 位的地址表示,但不需要额外的 REX 前缀来指示操作数的大小。
-
所有隐式引用堆栈指针寄存器(RSP)的指令也默认使用 64 位操作数大小。这些指令通常用于操作函数调用和栈操作,如推入或弹出栈的值。
2.2.2 Additional Encodings for Control and Debug Registers控制和调试寄存器的附加编码
在 64 位模式下,控制寄存器和调试寄存器有更多的编码可用。当 ModR/M 的 reg 字段编码为控制寄存器或调试寄存器时,REX.R 位用于修改该字段(请参见表 2-4)。这些编码使得处理器能够访问 CR8-CR15 和 DR8-DR15。在 64 位模式中定义了一个额外的控制寄存器(CR8)。CR8 被称为任务优先级寄存器(TPR)。
在 IA-32e 模式的最初实现中,并没有实际的寄存器 CR9 到 CR15 和 DR8 到 DR15。也就是说,这些寄存器在硬件上并不存在。如果程序尝试访问这些未实现的寄存器,例如通过某些指令读取或写入它们的值,处理器会触发一个异常,这种异常被称为 无效操作码异常(#UD, Undefined Opcode)。这意味着处理器无法识别或执行该操作,从而导致程序崩溃或中断
2.3 INTEL® ADVANCED VECTOR EXTENSIONS (INTEL® AVX) intel®高级矢量扩展(intel®avx)
…略
CHAPTER 3 INSTRUCTION SET REFERENCE, A-L指令集参考
本章描述了 Intel 64 和 IA-32 架构(A-L)在 IA-32e、保护模式、虚拟 8086 模式和实地址模式下的指令集。该指令集包括通用指令、x87 FPU 指令、MMX 指令、SSE/SSE2/SSE3/SSSE3/SSE4 指令、AESNI/PCLMULQDQ 指令、AVX 指令和系统指令。有关更多信息,请参见《Intel® 64 和 IA-32 架构软件开发手册》第 2B 卷的第 4 章“指令集参考,M-U”;第 2C 卷的第 5 章“指令集参考,V”;以及第 2D 卷的第 6 章“指令集参考,W-Z”。
对于每条指令,都会描述每种操作数组合。提供了指令及其操作数的描述、操作描述、指令对 EFLAGS 寄存器中标志的影响描述以及可能生成的异常的总结。
3.1 INTERPRETING THE INSTRUCTION REFERENCE PAGES 解释指令参考页
本节描述本章的指令参考页中包含的信息的格式。它解释了这些部分中使用的符号约定和缩写。
3.1.1 Instruction Format
下面是本章中每条指令描述使用的格式示例。下面的标题介绍了这个例子。下表提供了一个示例汇总表。
CMC—Complement Carry Flag [这是一个例子]
CMC—取反进位标志。它是 x86 指令集中的一条指令,主要功能是对进位标志(CF, Carry Flag)进行取反操作
3.1.1.1Opcode Column in the Instruction Summary Table (Instructions without VEX Prefix)指令汇总表操作码列(不带VEX前缀的指令)
上表中的“Opcode”列显示了为每种形式的指令生成的目标代码。在可能的情况下,代码以十六进制字节的形式给出,其顺序与它们在内存中的顺序相同。对于除了十六进制字节以外的其他条目的定义如下:
-
NP -指示指令不允许使用66/F2/F3前缀(除了那些已经成为指令操作码一部分的前缀)。这样的使用要么会导致无效操作码异常(#UD),要么会导致对不同指令进行编码。
-
NFx -指示指令不允许使用F2/F3前缀(除了那些已经成为指令操作码一部分的前缀)。这样的使用要么会导致无效操作码异常(#UD),要么会导致对不同指令进行编码。
-
REX.W-指示使用一个 REX 前缀,该前缀影响操作数的大小或指令的语义。REX 前缀与其他可选或强制的指令前缀的顺序在第 2 章中讨论。需要注意的是,提升传统指令到 64 位行为的 REX 前缀在操作码列中没有明确列出。
-
/digit-0 到 7 之间的数字表示指令的 ModR/M 字节仅使用 r/m(寄存器或内存)操作数。reg 字段包含该数字,用于扩展指令的操作码。
-
/r-指示指令的 ModR/M 字节包含一个寄存器操作数和一个 r/m 操作数。
-
cb, cw, cd, cp, co, ct-这些符号表示在操作码后跟随的值的字节大小:
cb
:1 字节cw
:2 字节cd
:4 字节cp
:6 字节co
:8 字节ct
:10 字节 这些值用于指定代码偏移量,并可能为代码段寄存器提供新值。
-
ib, iw, id, io-这些符号表示紧接在操作码、ModR/M 字节或比例-索引字节后面的立即操作数的字节大小:
ib
:1 字节iw
:2 字节id
:4 字节io
:8 字节 操作码决定了操作数是否为带符号值。所有字、双字和四字的低位字节优先排列。
-
+rb, +rw, +rd, +ro-指示操作码字节的低 3 位用于编码寄存器操作数,而不使用 modR/M 字节。指令列出了对应的操作码字节的十六进制值,其中低 3 位为 000b。
- 在非 64 位模式下,寄存器代码(0 到 7)会被加到十六进制操作码字节的值上。
- 在 64 位模式下,指示 REX.b 的 4 位字段和操作码的 [2:0] 字段编码指令的寄存器操作数。“+ro” 仅适用于 64 位模式。有关代码的更多信息,请参见Table 3-1。
-
+i-在浮点指令中,当一个操作数是来自 FPU 寄存器栈的 ST(i) 时使用的数字。数字 i(范围为 0 到 7)会被加到加号左侧给出的十六进制字节上,以形成一个单一的操作码字节。
3.1.1.2 Opcode Column in the Instruction Summary Table (Instructions with VEX prefix)带有VEX前缀的指令
省略
3.1.1.3 Instruction Column in the Opcode Summary Table
“Instruction”列给出了在ASM386程序中出现的指令语句的语法。
下面是指令语句中用于表示操作数的符号列表:
-
**rel8:**表示一个相对地址,范围从指令结束前 128 字节到指令结束后 127 字节之间。
-
rel16, rel32:
rel16
:指在与指令同一代码段内的相对地址,适用于操作数大小为 16 位的指令。rel32
:指在与指令同一代码段内的相对地址,适用于操作数大小为 32 位的指令。
-
ptr16:16, ptr16:32 :表示远指针,通常指向与指令不同的代码段.16:16表示指针的值由两部分组成。冒号左边的值是一个16位选择子或用于代码段寄存器的值。右侧的值对应目标段内的偏移量。当指令的操作数大小属性为16位时,使用ptr16:16符号;当操作数大小属性为32位时使用ptr16:32符号
-
**r8:**表示一个 byte通用寄存器,包括 AL, CL, DL, BL, AH, CH, DH, BH, BPL, SPL, DIL 和 SIL,或在 64 位模式下使用 REX.R 时可用的字节寄存器(R8B - R15B)。
-
r16 :表示一个word 通用寄存器,包括 AX, CX, DX, BX, SP, BP, SI, DI,或在 64 位模式下使用 REX.R 时可用的字寄存器(R8-R15)
-
r32:表示一个 doubleword 通用寄存器,包括 EAX, ECX, EDX, EBX, ESP, EBP, ESI, EDI,或在 64 位模式下使用 REX.R 时可用的双字寄存器(R8D - R15D)。
-
**r64:**表示一个 quadword 通用寄存器,包括 RAX, RBX, RCX, RDX, RDI, RSI, RBP, RSP, R8–R15。这些寄存器在 64 位模式下可用,并使用 REX.R。
-
imm8:表示一个立即字节值,范围为 -128 到 +127(包含)。当与字或双字操作数结合时,立即值会被符号扩展以形成字或双字。字的高字节用立即值的最高位填充
-
imm16:表示一个立即字值,适用于操作数大小为 16 位的指令,范围为 -32,768 到 +32,767(包含)。
-
imm32表示一个立即双字值,适用于操作数大小为 32 位的指令,范围为 -2,147,483,648 到 +2,147,483,647(包含)。
-
imm64表示一个立即四字值,适用于操作数大小为 64 位的指令,范围为 -9,223,372,036,854,775,808 到 +9,223,372,036,854,775,807(包含)。
-
r/m8表示一个字节操作数,可以是一个字节通用寄存器的内容(如 AL, CL, DL 等)或内存中的一个字节。在 64 位模式下,字节寄存器 R8B - R15B 在使用 REX.R 时可用。
-
r/m16:表示一个16位操作数,可以是16位通用寄存器或内存操作数。16位通用寄存器包括 AX、CX、DX、BX、SP、BP、SI 和 DI。在64位模式下,通过使用 REX.R 前缀,还可以访问 R8W 到 R15W 这些16位寄存器。
-
mm/m64:表示一个 MMX 寄存器或64位内存操作数。MMX 寄存器包括 MM0 到 MM7。内存内容是通过有效地址计算得出的。
-
xmm:表示一个 XMM 寄存器。XMM寄存器是128位的,XMM0 到 XMM7;在64位模式下,使用 REX.R 前缀还可以访问 XMM8 到 XMM15。
-
xmm/m32:表示一个 XMM 寄存器或32位内存操作数。128位的 XMM 寄存器包括 XMM0 到 XMM7;在64位模式下,XMM8 到 XMM15 也可用。内存内容通过有效地址计算得出。
-
ymm:表示一个 YMM 寄存器。这是256位的寄存器,包括 YMM0 到 YMM7;在64位模式下,YMM8 到 YMM15 也可用。
-
zmm/m512:表示一个 ZMM 寄存器或512位内存操作数。ZMM寄存器用于处理更大数据的操作,ZMM0到ZMM7,以及在64位模式下使用 ZMM8 到 ZMM15。
-
{k1}{z}:表示一个掩码寄存器 (mask register) 用于指令的写掩码。64位掩码寄存器包括 k1 到 k7。掩码通过 EVEX 前缀指定。掩码可以以合并的方式使用,即保持被掩盖的元素的旧值,或者以零填充的方式 (zeroing masking) 来掩盖元素。
-
imm8、imm16、imm32 和 imm64:这些是立即数操作数,表示固定长度的数据直接跟随在指令后。它们分别代表 8位、16位、32位和64位的立即数。
-
moffs8、moffs16、moffs32 和 moffs64:这些表示简单的内存偏移量操作数,通常用于 MOV 指令,实际地址通过段基址加上简单的偏移量给出。
-
Sreg:表示段寄存器。段寄存器的位分配如下:ES=0,CS=1,SS=2,DS=3,FS=4,GS=5。
-
r/m32:表示一个32位通用寄存器或内存操作数,用于指令的操作数大小属性为32位的情况。32位通用寄存器包括 EAX、ECX、EDX、EBX、ESP、EBP、ESI、EDI。在64位模式下,通过使用 REX.R 前缀,还可以访问 R8D 到 R15D 这些32位寄存器。
-
r/m64:表示一个64位通用寄存器或内存操作数,用于指令的操作数大小属性为64位的情况,且使用 REX.W 前缀时可用。64位通用寄存器包括 RAX、RBX、RCX、RDX、RDI、RSI、RBP、RSP,以及 R8 到 R15,这些寄存器仅在64位模式下可用。内存内容通过有效地址计算得出。
-
reg:表示一个通用寄存器,用于指令操作数的宽度对指令操作语义没有影响的情况。寄存器可以是16位、32位或64位(分别为 r16、r32 或 r64)
-
m:表示一个内存操作数,可能是16位、32位或64位。
-
m8:表示一个内存中的8位操作数,通常由变量或数组名称表示,但实际上是由 DS:(E)SI 或 ES:(E)DI 寄存器指向的。在64位模式下,由 RSI 或 RDI 寄存器指向。
-
m16:表示一个内存中的16位操作数,通常由变量或数组名称表示,但实际上是由 DS:(E)SI 或 ES:(E)DI 寄存器指向。此符号只用于字符串指令。
-
m32:表示一个32位内存操作数。内存内容由有效地址计算得出。
-
m64:表示一个64位内存操作数。
-
m128:表示一个128位内存操作数(双四字内存操作数)。
-
m16:16、m16:32 & m16:64:表示包含一个由两个数字组成的远指针的内存操作数。冒号左边的数字表示段选择符,右边的数字表示段内偏移量。
-
m16&32、m16&16、m32&32、m16&64:表示由一对数据项组成的内存操作数,左侧和右侧的数字指示它们的大小。所有的内存寻址模式都可用。m16&16 和 m32&32 操作数用于 BOUND 指令,提供包含数组索引上下限的操作数。m16&32 操作数用于 LIDT 和 LGDT 指令,提供用于加载对应 GDTR 和 IDTR 寄存器的限制字段和基地址字段的操作数。在64位模式下,m16&64 操作数用于 LIDT 和 LGDT 指令,提供一个用于加载限制字段的16位数字和用于加载基字段的64位数字。
-
m80bcd:表示内存中的80位二进制编码十进制(BCD)操作数。
-
moffs8、moffs16、moffs32、moffs64:表示一些 MOV 指令使用的简单内存变量(内存偏移量)。实际地址是通过段基址加上简单偏移量计算得出的。moffs 后的数字表示其大小,由指令的地址大小属性决定。
-
m32fp、m64fp、m80fp:表示内存中的单精度、双精度和扩展精度(分别为32位、64位和80位)的浮点数操作数。这些符号表示用于 x87 FPU 浮点指令的浮点数操作数。
-
m16int、m32int、m64int:表示内存中的16位、32位和64位整数操作数。它们用于 x87 FPU 的整数指令。
-
ST 或 ST(0):表示 FPU 寄存器堆栈的顶部元素。
-
ST(i):表示 FPU 寄存器堆栈的第 i 个元素(i 为 0 到 7)。
-
mm:表示一个 MMX 寄存器,64位 MMX 寄存器包括 MM0 到 MM7。
-
mm/m32:表示 MMX 寄存器的低32位或32位内存操作数。MMX 寄存器为 64 位,包含 MM0 到 MM7。内存内容通过有效地址计算得出。
在指令编码中,MODRM 字节的表示方式会根据其作用不同而有所变化。MODRM 字节包含 3 个字段:2 位的 MODRM.MOD 字段、3 位的 MODRM.REG 字段和 3 位的 MODRM.RM 字段。当一条指令对 MODRM 字节的所有位都有固定值时,该字节的 2 个十六进制值将显示在指令描述页面的操作码后面的编码框中。如果 MODRM 字节的某些字段必须包含固定值,这些值将按以下方式指定:
- 如果 MODRM.MOD 字段必须是
0b11
,而 MODRM.REG 字段 和 MODRM.RM 字段 没有约束,这种情况表示为 11:rrr- 其中rrr表示MODRM.REG 字段 的 3 位, bbb表示 MODMR.RM 字段的 3 位。
- 如果 MODRM.MOD 字段 不能是
0b11
,即它必须是0b00
、0b01
或0b10
之一,则表示为 !(11)。 - 如果 MODRM.REG 字段 需要特定的值,例如
0b101
,则表示为 mm:101
3.1.1.4 Operand Encoding Column in the Instruction Summary Table指令汇总表中的操作数编码列
在指令汇总表的标题中,“operand encoding”一栏缩写为 Op/En。每条汇编指令的操作数编码信息通过一个字母与操作数编码定义表中的一行对应,用户可以通过此字母查阅表中的相应条目。每条指令的参考页面中,操作数编码表会列出每个指令操作数(根据指令列中的指令语法和操作数顺序)与 ModRM 字节、VEX.vvvv 字段或其他操作数编码位置的对应关系。
对于 EVEX 编码的指令,它们采用压缩的 disp8*N 编码方式,其中 N 是根据 Tupletypes(元组类型)在 表 2-34 和 表 2-35 中定义的。指令的元组类型在适用时会在操作数编码定义表中列出。
[!NOTE]
在Instruction Summary Table(指令汇总表)之后紧接的encoding definition table (编码定义表)中,Op/En 列中的字母仅适用于该表。
- 在encoding definition table (编码定义表)中,字母 “r” 放在一对括号中,表示处理器会读取该操作数的内容。
- 字母 “w” 放在一对括号中,表示处理器会更新该操作数的内容。
3.1.1.5 64/32-bit Mode Column in the Instruction Summary Table指令汇总表中的64/32位模式列
"64/32位模式"列表示以下两种模式中是否支持该操作码序列: (a) 64位模式 (b) 兼容模式以及与 CPUID 功能标志关联的特定指令扩展相关的其他 IA-32 模式
64位模式支持在‘斜杠’的左边,并具有以下表示法:
- V -支持。
- I -不支持。
- N.E. — 表示指令语法在64位模式下不可编码(它可能在其他模式中是有效指令序列的一部分)。
- N.P. — 表示REX前缀在64位模式下不影响传统指令。
- N.I. — 表示该操作码在64位模式下被视为新指令。
- N.S. — 表示指令语法在64位模式下需要地址覆盖前缀且不被支持。在64位模式下使用地址覆盖前缀可能会导致与特定处理器型号相关的执行行为。
3.1.1.6 CPUID Support Column in the Instruction Summary Table指令汇总表中CPUID Support列
第四列包含缩写的CPUID特性标志(例如,CPUID.01H.ECX 或 CPUID.01H.EDX 中的相应位,用于指示SSE、SSE2、SSE3、SSSE3、SSE4.1、SSE4.2、AESNI、PCLMULQDQ、AVX、RDRAND等指令集的支持)。如果对应的标志位是“0”,那么指令执行时将会引发无效指令异常(#UD)。
在处理器架构中,特定指令的支持是由CPUID指令返回的信息决定的。CPUID指令能够报告处理器支持的特性,这些特性用多个寄存器中的标志位(flag bits)表示。指令汇总表的第四列列出了这些特性标志,表示处理器是否支持某条特定指令。
- CPUID.01H.ECX 和 CPUID.01H.EDX 是CPUID指令的返回结果,它们表示不同指令集扩展(如SSE、SSE2、AVX等)的支持情况。
- 当处理器通过CPUID指令返回的特性标志位(如ECX或EDX中的位)为1时,意味着该处理器支持相应的指令集扩展。反之,如果标志位为0,则处理器不支持该指令集。
- 如果某条指令依赖于一个特定的指令集扩展(如SSE或AVX),而处理器的CPUID特性标志中该位是0(表示不支持该扩展),那么在执行这条指令时,处理器会产生“无效指令异常” (#UD) 并停止执行。
简单来说,这列标志帮助开发者判断在不同处理器上是否可以安全地使用某些扩展指令,并在不支持的情况下采取替代方案。
3.1.1.7 Description Column in the Instruction Summary Table指令汇总表“描述”列
"Description”列简要解释了指令的不同形式。
3.1.1.8 Description Section Description部分
每条指令都有若干信息部分进行描述。“描述”部分更详细地说明了指令的目的和所需操作数。
在描述部分中可能使用的术语总结:
- 传统 SSE:指 SSE、SSE2、SSE3、SSSE3、SSE4、AESNI、PCLMULQDQ,以及任何未来的指令集,涉及 XMM 寄存器并且未使用 VEX 前缀进行编码。
- VEX.vvvv:指定源或目的寄存器的 VEX 位字段(以 1 的补码形式)。
- rm_field:ModR/M 的 r/m 字段和任何 REX.B 的简写。
- reg_field:ModR/M 的 reg 字段和任何 REX.R 的简写。
3.1.1.9 Operation Section Operation部分
“Operation” 部分包含了对指令的算法描述(通常以伪代码形式写成)。算法由以下元素组成:
-
注释用符号对“(” 和 “)” 包围。
-
复合语句用关键字包围,例如:IF、THEN、ELSE 和 FI 表示 if 语句;DO 和 OD 表示 do 语句;或 CASE… OF 表示 case 语句。
-
寄存器名称隐含寄存器的内容。用方括号括起来的寄存器名称则表示该寄存器所包含地址的内容。例如,ES:[DI] 表示在寄存器 DI 中的 ES 段相对地址所指向位置的内容。[SI] 表示寄存器 SI 中所包含的地址在 SI 寄存器默认段(DS)或被覆盖段相对的内容。
-
在通用寄存器名称中的 “E” 周围加上括号,例如 (E)SI,表示如果地址大小属性为 16,则从 SI 寄存器读取偏移量;如果地址大小属性为 32,则从 ESI 寄存器读取偏移量。在 64 位寄存器定义下,例如 ®SI,括号围绕 “R” 表示如果地址大小属性为 64,则从 64 位 RSI 寄存器读取偏移量。
-
方括号用于表示内存操作数,表示内存位置的内容是一个段相对偏移量。例如, [SRC] 表示源操作数的内容是一个段相对偏移量。
-
A := B 表示将 B 的值赋给 A。
-
符号 =、≠、>、<、≥ 和 ≤ 是用于比较两个值的关系运算符,分别表示相等、不相等、大于、小于、大于等于和小于等于。关系表达式例如 A = B 为 TRUE 当 A 的值等于 B;否则为 FALSE。
-
表达式 “« COUNT” 和 “» COUNT” 表示目标操作数应按 COUNT 操作数指示的位数向左或向右移动。
以下标识符在算法描述中使用:
这一部分省略,对于本工程来说太大…
3.1.1.11 Flags Affected Section 受影响标志部分
“Flags Affected” 部分列出了受指令影响的 EFLAGS 寄存器中的标志。当一个标志被清除时,其值为 0;当一个标志被设置时,其值为 1。算术和逻辑指令通常以统一的方式为状态标志赋值(详见英特尔® 64 和 IA-32 架构软件开发者手册第一卷附录 A “EFLAGS 交叉引用”)。非常规赋值将在“Operation” 部分中描述。标志的值如果列为未定义,则可能会被指令以不确定的方式更改。未列出的标志在指令执行后保持不变。
3.1.1.12 FPU Flags Affected Section
浮点指令有一个“受影响的FPU标志”部分,该部分描述了每个指令如何影响FPU状态字的四个条件码标志。
3.1.1.13 Protected Mode Exceptions Section 保护模式异常部分
“Protected Mode Exceptions” 部分列出了在保护模式下执行指令时可能发生的异常及其原因。每个异常都有一个助记符,由一个井号 (#) 后跟两个字母和一个可选的错误代码(在括号中)组成。例如,#GP(0) 表示一个具有错误代码 0 的通用保护异常。表 3-4 将每个两个字母的助记符与相应的异常向量和名称关联起来。有关异常的详细描述,请参见英特尔® 64 和 IA-32 架构软件开发者手册第三卷 A,章节 6 “过程调用、中断和异常”。应用程序开发人员应查阅与其操作系统一起提供的文档,以确定异常发生时采取的措施。
[!NOTE]
- 适用于保护模式、兼容模式和64位模式。
- 在real-address模式下,向量13是段溢出异常。
3.1.1.14 Real-Address Mode Exceptions Section 实地址模式部分
3.1.1.14 Real-Address Mode Exceptions Section 虚拟8086模式部分
3.1.1.16 Floating-Point Exceptions Section 浮点
“Floating-Point Exceptions” 部分列出了在执行 x87 FPU 浮点指令时可能发生的异常。这些异常条件都会导致生成浮点错误异常 (#MF,异常 16)。表 3-5 将一个或两个字母的助记符与相应的异常名称关联起来。有关这些异常的详细描述,请参见英特尔® 64 和 IA-32 架构软件开发者手册第一卷第八章“浮点异常条件”。
3.1.1.17 SIMD Floating-Point Exceptions Section
“SIMD Floating-Point Exceptions” 部分列出了在执行 SSE/SSE2/SSE3 浮点指令时可能发生的异常。这些异常条件都会导致生成 SIMD 浮点错误异常 (#XM,异常 19)。表 3-6 将一个字母的助记符与相应的异常名称关联起来。有关这些异常的详细描述,请参见英特尔® 64 和 IA-32 架构软件开发者手册第一卷第十一章“ SSE 和 SSE2 异常”。
3.1.1.18 Compatibility Mode Exceptions Section 兼容模式异常部分
列出了在兼容模式下出现的异常。
3.1.1.19 64-Bit Mode Exceptions Section 64位模式异常部分
列出64位模式下发生的异常。
3.2 INTEL® AMX CONSIDERATIONS
英特尔的 AMX(Advanced Matrix Extensions)指令集是针对高性能计算(HPC)和机器学习等应用而设计的,主要用于加速矩阵运算。故省略
Appendix A Opcode Map 附录 A Opcode映射表
使用本章中的Opcode映射 表来解释 IA-32 和 Intel 64 架构的目标代码。指令分为以下几类编码组:
- 1 字节、2 字节和 3 字节Opcode编码用于编码整数、系统、MMX 技术、SSE/SSE2/SSE3/SSSE3/SSE4 和 VMX 指令。这些指令的映射在 Table A-2 至 Table A-2 中给出。
- 转义操作码(格式为:ESC 字符,操作码,ModR/M 字节)用于浮点指令。这些指令的映射在 Table A-7 至 Table A-22. 中提供。
[!NOTE]
Opcode映射 表中的所有空白都是保留的,不能使用。不要依赖于未定义或空白操作码的操作。
A.1 USING OPCODE TABLES 使用opcode表
本附录中的表列出了指令的操作码(包括所需的指令前缀、与之关联的 ModR/M 字节中的操作码扩展)。表中的空单元格表示保留或未定义的操作码。标记为“Reserved-NOP”的单元格也被保留,但在某些处理器上可能表现为 NOP。软件不应使用对应于空单元格或标记为“Reserved-NOP”的单元格的操作码,也不应依赖于这些操作码的当前行为。
操作码映射表按操作码字节的高 4 位和低 4 位的十六进制值进行组织。对于 1 字节编码(表 A-2),使用操作码的高四位索引操作码表的一行;使用低四位索引表的一列。对于以 0FH 开头的 2 字节操作码(表 A-3),跳过任何指令前缀和 0FH 字节(0FH 前面可以是 66H、F2H 或 F3H),使用下一个操作码字节的高四位和低四位来索引表的行和列。类似地,对于以 0F38H 或 0F3AH 开头的 3 字节操作码(表 A-4),跳过任何指令前缀和 0F38H 或 0F3AH,并使用第三个操作码字节的高四位和低四位来索引表的行和列。有关一字节、两字节和三字节操作码的查找示例,请参见 A.2.4 节。
当 ModR/M 字节提供操作码扩展时,此信息会限定操作码的执行。有关 ModR/M 字节中的操作码扩展如何修改表 A-2 和表 A-3 中的操作码映射的信息,请参见 A.4 节。浮点指令的转义(ESC)操作码表在每页的顶部标识了操作码的八个高位。请参见 A.5 节。如果附带的 ModR/M 字节在 00H-BFH 范围内,则 ModR/M 的位 3-5(每页第三个表的顶部行)以及 ModR/M 的 reg 位共同决定操作码。在 00H-BFH 范围之外的 ModR/M 字节由该节每页底部的两个表进行映射。
A.2 KEY TO ABBREVIATIONS 缩写键
操作数通过形式为 Zz 的两个字符代码进行标识。第一个字符是大写字母,指定寻址方法;第二个字符是小写字母,指定操作数的类型。
A.2.1 寻址方法代码
以下缩写用于记录寻址方法:
- A 直接地址:指令没有 ModR/M 字节;操作数的地址编码在指令中。不能使用基址寄存器、索引寄存器或缩放因子(例如,远跳转(far JMP))。
- B VEX 前缀的 VEX.vvvv 字段选择一个通用寄存器。
- C ModR/M 字节的 reg 字段选择一个控制寄存器(例如,MOV (0F20, 0F22))。
- D ModR/M 字节的 reg 字段选择一个调试寄存器(例如,MOV (0F21, 0F23))。
- E ModR/M 字节跟随在 opcode 之后并指定操作数。操作数可以是一个通用寄存器或一个内存地址。如果是内存地址,则该地址由一个段寄存器和以下任意值计算得出:基址寄存器、索引寄存器、缩放因子、位移。
- F EFLAGS/RFLAGS 寄存器。
- G ModR/M 字节的 reg 字段选择一个通用寄存器(例如,AX (000))。
- H VEX 前缀的 VEX.vvvv 字段选择一个 128 位 XMM 寄存器或一个 256 位 YMM 寄存器,具体取决于操作数类型。对于传统的 SSE 编码,此操作数不存在,会将指令更改为破坏性形式。
- I 立即数:操作数值编码在指令的后续字节中。
- J 指令包含一个相对偏移量,该偏移量将被加到指令指针寄存器(例如,JMP (0E9),LOOP)。
- L 8 位立即数的高 4 位选择一个 128 位 XMM 寄存器或一个 256 位 YMM 寄存器,具体取决于操作数类型(在 32 位模式下忽略最高有效位)。
- M ModR/M 字节可能仅引用内存(例如,BOUND、LES、LDS、LSS、LFS、LGS、CMPXCHG8B)。
- N ModR/M 字节的 R/M 字段选择一个打包的四字(packed-quadword)MMX 技术寄存器。
- O 指令没有 ModR/M 字节。操作数的偏移量在指令中编码为字或双字(取决于地址大小属性)。不能使用基址寄存器、索引寄存器或缩放因子(例如,MOV (A0–A3))。
- P ModR/M 字节的 reg 字段选择一个打包的四字 MMX 技术寄存器。
- Q ModR/M 字节跟随在 opcode 之后并指定操作数。操作数可以是一个 MMX 技术寄存器或一个内存地址。如果是内存地址,则该地址由一个段寄存器和以下任意值计算得出:基址寄存器、索引寄存器、缩放因子和位移。
- R ModR/M 字节的 R/M 字段可能仅引用一个通用寄存器(例如,MOV (0F20-0F23))。
- S ModR/M 字节的 reg 字段选择一个段寄存器(例如,MOV (8C,8E))。
- U ModR/M 字节的 R/M 字段选择一个 128 位 XMM 寄存器或一个 256 位 YMM 寄存器,具体取决于操作数类型。
- V ModR/M 字节的 reg 字段选择一个 128 位 XMM 寄存器或一个 256 位 YMM 寄存器,具体取决于操作数类型。
- W ModR/M 字节跟随在 opcode 之后并指定操作数。操作数可以是一个 128 位 XMM 寄存器、一个 256 位 YMM 寄存器(由操作数类型决定),或一个内存地址。如果是内存地址,则该地址由一个段寄存器和以下任意值计算得出:基址寄存器、索引寄存器、缩放因子和位移。
- X 由 DS:rSI 寄存器对寻址的内存(例如,MOVS、CMPS、OUTS 或 LODS)。
- Y 由 ES:rDI 寄存器对寻址的内存(例如,MOVS、CMPS、INS、STOS 或 SCAS)。
A.2.2 Codes for Operand Type 操作数类型
以下缩写用于文档中操作数类型的说明:
-
a 两个存储器中的单字操作数或两个存储器中的双字操作数,取决于操作数大小属性(仅用于 BOUND 指令)。
-
b Byte,无论操作数大小属性如何。
-
c Byte or word,,取决于操作数大小属性。
-
d Doubleword,无论操作数大小属性如何。
-
dq Double-quadword,无论操作数大小属性如何。
-
p 32 位、48 位或 80 位指针,取决于操作数大小属性。
-
pd 128 位或 256 位打包双精度浮点数据。
-
pi Quadword, MMX 技术寄存器(例如:mm0)。
-
ps 128 位或 256 位打包单精度浮点数据。
-
q Quadword,,无论操作数大小属性如何。
-
qq 四个Quadword(256 位),无论操作数大小属性如何。
-
s 6-byte or 10-byte 伪描述符。
-
sd 128 位双精度浮点数据的标量元素。
-
ss 128 位单精度浮点数据的标量元素。
-
si doubleword 整型寄存器(例如:eax)。
-
v Word, doubleword or quadword (在 64 位模式下),取决于操作数大小属性。
-
w Word,无论操作数大小属性如何。
-
x dq 或 qq,基于操作数大小属性。
-
y Doubleword or quadword (在 64 位模式下),取决于操作数大小属性。
-
z 16 位操作数大小为 Word ,32 位或 64 位操作数大小为 doubleword 。
A.2.3 Register Codes
当一个 opcode 需要特定的寄存器作为操作数时,该寄存器通过名称进行标识(例如,AX、CL 或 ESI)。这个名称指示了寄存器的宽度是 64 位、32 位、16 位,还是 8 位。
寄存器标识符的形式为 eXX 或 rXX,用于表示寄存器的宽度取决于操作数大小属性。eXX 用于可能是 16 位或 32 位的大小;rXX 用于可能是 16 位、32 位或 64 位的大小。例如:eAX 表示在操作数大小属性为 16 时使用 AX 寄存器,而在操作数大小属性为 32 时使用 EAX 寄存器。rAX 可以表示 AX、EAX 或 RAX。
当 REX.B 位被用来修改 opcode 中 reg 字段指定的寄存器时,通过在寄存器名称后添加 “/x” 来指示这种附加可能性。例如,rCX/r9 用于指示该寄存器可以是 rCX 或 r9。请注意,这种情况下 r9 的大小由操作数大小属性决定(与 rCX 相同)。
A.2.4 Opcode Look-up Examples for One, Two, and Three-Byte Opcodes
本节提供一些示例,演示如何使用操作码映射。
A.2.4.1 One-Byte Opcode Instructions 单字节操作码指令
1 字节 opcode 的映射在**Table A-2.**中展示。1 字节 opcode 的映射按行(十六进制值的最低有效 4 位)和列(十六进制值的最高有效 4 位)排列。表中的每一项列出以下类型的 opcode:
- 使用第 A.2 节中列出的符号的指令助记符和操作数类型
- 用作指令前缀的 opcode
对于每个与指令对应的 opcode 映射条目,解释主 opcode 后面的字节的规则分为以下几种情况:
-
需要一个 ModR/M 字节,并根据第 A.1 节和英特尔® 64 及 IA-32 架构软件开发者手册第 2A 卷的“指令格式”中列出的缩写进行解释。操作数类型根据第 A.2 节中列出的符号进行列示。
-
需要一个 ModR/M 字节,并且在 ModR/M 字节的 reg 字段中包含一个 opcode 扩展。解释 ModR/M 字节时请使用Table A-6。
-
ModR/M 字节的使用是保留或未定义的。这适用于表示指令前缀的条目或不带操作数且使用 ModR/M 的指令条目(例如:60H, PUSHA; 06H, PUSH ES)。
Example A-1. Look-up Example for 1-Byte Opcodes
对于 ADD 指令的 opcode 030500000000H 的解释如下:
- 第一位数字 (0) 表示表的行,而 第二位数字 (3) 表示表的列。这定位到一个具有两个操作数的 ADD 指令的 opcode。
- 第一个操作数(类型 Gv)表示一个通用寄存器,大小为字(word)或双字(doubleword),具体取决于操作数大小属性。第二个操作数(类型 Ev)指示后面跟随一个 ModR/M 字节,该字节指定操作数是一个字或双字的通用寄存器,还是一个内存地址。
- 此指令的 ModR/M 字节为 05H,指示后面跟随一个 32 位位移(00000000H)。ModR/M 字节的 reg/opcode 部分(位 3-5)为 000,表示 EAX 寄存器。
因此,这条指令的格式为 ADD EAX, mem_op
,其中 mem_op
的偏移量为 00000000H。
一些 1 字节和 2 字节的 opcodes 指向组号(在 opcode 映射表中的阴影条目)。组号表示指令使用 ModR/M 字节中的 reg/opcode 位作为 opcode 扩展(详见 A.4 节)。
A.2.4.2 Two-Byte Opcode Instructions 双字节Opcode指令
在Table A-3 中显示的两字节 opcode 映射包括长度为两字节或三字节的主 opcode。长度为两字节的主 opcode 以转义 opcode 0FH 开头。第二个 opcode 字节的高四位和低四位用于在表 A-3 中索引特定的行和列。
长度为三字节的两字节 opcode 以强制前缀 (66H, F2H, 或 F3H) 和转义 opcode (0FH) 开头。第三个字节的高四位和低四位用于在Table A-3中索引特定的行和列(除非第二个 opcode 字节是三字节转义 opcode 38H 或 3AH;在这种情况下,请参阅 A.2.4.3 节)。
对于 opcode 映射中的每一条目,解释主 opcode 后面字节的规则属于以下几种情况之一:
- 需要 ModR/M 字节,并根据 A.1 节和《英特尔 64 和 IA-32 架构软件开发者手册》第 2A 卷的“指令格式”中列出的缩写进行解释。操作数类型按 A.2 节中列出的标记列出。
- 需要 ModR/M 字节,并且 ModR/M 字节中的 reg 字段包含一个 opcode 扩展。在解释 ModR/M 字节时,请使用表 Table A-6。
- ModR/M 字节的使用是保留或未定义的。这适用于表示没有操作数的指令的条目,这些指令是通过 ModR/M 编码的(例如:0F77H, EMMS)。
Example A-2. Look-up Example for 2-Byte Opcodes
查找 opcode 0FA4050000000003H 以获取 SHLD 指令,使用表 A-3:
- opcode 位于行 A,列 4。该位置指示一个 SHLD 指令,操作数为 Ev, Gv, 和 Ib。操作数的解释如下:
- Ev: ModR/M 字节跟随在 opcode 之后,用于指定字(word)或双字(doubleword)操作数。
- Gv: ModR/M 字节中的 reg 字段选择一个通用寄存器。
- Ib: 立即数数据编码在指令的后续字节中。
- 第三个字节是 ModR/M 字节 (05H)。Mod 和 opcode/reg 字段的 ModR/M 指示使用一个 32 位的偏移量来定位第一个操作数在内存中的位置,第二个操作数是 EAX。
- opcode 的下一部分是目标内存操作数的 32 位偏移量 (00000000H)。最后一个字节存储立即字节,提供了移位的计数 (03H)。
因此,指令的完整解释为:从内存位置 00000000H 中读取数据,并将其与寄存器 EAX 中的内容进行左移,移位计数为 3。
A.2.4.3 Three-Byte Opcode Instructions 三字节操作码指令
在 Table A-4 和 Table A-5 中显示的三字节 opcode 映射包括长度为 3 或 4 字节的主要 opcode。长度为 3 字节的主要 opcode 以两个转义字节 0F38H 或 0F3AH 开头。第三个 opcode 字节的高四位和低四位用于在 Table A-4 和 Table A-5 中索引特定的行和列。长度为 4 字节的三字节 opcode 以一个强制前缀 (66H, F2H, 或 F3H) 和两个转义字节 (0F38H 或 0F3AH) 开头。第四个字节的高四位和低四位用于在 Table A-4 和 Table A-5 中索引特定的行和列。
对于 opcode 映射中的每个条目,解释主要 opcode 后面字节的规则归入以下情况:
- 需要 ModR/M 字节,并按照 A.1 和英特尔® 64 及 IA-32 架构软件开发手册第 2A 卷“指令格式”中列出的缩写进行解释。操作数类型根据 A.2 节中列出的符号进行说明。
Example A-3. Look-up Example for 3-Byte Opcodes
使用Table A-5 查找 opcode 660F3A0FC108H 对应的 PALIGNR 指令。
- 66H 是前缀,0F3AH 表示使用表 A-5。该 opcode 位于第 0 行、第 F 列,指示这是一个 PALIGNR 指令,操作数为 Vdq, Wdq, 和 Ib。解释操作数如下:
- Vdq: ModR/M 字节中的 reg 字段选择一个 128 位的 XMM 寄存器。
- Wdq: ModR/M 字节中的 R/M 字段选择一个 128 位的 XMM 寄存器或内存位置。
- Ib: 立即数数据编码在指令的后续字节中。
- 下一个字节是 ModR/M 字节 (C1H)。reg 字段表明第一个操作数是 XMM0。mod 字段显示 R/M 字段指定了一个寄存器,而 R/M 字段指示第二个操作数为 XMM1。
- 最后一个字节是立即数字节 (08H)。
- 通过这种拆解,可以确认该 opcode 代表的指令为:PALIGNR XMM0, XMM1, 8。
A.2.4.4 VEX Prefix Instructions
省略
A.2.5 Superscripts Utilized in Opcode Tables 操作码表中使用的上标
表 A-1 包含特定编码的注释。这些注释在以下 opcode 表中通过上标表示。灰色单元格表示指令分组。
上标符号 | 符号的意义 |
---|---|
1A | ModR/M字节的第5位、第4位和第3位用作操作码扩展(参见章节A.4,“单字节和双字节操作码的操作码扩展”)。 |
1B | 当故意试图生成无效操作码异常(#UD)时,使用0F0B操作码(UD2指令)、0FB9H操作码(UD1指令)或0FFFH操作码(UD0指令)。 |
1C | 有些指令使用相同的双字节操作码。如果指令有变化,或者操作码代表不同的指令,ModR/M字节将用于区分指令。解码指令所需的ModR/M字节值见Table A-6。 |
i64 | 该指令在64位模式下无效或不可编码。在64位模式下,40到4F(单字节INC和DEC)是REX前缀组合(使用FE/FF Grp 4和5表示INC和DEC)。 |
o64 | 指令仅在64位模式下可用 |
d64 | 在64位模式下,指令默认为64位操作数大小,不能对32位操作数大小进行编码。 |
f64 | 在64位模式下,操作数大小强制为64位操作数大小(在64位模式下,此指令忽略更改操作数大小的前缀)。 |
v | 只存在VEX形式。没有遗留的SSE形式的指令。对于整数GPR指令,它意味着需要VEX前缀。 |
v1 | 当不能从数据大小推断时,只存在VEX128和SSE表单(不存在VEX256)。 |
A.3 ONE, TWO, AND THREE-BYTE OPCODE MAPS 1、2和3字节的操作码映射表
请参见表A-2至表A-5。表格是多页展示。具有顺序关系的行和列被放置在相对的页面上,使查找任务更容易。请注意,表格脚注并没有在每页上显示。每个表格的脚注在表格的最后一页。
A.4 OPCODE EXTENSIONS FOR ONE-BYTE AND TWO-BYTE OPCODES 单字节和双字节操作码的操作码扩展
一些1字节和2字节的操作码使用ModR/M字节(图A-1中的nnn字段)的3-5位作为操作码的扩展。
具有 opcode 扩展的 opcodes 在中列出,并按组号组织。组号(第 2 列,范围从 1 到 16)提供了表条目的入口。每条指令的 r/m 字段编码可以通过表的第 3 列确定。
A.4.1 Opcode Look-up Examples Using Opcode Extensions
下面提供了一个示例
Example A-4. Interpreting an ADD Instruction
具有 1 字节 opcode 80H 的 ADD 指令是组 1 指令:
- Table A-6 指出该指令的 ModR/M 字节中编码的 opcode 扩展字段为 000B。
- r/m 字段可以编码为访问寄存器(11B)或使用指定寻址模式访问内存地址(例如:mem = 00B,01B,10B)。
Example A-5. Looking Up 0F01C3H
通过使用表 A-2、表 A-3 和表 A-6 查找 opcode 0F01C3 以获取 VMRESUME 指令:
- 0F 表示该指令位于 2 字节 opcode 映射中。
- 01(表 A-3 中的第 0 行、第 1 列)揭示该 opcode 位于表 A-6 的第 7 组。
- C3 是 ModR/M 字节。C3 的前两位是 11B,这告诉我们查看表 A-6 中第 7 组的第二行。
- Op/Reg 位 [5,4,3] 是 000B,这告诉我们在第 7 组中查看 000 列。
- 最后,R/M 位 [2,1,0] 是 011B,这标识该 opcode 为 VMRESUME 指令。
A.4.2 Opcode Extension Tables
See Table A-6 below.
A.5 ESCAPE OPCODE INSTRUCTIONS 转义操作码指令
用于协处理器逃逸指令 opcodes(x87 浮点指令 opcodes)的 opcode 映射在表 A-7 到表 A-22 中。这些映射按 opcode 的第一个字节分组,从 D8 到 DF。每个这些 opcodes 都具有 ModR/M 字节。如果 ModR/M 字节在 00H-BFH 的范围内,则 ModR/M 字节的第 3-5 位用作 opcode 扩展,这与用于 1 字节和 2 字节 opcodes 的技术类似(见 A.4)。如果 ModR/M 字节超出 00H 到 BFH 的范围,则整个 ModR/M 字节用作 opcode 扩展。
A.5.1转义指令操作码的操作码查找示例
省略…
APPENDIX B INSTRUCTION FORMATS AND ENCODINGS
本附录提供了IA-32指令的机器指令格式和编码。第一部分描述了IA-32架构的机器指令格式。其余部分显示通用、MMX、P6系列、SSE/SSE2/SSE3、x87 FPU指令和VMX指令的格式和编码。这些指令格式也适用于Intel 64架构。64位模式中使用的指令格式作为上述格式的超集提供
B.1 MACHINE INSTRUCTION FORMAT 机器指令格式
所有英特尔架构指令都是使用图B-1所示的通用机器指令格式的子集进行编码的。每条指令包括:
操作码(opcode):指令的基本编码,用于指示要执行的操作。
寄存器和/或地址模式说明符:
- 包括 ModR/M 字节:用于指定操作数的寄存器或内存地址。
- 有时还包括 SIB 字节:用于进一步指定复杂地址模式的情况下,SIB 字节用于提供比例因子、索引和基址。
位移(displacement)和立即数(immediate data)字段:
- 位移字段用于在内存地址计算中增加一个常数值。
- 立即数字段包含在指令中直接使用的值,通常是用于操作的直接数据。
下面几节将讨论这种格式。
B.1.1 Legacy Prefixes
图 B-1 中提到的传统前缀包括 66H、67H、F2H 和 F3H。这些前缀是可选的,但在使用 F2H、F3H 和 66H 进行指令扩展时,必须使用。传统前缀必须放置在 REX 前缀之前。
有关传统前缀的更多信息,请参阅英特尔® 64 和 IA-32 架构软件开发人员手册第 2 卷 A 章“指令格式”。
B.1.2 REX Prefixes
REX 前缀是一组 16 个操作码,跨越操作码映射中的一行,并占用条目 40H 到 4FH。这些操作码表示在 IA-32 操作模式和兼容模式下有效的指令(如 INC 或 DEC)。在 64 位模式下,相同的操作码表示指令前缀 REX,而不被视为单独的指令。
有关 REX 前缀的更多信息,请参阅英特尔® 64 和 IA-32 架构软件开发人员手册第 2 卷 A 章“指令格式”。
B.1.3 Opcode Fields
指令的主操作码以 1 到 3 字节的形式编码。在主操作码中,可能会定义较小的编码字段。这些字段根据所执行的操作类别而有所不同。
几乎所有引用寄存器和/或内存操作数的指令在操作码之后都有一个寄存器和/或地址模式字节。这个字节称为 ModR/M 字节,由 mod 字段(2 位)、reg 字段(3 位;该字段有时是操作码扩展)和 R/M 字段(3 位)组成。某些 ModR/M 字节的编码指示必须使用第二个地址模式字节,即 SIB 字节。
如果寻址模式指定了位移,位移值会紧接在 ModR/M 字节或 SIB 字节之后。可能的大小为 8、16 或 32 位。如果指令指定了立即值,则立即值会跟在任何位移字节之后。如果指定,立即值总是指令的最后一个字段。
有关操作码的更多信息,请参阅英特尔® 64 和 IA-32 架构软件开发人员手册第 2 卷 A 章“指令格式”。
B.1.4 Special Fields
表 B-1 列出了某些指令中出现的位字段,这些字段有时出现在opcode 字段中。所有这些字段(除了 d 位)都出现在表 B-13 中的一般用途指令格式中。
Description | ||
---|---|---|
通用寄存器说明符(见表B-4或表B-5)。 | ||
指定数据是Byte还是全尺寸,其中全尺寸为 16 位或 32 位(见表 B-6)。 | ||
指定直接字段的符号扩展名(参见表B-7)。 | ||
CS, SS, DS, ES的段寄存器说明符(见表B-8)。 | ||
CS、SS、DS、ES、FS、GS的段寄存器指定符(见表B-8)。 | ||
指定一个专用(控制或调试)寄存器(见表B-9) | ||
对于条件指令,指定一个断言或否定的条件(见表B-12)。 | ||
对于条件指令,指定一个断言或否定的条件(见表B-12)。 |
B.1.4.1 Reg Field (reg) for Non-64-Bit Modes 64位模式的Reg字段(Reg)
在 ModR/M 字节中,reg 字段用于指定一个通用寄存器操作数。这个寄存器的组会受到 w 位(即宽度位)的影响。以下是关于这两个表的解释:
- w 位缺失时的 reg 字段编码(见Table B-2.):
- 当 w 位 不存在时,reg 字段 的编码方式将指定一个特定的寄存器,通常指示一个 16 位或 32 位的寄存器。
- w 位存在时的 reg 字段编码(见Table B-3):
- 当 w 位 存在时,reg 字段 的编码将指示一个不同的寄存器组,通常会影响操作数的位宽,比如可能指示 64 位的寄存器。
这两个表提供了在不同情况下如何解析和理解 reg 字段 的编码,从而确保指令能够正确地访问和使用相应的寄存器。
B.1.4.2 Reg Field (reg) for 64-Bit Mode 64位模式的Reg字段(Reg)
会受到 w 位 的影响,具体如下:
-
w 位的影响:
- w 位 的存在与状态会改变所指定寄存器的类型。具体来说:
- 当 w 位 不存在时,reg 字段 的编码遵循表 B-4 的定义。
- 当 w 位 存在时,reg 字段 的编码遵循表 B-5 的定义。
- w 位 的存在与状态会改变所指定寄存器的类型。具体来说:
-
表 B-4 和表 B-5:
-
表 B-4: 详细说明了在没有 w 位 的情况下,reg 字段 的具体编码。
-
表 B-5: 详细说明了在存在 w 位 的情况下,reg 字段 的具体编码。
-
指令中不存在w字段时reg字段的编码
指令中有w字段时reg字段的编码
[!NOTE]
- 使用REX前缀时,不能对AH、CH、DH、BH进行编码。这样的表达式默认为低字节。
B.1.4.3 Encoding of Operand Size (w) Bit 操作数大小的编码(w)位
当前操作数大小属性 决定了处理器进行 16 位、32 位或 64 位 操作。在当前操作数大小属性的约束下,操作数大小位 (w) 可以用于指示对 8 位操作数 的操作,或者使用当前操作数大小属性指定的完整操作数大小。
当前操作数大小属性:
- 指定处理器正在进行的操作数大小,可以是 16 位、32 位或 64 位。
操作数大小位 (w):
- 可以指示使用 8 位 的操作数,或者使用当前操作数大小属性所指定的完整操作数大小。
表 B-6:
- 显示了 w 位 的编码方式,取决于当前操作数大小属性。
B.1.4.4 Sign-Extend (s) Bit 符号扩展位
符号扩展位出现在具有从8位扩展到16位或32位的即时数据字段的指令中。参见表B-7。
B.1.4.5 Segment Register (sreg) Field 段寄存器(sreg)字段
当指令在段寄存器上操作时,ModR/M字节中的reg字段称为sregg字段,用于指定段寄存器。表B-8显示了sregg字段的编码。这个字段有时是2位字段(sreg2),有时是3位字段(sreg3)。
[!NOTE]
不要使用保留编码。
不要使用保留编码。
B.1.4.6 Special-Purpose Register (eee) Field 特殊用途寄存器(eee)字段
当控制或调试寄存器在指令中被引用时,它们被编码在eee字段中,位于ModR/M字节的第5位到第3位(sregg字段的另一种编码)。参见表B-9。
B.1.4.7 Condition Test (tttn) Field 条件测试(tttn)字段
对于条件指令(如条件跳转和条件设置),条件测试字段(tttn)是为被测试的条件编码的。字段的ttt部分给出要测试的条件,n部分表示是使用该条件(n = 0)还是其负值(n = 1)。
- tttn 字段的组成:
- ttt:表示要测试的条件。
- n:指示是否使用该条件(当 n = 0 时)或使用其否定(当 n = 1 时)。
- 1字节主操作码:
- 对于使用 1 字节操作码的指令,tttn 字段 位于操作码字节的第 3、2、1 和 0 位。
- 2字节主操作码:
- 对于使用 2 字节操作码的指令,tttn 字段 位于第二个操作码字节的第 3、2、1 和 0 位。
Table B-10 提供了 tttn 字段 的具体编码信息,列出了不同条件及其对应的编码。
B.1.4.8 Direction (d) Bit 方向(d)位
在许多双操作数指令中,方向位(d 位)如何指示哪个操作数被视为源操作数,哪个操作数被视为目标操作数。参见Table B-11。
-
在用于整数指令时,d 位位于 1 字节主操作码的第 1 位。
-
注意,这个位在Table B-13 中并不显示为符号“d”;而是以 1 或 0 的实际编码形式表示。
-
在浮点指令中(在Table B-16中),d 位显示为主操作码第一个字节的第 2 位。
B.1.5 Other Notes
表B-12载有对特定编码的说明。这些注释在下列各节所示的表格中用上标表示。
A | 保留ModR/M字节第7位和第6位的11B值。 |
B | 保留ModR/M字节第7位和第6位的01B(或10B)值。 |
B.2 GENERAL-PURPOSE INSTRUCTION FORMATS AND ENCODINGS FOR NON-64-BIT MODES 非64位模式的通用指令格式和编码
Table B-13显示了非64位模式下通用指令的机器指令格式和编码
Table B-13. General Purpose Instruction Formats and Encodings for Non-64-Bit Modes 省略 请按此标题搜索 英特尔文档
B.2.1 General Purpose Instruction Formats and Encodings for 64-Bit Mode 64位模式的通用指令格式和编码
表B-15显示了64位模式下通用指令的机器指令格式和编码
符号 | |
---|---|
S | 当 REX.W 位的值为 1 时,它会覆盖 66H 前缀的存在 |
W | REX 前缀中的 W 位(即 REX.W )没有影响 |
Table B-15. General Purpose Instruction Formats and Encodings for 64-Bit Mode 省略,请按此标题搜索 英特尔文档
B.3 PENTIUM® PROCESSOR FAMILY INSTRUCTION FORMATS AND ENCODINGS奔腾®处理器家族指令格式和编码
省略
B.4 64-BIT MODE INSTRUCTION ENCODINGS FOR SIMD INSTRUCTION EXTENSIONS用于simd指令扩展的64位模式指令编码
在非64位模式下,MMX 技术、SSE、SSE2 和 SSE3 的指令编码遵循以下规则,具体信息可参考 Table B-19 到 Table B-31。另外,Table B-34 列出了特殊编码(不遵循这些规则的指令)。
- REX 指令的无效性:
- 对立即数无效:REX 指令不会影响立即数的编码或操作。
- 当两个操作数都是 MMX 寄存器时无效:如果两个操作数都是 MMX 寄存器,REX 指令不会改变它们的行为。
- 对 MMX 和 XMM 寄存器无效:REX 指令不会影响 MMX 寄存器和 XMM 寄存器的行为。
- 当 MMX 寄存器在 ModR/M 字节的 reg 字段中编码时无效:如果 MMX 寄存器在 ModR/M 字节的 reg 字段中,REX 指令的存在不会改变这个寄存器的使用。
- 如果内存操作数编码在 ModR/M 字节的 r/m 字段中:
- 可以使用 REX.X 和 REX.B 来编码这个内存操作数。
- 如果通用寄存器编码在 ModR/M 字节的 r/m 字段中:
- 可以使用 REX.B 来编码寄存器,并且可以使用 REX.W 来编码 64 位操作数大小。
- 如果 XMM 寄存器操作数编码在 ModR/M 字节的 reg 字段中:
- 可以使用 REX.R 来编码寄存器。如果 XMM 寄存器操作数编码在 ModR/M 字节的 r/m 字段中,可以使用 REX.B 来编码寄存器。
以下的区域未来再探索吧
66H** 前缀的存在 |
| W | REX 前缀中的 W 位(即 REX.W
)没有影响 |
Table B-15. General Purpose Instruction Formats and Encodings for 64-Bit Mode 省略,请按此标题搜索 英特尔文档
B.3 PENTIUM® PROCESSOR FAMILY INSTRUCTION FORMATS AND ENCODINGS奔腾®处理器家族指令格式和编码
省略
B.4 64-BIT MODE INSTRUCTION ENCODINGS FOR SIMD INSTRUCTION EXTENSIONS用于simd指令扩展的64位模式指令编码
在非64位模式下,MMX 技术、SSE、SSE2 和 SSE3 的指令编码遵循以下规则,具体信息可参考 Table B-19 到 Table B-31。另外,Table B-34 列出了特殊编码(不遵循这些规则的指令)。
- REX 指令的无效性:
- 对立即数无效:REX 指令不会影响立即数的编码或操作。
- 当两个操作数都是 MMX 寄存器时无效:如果两个操作数都是 MMX 寄存器,REX 指令不会改变它们的行为。
- 对 MMX 和 XMM 寄存器无效:REX 指令不会影响 MMX 寄存器和 XMM 寄存器的行为。
- 当 MMX 寄存器在 ModR/M 字节的 reg 字段中编码时无效:如果 MMX 寄存器在 ModR/M 字节的 reg 字段中,REX 指令的存在不会改变这个寄存器的使用。
- 如果内存操作数编码在 ModR/M 字节的 r/m 字段中:
- 可以使用 REX.X 和 REX.B 来编码这个内存操作数。
- 如果通用寄存器编码在 ModR/M 字节的 r/m 字段中:
- 可以使用 REX.B 来编码寄存器,并且可以使用 REX.W 来编码 64 位操作数大小。
- 如果 XMM 寄存器操作数编码在 ModR/M 字节的 reg 字段中:
- 可以使用 REX.R 来编码寄存器。如果 XMM 寄存器操作数编码在 ModR/M 字节的 r/m 字段中,可以使用 REX.B 来编码寄存器。
以下的区域未来再探索吧
以上白皮书第一卷的粗略GPT翻译.后续将补充说明,其细节.
图片全部都是白皮书截图.