Assembly 以下汇编命令有什么好处吗?

Assembly 以下汇编命令有什么好处吗?,assembly,x86,masm,x86-16,Assembly,X86,Masm,X86 16,在我们的系统编程课程中,我们学习汇编语言。在我们教授在课堂上展示的大多数示例程序中;他正在使用: 异或CX,CX 而不是 MOV CX, 0 CMP AX, 0 JNE SOME_LABEL SUB AL, '0' 或 而不是 MOV CX, 0 CMP AX, 0 JNE SOME_LABEL SUB AL, '0' 或 而不是 MOV CX, 0 CMP AX, 0 JNE SOME_LABEL SUB AL, '0' 我的问题是,当使用和/或或异或代替替代(易于理解/阅

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

异或CX,CX 而不是

MOV CX, 0
CMP AX, 0
JNE SOME_LABEL
SUB AL, '0'

而不是

MOV CX, 0
CMP AX, 0
JNE SOME_LABEL
SUB AL, '0'

而不是

MOV CX, 0
CMP AX, 0
JNE SOME_LABEL
SUB AL, '0'
我的问题是,当使用
/
异或
代替替代(易于理解/阅读)方法时,是否有更好的性能

由于这些课程通常在理论课上向我们展示,所以大多数学生无法实际口头评估。为什么要花40分钟来解释这些琐碎的陈述

XOR CX, CX  ;0x31 0xC9
仅使用两个字节:操作码
0x31
和存储源寄存器和目标寄存器的ModR/M字节(在本例中,这两个字节相同)

需要更多字节:操作码
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


SUB AL'0';0x2D 0x30 0x00一个重要的区别是它们是否影响CPU操作标志。使用逻辑运算
xor
等时,操作标志会受到影响。因此:

XOR  CX, CX
不仅会将CX设置为零,而且会设置CPU的零标志。
mov
指令不影响标志。因此:

MOV  CX, 0

例如,不会设置零标志。

XOR操作比MOV工作得更快,因为它是一种逐位操作,所有逐位操作都由CPU执行得更快。

除了在其他答案中提到的代码大小节省外,我想我还应该提到一些其他内容,您可以在和中了解更多:

XOR-REG,REG
SUB-REG,REG
(两个操作数的
REG
相同)被现代x86处理器视为依赖关系断路器;这意味着它们还用于打破对先前寄存器/标志值的错误依赖。请注意,如果清除8位或16位寄存器,这不一定适用,但如果清除32位寄存器,则会适用



我认为首选的指令应该是
测试AX,AX
<代码>测试
可以在现代x86处理器上与任何条件跳转(基本上在解码之前与跳转指令合并为单个指令)进行宏融合<代码>CMP
只能与无符号条件跳转融合,至少在Nehalem体系结构之前。同样,我不确定16位操作数是否是这种情况。

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

一个看似无辜的指令具有巨大影响的例子,请参见GMP名人托尔比约恩·格兰隆德的第8页。在页面右上角的示例三中,一个非常快速的除法循环以“nop”指令开始。A根据同一页的脚注4,nop指令的缺失导致循环执行慢1个时钟周期。Granlund建议通过在环路中放置其他NOP来进行试验,以实现进一步的加速


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

指令可能更短,而且它们不会产生空字节……还有一些特殊的优化,如寄存器重命名,可以识别
xor eax,eax
在此
xor
使用之后何时需要ZF?@user35443,如果您正在检查可能从代码中的多个位置到达的某个点上的标志,则可能需要使用它。所以检查发生的地方可能不知道影响指令的先前标志是
xor
?为什么要使用移位器来实现异或?我的意思是按位写,对不起,我的错,那不是真的。mov reg、imm和xor reg、reg仅占用一个时钟。
mov
也会打破对寄存器上一个值的依赖关系。它只在异或等情况下被提及,因为在一般情况下,输出确实依赖于前面的值,因此需要特殊支持来识别这种情况
movzx
movd
等都将dest reg的其余部分归零,从而断开dep链。(与
pinsrw
movlhps
相反),对于复杂/简单的解码器,这可能会更好地对齐后续指令。Core2早于循环缓存(Nehalem)和uop缓存(Sandybridge),因此即使对于短循环,解码器吞吐量也是一个因素。