assembly - x86指令编码如何选择操作码

标签 assembly compiler-construction x86-64 disassembly

编码指令时cmpw %ax -5对于 x86-64,从 Intel-instruction-set-reference-manual,我有两个操作码可供选择:

3D iw CMP AX, imm16 I Valid Valid Compare imm16 with AX.
83 /7 ib CMP r/m16, imm8 MI Valid Valid Compare imm8 with r/m16.

所以会有两种编码结果:
66 3d fb ff ; this for opcode 3d
66 83 f8 fb ; this for opcode 83

那么哪个更好呢?

我在下面尝试了一些在线反汇编程序
  • https://defuse.ca/online-x86-assembler.htm#disassembly2
    https://onlinedisassembler.com/odaweb/

  • 两者都可以反汇编到原点指令。但为什么6683fb00也可以使用和 663dfb没有。

    最佳答案

    两种编码的长度相同,因此这无助于我们做出决定。

    然而,正如@Michael Petch 所评论的,imm16编码将导致 Intel CPU 上的解码器中的 LCP 停顿。 (因为没有 66 操作数大小前缀,它将是 3D imm32 ,所以操作数大小前缀会改变指令其余部分的长度。这就是为什么它被称为 Length-Changing-Prefix stall 。AFAIK,你会在 16 位代码中获得相同的停顿以使用 32 位立即数。)

    imm8编码不会对我所知道的任何微体系结构造成问题,所以赞成它。 Agner Fog's microarch.pdf ,以及来自 的其他链接标记维基。

    值得使用更长的指令来避免 LCP 停顿。 (例如,如果您知道寄存器的高 16 位为零或符号扩展,则使用 32 位操作数大小可以避免 LCP 停顿。)

    Intel SnB 系列 CPU 具有 uop 缓存,因此在执行之前不必总是重新解码指令。尽管如此,uop 缓存很小,所以值得。

    当然,如果您正在为 AMD 进行调整,那么这不是一个因素。我忘了 Atom 和 Silvermont 解码器是否也有 LCP 档位。

    回复:第 2 部分:
    663dcmp ax, imm16 的前缀+操作码. 663dfb不“工作”,因为它消耗了以下指令的第一个字节。当解码器看到66 3D ,它从指令流中获取接下来的 2 个字节作为立即数。

    关于assembly - x86指令编码如何选择操作码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37611247/

    相关文章:

    c - ASM 调用约定

    assembly - 每个函数名称后面的 @n ("at sign") 是什么?

    assembly - 68k寄存器地址

    c++ - 未使用的功能会被优化吗?

    assembly - 是否有任何语言/编译器使用具有非零嵌套级别的 x86 ENTER 指令?

    assembly - cmp汇编语言指令-gas格式

    c - 为什么编译器不优化掉这些无法访问的指令呢?

    assembly - 获取 CALL 的微操作

    c++ - 常量字段中的初始化列表不生成 operator=

    linux - clang 错过汇编程序错误?