2011-07-24 59 views
12

我目前正在学习x86汇编语言,并想知道什么是实现循环的更好方法。一种方法是将一个值传递给ecx寄存器并使用循环指令,另一种方式是使用jmp指令,然后进入循环体,然后有条件跳转到循环体的开始处。我想第一个会有更好的可读性,但其他的我不知道为什么要使用它。x86汇编编程循环与ecx和循环指令与jmp + j <condition>

+0

从来不知道/知道什么时候接受它,因为我总是可能会有更好的答案?这真的很重要吗?因为我真的不知道。 – rob

+0

相关:[为什么总是像这样编译循环?](https://stackoverflow.com/questions/47783926/why-are-loops-always-compiled-like-this):几乎总是最好使用'do {} while()'在asm中构造,底部有条件分支。如果循环可能需要运行0次,那么jmp到底是一种策略,但通常不是最好的。 –

回答

12

当您提到jmp + body + test时,我相信您正在讨论高级语言中while循环的翻译。第二种方法是有原因的。让我们来看看。

考虑

x = N 
while (x != 0) { 
    BODY 
    x-- 
} 

用简单的方式是

mov ecx, N  ; store var x in ecx register 
top: 
    cmp ecx, 0  ; test at top of loop 
    je bottom  ; loop exit when while condition false 
    BODY 
    dec ecx 
    jmp top 
bottom: 

这有N个条件跳转和N无条件跳跃。

第二种方式是:

mov ecx, N 
    jmp bottom 
top: 
    BODY 
    dec ecx 
bottom: 
    cmp ecx, 0 
    jne top 

现在我们还在做ň条件跳转,但我们只能做一件无条件跳转。节省很少,但它可能很重要,特别是因为它在循环中。

现在你没有提到的loop指令,它本质上是

dec ecx 
cmp ecx, 0 
je somewhere 

你将如何工作,在?大概是这个样子:

mov ecx, N 
    cmp ecx, 0  ; Must guard against N==0 
    je bottom 
top: 
    BODY 
    loop top   ; built-in dec, test, and jump if not zero 
bottom: 

这是典型的CISC处理器的一个漂亮的小的解决方案。它比上面的第二种方法更快吗?这在很大程度上取决于架构。如果您真的想了解更多信息,我建议您对IA-32和Intel 64处理器架构中的loop指令的性能进行一些研究。

+0

谢谢,这有助于退出,我会尝试做一些关于ECX循环速度的进一步研究:) – rob

+3

@rob,快乐的研究。我可以建议http://www.agner.org/optimize/optimizing_assembly.pdf?一个惊人的资源。很长。在第89页提到,你应该避免JECXZ和LOOP,因为它们在更现代的体系结构上效率不高。 –

+0

相关:[为什么循环指令很慢?英特尔能否有效地实现它?](https://stackoverflow.com/questions/35742570/why-is-the-loop-instruction-slow-couldnt-intel-have-implemented-it-efficiently)一些历史因素。有趣的事实:AMD推土机/ Ryzen拥有快速的“循环”,但没有其他任何事情。还有相关的问题:[为什么循环总是像这样编译?](https://stackoverflow.com/questions/47783926/why-are-loops-always-compiled-like-this)以获得高效的循环结构:如您所说,有条件底部的分支,以及可能需要运行0次的各种策略。 –