设置寄存器为1或(-1)的最有效方法

时间:2010-05-13 12:53:37

标签: assembly performance xor cpu-registers x86-16

我现在正在参加一个装配课程,那个检查我们家庭作业的人是一个非常迂腐的老派优化狂。例如,如果他看到,他会扣除10%:

mov ax, 0

而不是:

xor ax,ax

即使只使用一次。

我不是一个完整的汇编程序初学者,但我不是一个优化专家,所以我需要你的帮助(可能是一个非常愚蠢的问题,但无论如何我都会问): 如果我需要将寄存器值设置为1或(-1),最好使用:

mov ax, 1

或做类似的事情:

xor ax,ax
inc ax

我真的需要一个好成绩,所以我试图让它尽可能优化。 (我需要优化时间和代码大小)

4 个答案:

答案 0 :(得分:10)

快速谷歌8086 instructions timings size出现了http://8086.tk/,它似乎拥有8086(及更多)指令集的所有时间和大小。

毫无疑问,您可以在网上找到具有类似信息的官方英特尔doco。

针对您的具体问题:

xor ax,ax
inc ax

需要3 + 3 = 6个时钟周期和2 + 1 = 3个字节

mov ax,1

需要4个时钟周期和3个字节。

所以后者在这种情况下更好。


但你需要和你的教育机构谈谈这个人。对于像乞丐信仰这样简单的事情,这个数字为10%。

你应该问在你有两种可能性的情况下应该做些什么,一种更快,一种更短。

然后,一旦他们承认根据你想要实现的目标有不同的编码方式,告诉他们你想要实现的是可读性和可维护性,并且严重无法实现飞跃关于浪费的周期或字节在这里或那里 * a

当一段代码处于接近完成状态后,如果遇到性能问题,通常会执行优化 - 当代码仍然受到无关紧要的变更可能性时,几乎总是浪费精力

对于它的价值而言,sub ax,ax在时钟周期和字节方面似乎与xor ax,ax相同,所以也许你可以在下次将它投入混合中以使他做更多的工作。

* a)不,不是真的,偶尔发泄也很有趣: - )

答案 1 :(得分:3)

你最好用

mov AX,1

8086上的

。如果你正在跟踪注册内容,你可以做得更好,如果你知道,例如,BX已经有1:

mov AX,BX

或者如果你知道AH是0:

mov AL,1

答案 2 :(得分:2)

根据您的具体情况,您可能会逃脱...

 sbb ax, ax

如果未设置进位标志,结果将为0;如果进位标志已设置,结果将为-1。

但是,如果上述示例不适用于您的情况,我建议

xor  ax, ax
inc  ax

方法。它应该满足你的教授的规模。但是,如果你的处理器使用任何管道衬里,我会期望在两个指令之间存在一些类似耦合的延迟(我很可能错误)。如果存在这样的耦合,可以通过稍微重新排序指令来略微提高速度,以便在它们之间有另一条指令(一个不使用ax的指令)。

希望这有帮助。

答案 3 :(得分:0)

在任何情况下我都会使用mov [e]ax, 1。它的编码不再是hackier xor序列,我很确定它在任何地方都更快。 8086很奇怪,只是异常,因为这个东西太慢了,像这样的微优化会产生最大的不同。但是在任何其他地方:执行2个“简单”指令总是比执行1慢,特别是如果你考虑数据危险和长管道。您在修改后尝试在下一条指令中读取寄存器,因此除非您的CPU可以绕过管道的第N阶段(xor正在执行的地方)到阶段N-1(公司试图加载寄存器的地方,别介意在它的值上加1),你就会有档位。

需要考虑的其他事项:指令获取带宽(16位代码的问题,两者都是3个字节); mov避免更改标志(比将它们全部强制为零更有用);根据其他寄存器可能包含的值,您可能会lea ax,[bx+1](也是3个字节,即使在32位代码中也不会对标志产生影响);正如其他人所说,sbb ax,ax在某些情况下也可以工作 - 它在2个字节时也会更短。

当面对这些微观优化时,你真的应该衡量替代方案,而不是盲目地依赖处理器手册。

P.S。新作业:xor bx,bxxor bx,cx(在任何处理器上)都快{?}}?