4

在我们系统的编程课程中,我们正在学习汇编语言。在大多数示例程序中,我们的教授。已在课堂上展示;他正在使用:

XOR CX, CX

代替

MOV CX, 0

或者

OR AX, AX
JNE SOME_LABEL

代替

CMP AX, 0
JNE SOME_LABEL

或者

AND AL, 0FH        ; To convert input ASCII value to numeral
; The value in AL has already been checked to lie b/w '0' and '9'

代替

SUB AL, '0'

AND我的问题如下,使用/ORXOR代替替代(易于理解/阅读)方法时是否有某种更好的性能?

由于这些程序通常在理论课时间向我们展示,因此大多数班级无法实际口头评估它们。为什么要花 40 分钟的时间来解释这些琐碎的陈述?

4

5 回答 5

6
XOR CX, CX  ;0x31 0xC9

仅使用两个字节:操作码0x31和存储源和目标寄存器的 ModR/M 字节(在这种情况下,这两个是相同的)。

MOV CX, 0  ;0xB8 0x08 0x00 0x00

需要更多字节:操作码0xB8、ModR/M 用于目标(在本例中为 CX)和用零填充的两个字节立即数。从时钟的角度来看没有区别(两者都只占用一个时钟),但mov需要 4 个字节,而xor只使用两个。

OR AX, AX  ;0x0A 0xC0

再次只使用操作码字节和 ModRM 字节,而

CMP AX, 0  ;0x3D 0x00 0x00 <-- but usually 0x3B ModRM 0x00 0x00

使用三个或四个字节。在这种情况下,它使用三个字节(操作码0x3D,表示零的字立即数),因为 x86 对累加器寄存器的某些操作具有特殊的操作码,但通常它会使用四个字节(操作码,ModR/M,字立即数)。谈到 CPU 时钟时,情况也是如此。

执行时处理器没有区别

AND AL, 0x0F  ;0x24 0x0F  <-- again special opcode for Accumulator

SUB AL, '0'  ;0x2D 0x30 0x00  <-- again special opcode for Accumulator

(只有一个字节的差异),但是当你减去 ASCII 零时,你不能确定不会有大于9累加器的值。同样,anding 将OFandCF设置为零,虽然sub根据结果设置它们AND会更安全,但我个人的看法是,这种用法取决于上下文。

于 2013-08-12T17:49:02.580 回答
3

Apart from code size savings mentioned in the other answers, I thought I'd mention a few more things which you can read more about in Intel's optimization manual and Agner Fog's x86 optimization guide:

XOR REG,REG and SUB REG,REG (with REG being the same for both operands) are recognized by modern x86 processors as dependency breakers; meaning that they also serve a purpose in breaking false dependencies on previous register/flag values. Note that this doesn't necessarily apply if you clear an 8- or 16-bit register, but it will if you clear a 32-bit register.


OR AX, AX
JNE SOME_LABEL

I believe the preferred instruction would be TEST AX,AX. TEST can be macro-fused with any conditional jump (basically combined with the jump instruction into a single instruction prior to decoding) on modern x86 processors. CMP can only be fused with unsigned conditional jumps, at least prior to the Nehalem architecture. Again, I'm not sure if this is the case for 16-bit operands.

于 2013-08-12T19:31:12.537 回答
1

一个重要的区别是它们是否会影响 CPU 操作标志。当您使用逻辑操作xor,or等时,操作标志会受到影响。所以:

XOR  CX, CX

不仅会归零CX,而且,例如,CPU 的归零标志将被设置。该mov指令不影响标志。所以:

MOV  CX, 0

例如,不会设置零标志。

于 2013-08-12T18:12:58.713 回答
1

除了前面提到的指令调度之外,哪个指令更快也可能取决于正在执行的实际指令序列。

一个看似无辜的指令却产生了巨大的影响,请参见这篇论文的第 8 页,作者是 GMP 的 Torbjörn Granlund。在页面右上角的示例三中,一个非常快速的除法循环以“nop”指令开始。根据同一页上的脚注 4,没有 nop 指令会导致循环执行慢 1 个时钟周期。Granlund 建议通过在循环中放置其他 nop 来进行试验,以实现进一步的加速。

我最初的直觉反应是更多的指示=更多的时间。然而,指令调度和执行显然比从手册中收集到的要多得多。

于 2013-08-16T08:16:00.143 回答
-1

XOR operation works faster than MOV since it is a bitwise operation,all bitwise operations are performed faster by the CPU.

于 2013-08-12T19:29:22.247 回答