以下汇编命令有一些好处吗?

时间:2013-08-12 17:09:06

标签: assembly x86 masm x86-16

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

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代替备用(易于理解/阅读)方法时,是否有某种更好的表现?< / p>

由于这些课程通常在理论讲座时间向我们展示,因此大多数课程无法用口头方式对其进行评估。为什么要花40分钟讲解这些琐碎的陈述?

5 个答案:

答案 0 :(得分: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的值。 同时将OFCF设置为零,而sub根据结果AND设置它们可能更安全,但我个人认为此用法取决于上下文。

答案 1 :(得分:3)

除了其他答案中提到的代码大小节省外,我想我还会提到一些您可以在Intel's optimization manualAgner Fog's x86 optimization guide中详细了解的内容:

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


OR AX, AX
JNE SOME_LABEL

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

答案 2 :(得分:1)

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

XOR  CX, CX

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

MOV  CX, 0
例如,

不会设置零标志。

答案 3 :(得分:1)

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

GMP成名的TorbjörnGranlund在this paper的第8页中看到了一个看似无辜的教导的例子。在页面右上角的示例三中,非常快速的分割循环以“nop”指令开始。根据同一页面上的脚注4,缺少nop指令会导致循环执行速度减慢1个时钟周期。 Granlund建议通过在循环内放置其他nops来进行实验,以实现进一步的加速。

我最初的,直觉反应是更多的指示=更多的时间。但是,与手册相比,指令调度和执行显然要多得多。

答案 4 :(得分:-1)

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