2010-04-15 581 views
15

我一直在試圖抓住x86彙編語言,並想知道是否有一個快速和短暫的等效movl $1, %eax。那是當我認爲在語言中頻繁使用的成語列表可能是一個好主意的時候。x86彙編語言

這可以包括優選使用xorl %eax, %eax而不是movl $0, %eaxtestl %eax, %eax而不是cmpl $0, %eax

噢,好心的發佈每個帖子的一個例子!

+5

'movl $ 1,%eax'非常快速和簡短。在某些處理器上,'xorl%eax,%eax'實際上比'movl $ 0,%eax'慢。在其他情況下,'incl%eax'比'addl $ 1,%eax'慢。如果你要在2010年編寫程序集的麻煩,你應該知道你正在編寫什麼樣的架構,並因此選擇你的「方言」(保留語言隱喻)。 – 2010-04-15 17:48:35

+0

@Pascal Cuoq,你能解釋一下哪些因素會影響這種性能差異?我特別被'incl%eax'比'addl $ 1,%eax'慢。此外,如果您可以指向某個詳細介紹此類行爲的鏈接,我將不勝感激! – susmits 2010-04-15 18:11:27

+0

對於2010年xor eax中的所有x86架構,eax的速度更快或者相當,在任何情況下它都更短。看看http://stackoverflow.com/questions/1396527/any-reason-to-do-a-xor-eax-eax/1396552#1396552。這是自486. – hirschhornsalz 2011-03-07 19:50:44

回答

5

在x64:

xor eax, eax 

xor rax, rax 

(第一個還隱含地清除的rax上半部分,但具有更小的操作碼)

7

使用LEA爲例如乘法,如:

lea eax, [ecx+ecx*4] 

爲EAX = 5 * ECX

+5

順便說一句:這是在NetBurst狗緩慢,因爲英特爾刪除桶式移位器,以便能夠獲得更高的時鐘速度。具有諷刺意味的是,在P4發佈時,這仍然記錄在英特爾的優化手冊中。 – 2010-04-15 18:39:31

+0

感謝您的評論。速度。我意識到一個成語不一定和優化一樣。然而,作爲一個習慣用法,我認爲LEA已被廣泛使用(ab)。 – PhiS 2010-04-15 18:52:10

+5

那麼,它*是一個優化。它甚至被英特爾正式推薦。只是在正式推薦了15年之後,他們突然發佈了一個緩慢的新CPU,因此基本上需要重新編譯每個編寫的程序*。值得慶幸的是,NetBurst死了一次快速而痛苦的死亡,所有當前的微架構都是Pentium III的演變,而不是Pentium4,所以所有當前的CPU都有一個桶式移位器。基本上,自80385以來所有的* Intel CPU和所有的Athlon都有,只有Pentium4沒有。 – 2010-04-16 01:55:33

5

你可能以及如何在裝配優化。那麼你不得不問你在優化什麼:大小或速度?總之,這裏是我的 「成語」,爲xchg更換:

xor eax, ebx 
xor ebx, eax 
xor eax, ebx 
+0

**警告:**如果eax == ebx - 兩者都將被清零! – LiraNuna 2010-04-15 18:42:45

+11

你確定嗎? 42^42 = 0; 42^0 = 42; 0^42 = 42 – Sparafusile 2010-04-15 18:53:10

2

由2

+0

它也可以擴展到其他數字。例如,'y * 320 =(y << 8)+(y << 6)'。雖然這可能並不總是比簡單的乘法更快。取決於你的處理器。 – csl 2016-06-23 09:13:57

2

另外一個(xor旁)電源使用SHLSHR乘法/除法的

mov eax, 0 ; B800000000h 

sub eax, eax ; 29C0h 

理由:小碼

2

不知道這是否算作一個成語,但在大多數處理器的i7到

movq xmm0, [eax] 
movhps xmm0, [eax+8] 

之前,或者,如果SSE3可用,

lddqu xmm0, [eax] 

更快用於從未對齊的內存位置讀取比

movdqu xmm0, [eax] 
4

擴展我的評論:

對於難辨別的處理器(如Pentium Pro),xorl %eax, %eax似乎對%eax有依賴性,因此必須等待該寄存器的值可用。後來的處理器實際上有額外的邏輯來識別該指令沒有任何依賴關係。

指令incldecl設置了一些標誌,但保留其他標誌不變。如果爲了重新排序指令而將標誌模型化爲單個寄存器,則這是最糟糕的情況:在incldecl之後讀取標誌的任何指令必須視爲取決於incldecl(以防讀取其中一個標誌該指令設置)以及設置標誌的前一條指令(以防讀取該指令未設置的某個標誌)。一種解決方案是將標誌寄存器分成兩部分,並考慮與這種更細粒度的依賴關係......但AMD有一個更好的主意,並且完全從他們幾年前提出的64位擴展中刪除了這些指令。

關於鏈接,我發現這無論是在英特爾手冊,它是無用提供一個鏈接,因爲它們是在一個企業網站,其每半年重組,或昂納霧的網站:http://www.agner.org/optimize/#manuals

4

在循環...

dec  ecx 
    cmp  ecx, -1  
    jnz  Loop    

dec  ecx 
    jns  Loop 

更快,更短。

+0

是不是循環。操作更簡單? – 2013-11-19 15:16:42

+1

@Hasan Saad:這是但是ti比較慢,在x86中使用循環已被棄用。 – 2013-11-19 19:15:16

+0

非常感謝:) 我不知道這個,所以謝謝你的信息。非常感謝:) – 2013-11-20 14:48:35

10

這是另一個有趣的「成語」。希望每個人都知道,即​​使與乘法相比,這個部門也是一個很大的時間。使用一個小數學,可以乘以常數的倒數而不是除以它。這超出了shr技巧。例如,除以5:

mov eax, some_number 
mov ebx, 3435973837 // 32-bit inverse of 5 
mul ebx 

現在eax已經被5除以不使用慢分區操作碼。下面是從http://blogs.msdn.com/devdev/archive/2005/12/12/502980.aspx

3 2863311531 
5 3435973837 
7 3067833783 
9 954437177 
11 3123612579 
13 3303820997 
15 4008636143 
17 4042322161 

被盜不在名單上的數字有用的常量的除法無恥的列表,你可能需要做一個轉變事前(6分,SHR 1,再乘以的逆3)。