“转义”代码通常是修改下一个字节/符号的含义的代码,而不是自己的含义。
例如,在 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 字节操作码,从而从 256 个可能的操作码(加上 ModRM 字节的 /r 字段中的重载)扩展编码空间。
例如,0F AF is IMUL r32, r/m32 和 0F B6 is movzx r32, r/m8。这些通用指令是在最初的 8086 之后引入的,并且没有剩余的编码空间给它们提供单字节操作码。 (或者英特尔将其保存为将来的转义序列。)
像66这样的强制性前缀是一个类似的想法,可以扩展编码空间以允许编码更多不同的操作码,使用在其他上下文中具有不同含义的字节,而不仅仅是一个转义字节(出现在操作码的开头时)。
这些字节是操作数大小,REP/REPE, and REPNE 前缀与这些前缀有意义的操作码一起使用。但是对于某些指令,这些前缀是不有意义的:操作码已经暗示了一个单一的操作数大小,它不是一个字符串指令。 (请注意,地址大小前缀和段覆盖前缀可以应用于任何具有显式内存操作数的指令,因此不用作强制前缀。lock 也不是。)
像 MMX 0F FC paddb mm0, mm1/m64 这样的指令已经有一个固定的 SIMD 操作数大小。这些前缀中没有一个对它有意义。英特尔选择(针对 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(这很有趣,因为它们在有/没有 BMI1 的 CPU 上做同样的事情,除非输入为零)。这允许向后兼容,因为通常 CPU 会忽略它们不理解为应用的 REP 前缀。
(但是,故意使用不适用的 REP 前缀作为填充不是未来的证明,因为编码可能会在未来的 CPU 中获得一些含义。但是当旧的和新的含义都知道时,英特尔通常会保证所有旧的 CPU 都解码@ 987654352@ 和 nop 一样,可以安全地在自旋循环中使用 pause 而无需检查 CPUID 功能位。)