"cqo"、"cdq" 和 "cwd" x86_64 指令。为什么不只使用 cqo?

"cqo", "cdq" and "cwd" x86_64 instructions. Why not use just cqo?

我不是最有经验的汇编程序员,我运行进入了"cqo"、"cdq"和"cwd"指令,它们都是有效的x86_64 程序集。

我想知道在较小的值上运行时使用 cdq 或 cwd 是否有任何优势。性能有什么不同吗?

编辑: 最初开始研究这个,在计算一位数字的绝对值时。

例如,如果我们在 al 中有 -9 值:

cwd
xor al,dl
sub al,dl

对比将其作为 32 位值并计算

cdq
xor eax,edx
sub eax,edx

或者如果我们有 -9 的 64 位值

cqo
xor rax,rdx
sub rax,rdx

如果原始值是 64 位并且由值 -9 到 9 组成,实际上它们看起来都一样。

只有当你的值已经被符号扩展以填充超过 16 位的 rax 时,你才有选择。

如果您在ax 中有一个有符号的16 位int,但eax 的upper16 未知或为零,您必须继续使用16 位指令。 cdq 会根据 eax 顶部的垃圾位设置 edx,而不是 ax 中值的符号位。

类似地,如果您使用 32 位操作在 eax 中生成一个带符号的 32 位 int,则 upper32 将被置零,而不是符号扩展。

如果可以,请使用cdq。如果您需要在 rdx 中设置所有 64 位,则可能需要 cqo


请参阅 http://agner.org/optimize/ 了解如何制作在 x86 上快速运行的 asm。 32 位操作数大小是 64 位模式下的默认值,因此 16 位或 64 位操作数需要额外的前缀。这意味着更大的代码大小,这意味着更差的 I-cache 效率(并且通常在 Sandybridge 之前的 CPU 上有更多的解码瓶颈;SnB 的 uop 缓存通常意味着解码不是问题。)

16bit 还错误地依赖于寄存器的先前内容,因为写入 ax 不会清除 rax 的其余部分。幸运的是,AMD64 在设计时考虑到了乱序 CPU,因此它避免了重复不利于高性能的设计选择,by clearing the upper32 when writing the low 32bits of a GP reg。 (x86 CPU 在设计 AMD64 时已经使用 OOO,这与 ax 扩展到 eax 时不同)。