2011-07-24 56 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次的各種策略。 –