为什么使用 `xor` 比使用 `mov` 占用的字节少?

Why does it take less bytes to use `xor` than to use `mov`?

为了将 x 设置为零 (x = 0),我的 csapp 书指出了两种方法。

第一个:

xorq %rcx, %rcx

第二个:

movq [=11=], %rcx

还说第一个只占3个字节,第二个占7个字节

这两种方式如何工作?为什么第一个占用的字节数比第二个少?

因为mov需要更多space来编码其32位立即源操作数。
xor 只需要 ModRM 字节对其操作数进行编码。

两者都不需要 REX 前缀,因此 您应该将 2 字节 xor %ecx,%ecx 与 5 字节 mov [=13=], %ecx 进行比较。 Why do x86-64 instructions on 32-bit registers zero the upper part of the full 64-bit register?
GAS 不会为您进行此优化,并且 movq 为您提供 mov $sign_extended_imm32, %r/m64 编码,而不是省略 ModRM 字节的特殊情况 5 字节 mov $imm32, %r32 编码。
(除非您使用 as -O2,在这种情况下它将 optimize the operand-size like NASM。请注意 gcc -O2 -c foo.s 不会 而不是 将优化选项传递给 as。 )

(如 中所述,CS:APP 似乎充满了 asm 错误。这不是无效语法错误,只是错过了优化。)


不幸的是,mov 没有带符号扩展的 8 位立即数的编码,否则我们可以有 3 字节 mov reg, imm8。 (https://www.felixcloutier.com/x86/mov)。 (令我惊讶的是,x86-64 的迭代没有将它释放的操作码字节之一重新用于像这样的漂亮 mov 编码,可能与 BMI1 或其他东西混为一谈。)

有关 x86 指令编码的更多详细信息,请阅读 Intel 的第 2 卷手册并查看反汇编,https://wiki.osdev.org/X86-64_Instruction_Encoding 是一个很好的概述,比 Intel 的手册更简洁。

另请参阅 以了解有关异或归零为何最佳的更多详细信息:在某些 CPU 上,特别是 P6 系列和 Sandybridge 系列,它除了简单的代码外,还具有优于 mov 的微体系结构优势-尺寸。

Why does the first one take fewer bytes than second?

虽然 Peter Cordes 的回答已经是关于技术细节的,但我想专注于数学背景:

x86s CPU 显然不区分大数字(如 12345789)和零值:存储这样的值需要 4 个字节。

然而,零值是一个非常特殊的值:

可以写成(a-a)或(a XOR a)而"a"可以是任意整数值!

这意味着你可以表演一招:

您执行操作 subq %rcx, %rcx 来计算值 (rcx - rcx)。它不关心 rcx 具有哪个值:如果您从自身中减去该值,结果将为零(因为 (a-a)=0)。

这意味着rcx在该操作后将为0。

操作xorq %rcx, %rcx具有相同的效果,因为(a XOR a)也总是0。