为了将 x 设置为零 (x = 0),我的 csapp 书指出了两种方法。
首先:
xorq %rcx, %rcx
第二个:
movq $0, %rcx
它还告诉我们第一个只需要 3 个字节,但是第二个需要 7 个字节。
这两种方式如何运作?为什么第一个占用的字节数比第二个少?
最佳答案
因为mov
需要更多空间来编码其 32 位立即源操作数。
xor
只需要 ModRM 字节对其操作数进行编码。
两者都不需要 REX 前缀,所以您应该比较 2 字节 xor %ecx,%ecx
针对 5 字节 mov $0, %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
编码而不是特殊情况 5 字节 mov $imm32, %r32
省略 ModRM 字节的编码。
(除非您使用 as -O2
,在这种情况下它将是 optimize the operand-size like NASM。请注意 gcc -O2 -c foo.s
不会将优化选项传递给 as
。)
(如 CS:APP example uses idivq with two operands? 中所述,CS:APP 似乎充满了 asm 错误。这不是无效语法错误,只是错过了优化。)
不幸的是没有mov
的编码使用符号扩展的 8 位立即数,否则我们可以有 3 字节 mov reg, imm8
. (https://www.felixcloutier.com/x86/mov)。 (令我惊讶的是,x86-64 的迭代没有将它释放的操作码字节之一重新用于像这样的漂亮 mov
编码,可能与 BMI1 或其他东西混为一谈。)
有关 x86 指令编码的更多详细信息,请阅读英特尔的第 2 卷手册并查看反汇编,以及 https://wiki.osdev.org/X86-64_Instruction_Encoding是一个很好的概述,比英特尔的手册更简洁。
另见 What is the best way to set a register to zero in x86 assembly: xor, mov or and?有关异或归零为何最佳的更多详细信息:在某些 CPU 上,特别是 P6 系列和 Sandybridge 系列,它具有优于 mov
的微体系结构优势除了简单的代码大小。
关于assembly - 为什么使用 `xor` 比使用 `mov` 占用的字节少?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58090417/