在 x86 上的 64 位模式下,大多数 32 位算术运算会清除目标寄存器的前 32 位。如果算术运算是“cmov”指令,并且条件为假怎么办?(我看过的参考手册中似乎没有涵盖这种情况)。
它总是零扩展到目标,就像所有写入 32 位寄存器的指令一样。
将 CMOV 视为始终写入其目的地:它是一个 ALU 选择操作(3 个输入:2 个整数操作数和标志,1 个输出)。
当条件为假时,它不像 ARM 32 位模式谓词指令那样真正像 NOP。
(出于同样的原因,即使条件为假,也cmovcc reg, [mem]
始终加载内存操作数,并且不会对错误地址进行故障抑制。同样,条件不是移动本身,而是移动条件的结果 -选择操作。AArch64 为它们的相同指令选择了一个更好的名称,csel
.)
有一种情况下一个32位的目的地可以不被零扩展:bsr
和bsf r32,r/m32
当所述源是零个叶目的地未修饰。(仅由 AMD 记录(如果第二个操作数包含 0,则指令将 ZF 设置为 1 并且不会更改目标寄存器的内容。),但也由 Intel 实现)。至少在 Intel CPU 的实践中,这包括在像bsf eax, ecx
. 我没有测试过 AMD。
(这就是为什么 BSF 和 BSR 对目标具有“错误”依赖关系:无分支地实现此行为需要真正的依赖关系。它只是英特尔上 LZCNT/TZCNT/POPCNT 的错误输出依赖关系,它们在同一执行单元上运行但总是覆盖它.)
(维基百科)声称 Intel 和 AMD 在bsf r32, r/m32
. 他们似乎在说英特尔(或者可能是 AMD;措辞有些含糊不清)在 source=0 的情况下未定义高位,而不是未修改。
在我对 Sandybridge 系列和 Core 2 的测试中,它似乎始终未修改,但我无法访问 P4 Nocona / Prescott,这是第一代 IA-32e 微体系结构。
撰写该内容的维基百科编辑器可能只是误解了英特尔的文档,该文档称在这种情况下整个目标寄存器是“未定义的”。(但对于英特尔来说,在硅片上超出他们在纸上的保证是正常的,因此他们关心的现有软件,例如 Windows,可以继续工作)。IDK,如果该声明还有其他来源,那么我想 [需要引用] 在这里真的很合适。
归档时间: |
|
查看次数: |
123 次 |
最近记录: |