在一次采访中,有人问我是否知道x64指令的行为有所不同,具体取决于使用的CPU,我无法在任何地方找到任何文档,有谁知道这些指令是什么以及为什么会这样?
答案 0 :(得分:5)
有一些leave a register or some flags with undefined values。英特尔和AMD可能会有所不同。
在某些情况下,这些未定义案例的实际硬件的实际行为保留了一些依赖它的旧软件的向后兼容性。例如,根据英特尔的手册,输入= 0的BSF
设置ZF并使目标寄存器保留未定义的内容。但AMD的手册(以及真正的英特尔+ AMD硬件)在这种情况下不会修改目的地。 (这就是bsf
/ bsr
具有输出依赖性的原因。)
如果计算性能差异,则有很多(请参阅x86标记wiki中的链接)!
您不只是在谈论不受支持的说明,不是吗?就像LAHF / SAHF在一些非常早期的x86-64 CPU中不支持长模式一样?或者早期K8也不支持CMPXCHG16B。
不受支持的说明最有趣的情况是LZCNT在不支持它的CPU上解码为REP BSR。即使对于非零输入,它们也会返回相反的结果。 (_tzcnt_u32(x) == 31-bsr(x)
)。 TZCNT同样在不支持它的CPU上解码为REP BSF,但它们做同样的事情,除非输入= 0.我之前没有提到过,因为以不同的方式运行相同的机器码与运行相同指令的方式不同,但听起来这就是您要求的那种。
我们只谈论无特权指示吗?特权指令的行为可能存在许多差异。例如,英特尔和AMD在SYSRET中都有不同的错误Linux has to work around,以避免恶意用户空间导致内核挂起。
我不确定的另一个案例是:PREFETCHW在Intel CPU上运行,从至少Core2到Haswell作为NOP,但在AMD CPU上(以及Intel自Broadwell以来)as an actual prefetch。
因此,有些CPU将其作为NOP运行,有些CPU将其作为预取运行(因此无论如何都没有架构上可见的效果),除非在古老的CPU中它作为非法insn出错。 64位Windows8.1 apparently requires that PREFETCHW can run without faulting(阻止它运行(某些?)64位Pentium4 CPU)。
答案 1 :(得分:3)
英特尔和AMD之间存在很多差异
- 当源为零且操作数大小为32位时,Intel 64的
BSF
和BSR
指令与AMD64的行为不同。处理器设置零标志并保留目标的高32位未定义。- Intel 64缺少一些被认为是AMD64架构的
MSR
。其中包括SYSCFG
,TOP_MEM
和TOP_MEM2
。- Intel 64仅在64位模式下(不在兼容模式下)允许
SYSCALL
/SYSRET
,[33]并在两种模式下允许SYSENTER
/SYSEXIT
。 [34] AMD64在长模式的两个子模式中都缺少SYSENTER
/SYSEXIT
。[35]- 在64位模式下,具有66H(操作数大小覆盖)前缀的近分支表现不同。 Intel 64忽略此前缀:指令具有32位符号扩展偏移量,并且指令指针不会被截断。 AMD64在指令中使用16位偏移字段,并清除指令指针的前48位。
- AMD处理器在执行80位信令NaN的
FLD
或FSTP
时会引发浮点无效异常,而英特尔处理器则不会。- 当使用
SYSRET
返回非规范地址时,AMD64处理器在特权级别3中执行常规保护错误处理程序,而在Intel 64处理器上,它以特权级别0执行。[38] [39]
https://en.wikipedia.org/wiki/X86-64#Differences_between_AMD64_and_Intel_64