对于x86-64的编码指令cmpw %ax -5
,来自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
然后哪一个更好?
我在
下面尝试了一些在线反汇编程序两者都可以反汇编到原点指令。但为什么6683fb00
也有效且663dfb
没有。
答案 0 :(得分:5)
两种编码长度相同,因此无法帮助我们做出决定。
但是,正如@Michael Petch评论的那样,imm16
编码将导致Intel CPU上的解码器中的LCP停顿。 (因为没有66
操作数大小前缀,它将是3D imm32
,因此操作数大小前缀会改变指令的 rest 的长度。这就是为什么它& #39; s称为Length-Changing-Prefix stall。AFAIK,您在16位代码中使用32位立即获得相同的停顿。)
imm8
编码在我知道的任何微架构上都没有问题,所以非常喜欢它。请参阅Agner Fog's microarch.pdf以及{x86中的其他链接3}}标签维基。
值得使用更长的指令来避免LCP停顿。 (例如,如果您知道寄存器的高16位为零或符号扩展,则使用32位操作数大小可以避免LCP停顿。)
Intel SnB系列CPU具有uop缓存,因此在执行之前不必重新解码指令。不过,uop缓存很小,所以值得。
当然,如果您正在调整AMD,那么这不是一个因素。我忘记了Atom和Silvermont解码器是否也有LCP档位。
663d
是cmp ax, imm16
的前缀+操作码。 663dfb
没有"工作"因为它消耗了以下指令的第一个字节。当解码器看到66 3D
时,它会从指令流中获取接下来的2个字节作为立即数。