'escape opcode' 是什么意思?
What does 'escape opcode' mean?
在intel software developers manual volumen 2A chapter 2.1.2中说
Two-byte opcode formats for general-purpose and SIMD instructions
consist of one of the following:
- An escape opcode byte 0FH as the primary opcode and a second opcode byte.
- A mandatory prefix (66H, F2H, or F3H), an escape opcode byte, and a second opcode byte (same as previous bullet).
什么是 'escape opcode',它的用途是什么?
"escape" 代码通常是修改下一个字节/符号的含义的代码,而不是其本身的含义。
例如,在 ASCII 键盘输入中(例如在 Linux 终端上),alt + 字母通常作为转义符 + 字母发送。 (其中 ASCII ESC character is 0x1b
,所以如果我 运行 hd
(hexdump) 并键入 alt+x进入其中,我从那个修改过的击键中得到 1b 78
。
或者在双引号 C 字符串中,n
只是一个普通字母。但是 \n
意味着不同的东西:它是一个换行符,仍然是一个字符(在编译器处理转义序列之后)。反斜杠转义了 n
,所以它有其他含义。
x86 机器码有许多单字节操作码(如 00
ADD r/m8, r8
),但一些字节值(如 0F
)是多字节操作码的第一个字节,而不是整个操作码。
通过用完一个单字节操作码 (0f
) 来提供另外 256 2 字节操作码。
例如,0F AF
is IMUL r32, r/m32
, and 0F B6
is movzx r32, r/m8
。这些通用指令是在最初的8086之后引入的,没有留下编码-space给它们单字节操作码。 (或者英特尔将其保存以供将来转义序列使用。)
像66
这样的强制性前缀与扩展编码space的想法类似,允许使用具有不同含义的字节对更多不同的操作码进行编码在其他情况下,而不是仅作为转义字节(当出现在操作码的开头时)。
这些字节是操作数大小,当与那些前缀有意义的操作码一起使用时,REP/REPE, and REPNE 前缀。但是对于某些指令,这些前缀 没有 意义:操作码已经暗示了单个操作数大小,并且它不是字符串指令。 (请注意,地址大小前缀和段覆盖前缀可以应用于具有显式内存操作数的任何指令,因此不用作强制性前缀。lock
也不是。)
像 MMX 0F FC paddb mm0, mm1/m64
这样的指令已经有一个固定的 SIMD 操作数大小。 None 这些前缀对它有意义。英特尔选择(针对 SSE2)制作 XMM 版本 66 0F FC PADDB xmm1, xmm2/m128
,为 MMX 编码添加操作数大小前缀。
类似地,F3 0F 59 MULSS xmm1,xmm2/m32
是 mulps
+ 一个 REP 前缀。
英特尔已使用 rep
作为某些非 SIMD 指令的强制性前缀。例如pause
是 rep nop
,tzcnt
是 rep bsf
(这很有趣,因为它们在 CPU with/without BMI1 上做同样的事情,除非输入为零)。这允许向后兼容,因为通常 CPU 会忽略它们不理解为应用的 REP 前缀。
(故意使用不适用的 REP 前缀作为填充并不是未来的证明,因为编码可能会在未来的 CPU 中获得一些意义。但是当新旧意义都已知时,英特尔通常会保证所有旧 CPU将 rep nop
解码为 nop
,从而无需检查 CPUID 功能位即可安全地在自旋循环中使用 pause
。)
在intel software developers manual volumen 2A chapter 2.1.2中说
Two-byte opcode formats for general-purpose and SIMD instructions consist of one of the following:
- An escape opcode byte 0FH as the primary opcode and a second opcode byte.
- A mandatory prefix (66H, F2H, or F3H), an escape opcode byte, and a second opcode byte (same as previous bullet).
什么是 'escape opcode',它的用途是什么?
"escape" 代码通常是修改下一个字节/符号的含义的代码,而不是其本身的含义。
例如,在 ASCII 键盘输入中(例如在 Linux 终端上),alt + 字母通常作为转义符 + 字母发送。 (其中 ASCII ESC character is 0x1b
,所以如果我 运行 hd
(hexdump) 并键入 alt+x进入其中,我从那个修改过的击键中得到 1b 78
。
或者在双引号 C 字符串中,n
只是一个普通字母。但是 \n
意味着不同的东西:它是一个换行符,仍然是一个字符(在编译器处理转义序列之后)。反斜杠转义了 n
,所以它有其他含义。
x86 机器码有许多单字节操作码(如 00
ADD r/m8, r8
),但一些字节值(如 0F
)是多字节操作码的第一个字节,而不是整个操作码。
通过用完一个单字节操作码 (0f
) 来提供另外 256 2 字节操作码。
例如,0F AF
is IMUL r32, r/m32
, and 0F B6
is movzx r32, r/m8
。这些通用指令是在最初的8086之后引入的,没有留下编码-space给它们单字节操作码。 (或者英特尔将其保存以供将来转义序列使用。)
像66
这样的强制性前缀与扩展编码space的想法类似,允许使用具有不同含义的字节对更多不同的操作码进行编码在其他情况下,而不是仅作为转义字节(当出现在操作码的开头时)。
这些字节是操作数大小,当与那些前缀有意义的操作码一起使用时,REP/REPE, and REPNE 前缀。但是对于某些指令,这些前缀 没有 意义:操作码已经暗示了单个操作数大小,并且它不是字符串指令。 (请注意,地址大小前缀和段覆盖前缀可以应用于具有显式内存操作数的任何指令,因此不用作强制性前缀。lock
也不是。)
像 MMX 0F FC paddb mm0, mm1/m64
这样的指令已经有一个固定的 SIMD 操作数大小。 None 这些前缀对它有意义。英特尔选择(针对 SSE2)制作 XMM 版本 66 0F FC PADDB xmm1, xmm2/m128
,为 MMX 编码添加操作数大小前缀。
类似地,F3 0F 59 MULSS xmm1,xmm2/m32
是 mulps
+ 一个 REP 前缀。
英特尔已使用 rep
作为某些非 SIMD 指令的强制性前缀。例如pause
是 rep nop
,tzcnt
是 rep bsf
(这很有趣,因为它们在 CPU with/without BMI1 上做同样的事情,除非输入为零)。这允许向后兼容,因为通常 CPU 会忽略它们不理解为应用的 REP 前缀。
(故意使用不适用的 REP 前缀作为填充并不是未来的证明,因为编码可能会在未来的 CPU 中获得一些意义。但是当新旧意义都已知时,英特尔通常会保证所有旧 CPU将 rep nop
解码为 nop
,从而无需检查 CPUID 功能位即可安全地在自旋循环中使用 pause
。)