【问题标题】:What does 'escape opcode' mean?“转义操作码”是什么意思?
【发布时间】:2018-09-15 16:37:28
【问题描述】:

intel software developers manual volumen 2A chapter 2.1.2 中这样说

通用指令和 SIMD 指令的双字节操作码格式 由以下之一组成:

  • 转义操作码字节 0FH 作为主操作码和第二个操作码字节。
  • 强制前缀(66H、F2H 或 F3H)、转义操作码字节和第二个操作码字节(与上一个项目符号相同)。

什么是“转义操作码”,它的用途是什么?

【问题讨论】:

  • 有趣的是,“转义操作码”曾经是d8df 范围内的操作码,用于用户定义的协处理器。如今,这个协处理器几乎可以肯定是 x87 FPU,但过去有不同的选择(最引人注目的是 8089 IO 处理器)。
  • 不是直接关于指令而是相关的:en.wikipedia.org/wiki/Escape_characteren.wikipedia.org/wiki/Escape_sequence 他们都是关于不同地对待下一个字节

标签: assembly encoding x86 opcode machine-code


【解决方案1】:

“转义”代码通常是修改下一个字节/符号的含义的代码,而不是自己的含义。

例如,在 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/m320F 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/m32mulps + REP 前缀。

英特尔已使用rep 作为某些非 SIMD 指令的强制前缀。例如pauserep noptzcntrep bsf(这很有趣,因为它们在有/没有 BMI1 的 CPU 上做同样的事情,除非输入为零)。这允许向后兼容,因为通常 CPU 会忽略它们不理解为应用的 REP 前缀。

(但是,故意使用不适用的 REP 前缀作为填充不是未来的证明,因为编码可能会在未来的 CPU 中获得一些含义。但是当旧的和新的含义都知道时,英特尔通常会保证所有旧的 CPU 都解码@ 987654352@ 和 nop 一样,可以安全地在自旋循环中使用 pause 而无需检查 CPUID 功能位。)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-11-21
    • 2018-07-31
    • 2015-11-22
    • 2011-02-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多