21

我现在正在学习组装课程,检查我们家庭作业的人是一个非常迂腐的老派优化怪胎。例如,如果他看到以下内容,他会扣除 1​​0%:

mov ax, 0

代替:

xor ax,ax

即使它只用过一次。

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

mov ax, 1

或执行以下操作:

xor ax,ax
inc ax

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

4

4 回答 4

14

一个快速的 google 找到8086 instructions timings size一个指令时序列表,它似乎包含 8086/8088 到 Pentium 的所有时序和大小。

尽管您应该注意,这可能不包括可能非常严重的代码获取内存瓶颈,尤其是在 8088 上。这通常使优化代码大小成为更好的选择。有关这方面的一些详细信息,请参见此处

毫无疑问,您可以在网上找到具有类似信息的英特尔官方文档,例如“8086/8088 用户手册:程序员和硬件参考”。

对于您的具体问题,下表给出了一个比较,表明后者更好(周期更少,空间相同):

指示 时钟周期 字节
xor ax, ax
inc 斧头
3
3
---
6
2
1
---
3
移动斧头,1 4 3

但是你可能想和你的教育机构谈谈这个人。像这样简单的事情被罚款 10% 似乎相当苛刻。你应该问在你有两种可能性的情况下应该怎么做,一种更快,一种更短。

然后,一旦他们承认根据你想要实现的目标有不同的方法来优化代码,告诉他们想要做的是优化可读性和可维护性,而且真的不能在乎关于在这里或那里浪费的周期或字节(1)

优化是您通常在遇到性能问题时所做的事情在一段代码处于接近完整状态之后 - 当代码仍然受到不小的变化可能性影响时,几乎总是浪费精力。

对于它的价值,在时钟周期和大小方面sub ax,ax似乎是相当xor ax,ax的,所以也许你下次可以把它加入到组合中,让他做更多的工作。


(1)不,不要真的那样做,但偶尔发泄一下很有趣:-)

于 2010-05-13T13:14:41.163 回答
3

你最好

移动 AX,1

在 8086 上。如果您正在跟踪寄存器内容,您可能会做得更好,如果您知道,例如,BX 已经有一个 1:

mov AX,BX

或者如果你知道 AH 为 0:

移动 AL,1

等等

于 2010-06-29T20:41:47.083 回答
2

根据您的情况,您可能能够逃脱...

 sbb ax, ax

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

但是,如果上述示例不适用于您的情况,我会推荐

xor  ax, ax
inc  ax

方法。它应该满足你的教授的大小。但是,如果您的处理器使用任何流水线,我希望两条指令之间会有一些类似耦合的延迟(我很可能是错的)。如果存在这种耦合,则可以通过稍微重新排序指令以在它们之间添加另一条指令(不使用 ax 的指令)来稍微提高速度。

希望这可以帮助。

于 2010-05-13T13:18:46.390 回答
2

我会mov [e]ax, 1在任何情况下使用。它的编码不比 hackierxor序列长,而且我很确定它几乎在任何地方都更快。8086 只是奇怪到足以成为例外,并且由于它是如此缓慢,因此像这样的微优化将产生最大的不同。但是在其他任何地方:执行 2 条“简单”指令总是比执行 1 条要慢,尤其是考虑到数据危险和长管道时。您正在尝试在修改后的下一条指令中读取寄存器,因此除非您的 CPU 可以将结果从管道的第 N 阶段(xor正在执行的地方)绕过到第 N-1 阶段(公司正在尝试的地方)加载寄存器,不要介意在它的值上加 1),你会有停顿。

其他需要考虑的事情:指令获取带宽(对于 16 位代码没有实际意义,都是 3 字节);mov避免更改标志(比将它们全部归零更有用);根据其他寄存器可能保存的值,您也许可以这样做lea ax,[bx+1](也是 3 个字节,即使在 32 位代码中,对标志没有影响);正如其他人所说,sbb ax,ax在某些情况下也可以工作 - 它也更短,只有 2 个字节。

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

PS 新作业:xor bx,bxxor bx,cx(在任何处理器上)更快吗?

于 2010-05-13T19:31:18.030 回答