簡體   English   中英

為什么C中沒有內置交換功能但是匯編中有xchg?

[英]Why is there no inbuilt swap function in C but there is xchg in Assembly?

最近我遇到了匯編語言。 x86程序集有一個xchg指令 ,用於交換兩個寄存器的內容。

由於每個C代碼都首先轉換為匯編代碼,如果在標頭stdio.h有一個內置的交換函數,那就太好了。 然后,只要編譯器檢測到交換函數,它就可以在匯編文件中添加xchg指令。

那么為什么這個交換功能沒有在C中實現呢?

C是一種跨平台語言。 裝配是特定於架構的。 並非每個架構都有這樣的指令。 而且,作為高級語言的C不必與機器級指令集和功能相對應,因為它的目的是在“人”語言和機器語言之間架起橋梁,而不是模仿它。 據說,針對此特定體系結構的C編譯器可能具有此交換指令的擴展,或者如果足夠智能則優化交換代碼以使用此指令。

這適用於適合寄存器並位於寄存器中的變量。 它不適用於內存中保存的大型結構或變量(如果在reg X中加載變量A,在reg Y中加上B,並交換它們,則可以跳過交換並直接在Y和B中加載A )。

話雖如此,沒有什么能阻止編譯器使用交換指令進行編譯:

 int a;
 int b;
 int tmp;
 tmp=a;
 a=b;
 b=tmp;

...如果那些恰好在寄存器中:事實上它不在C中並不意味着編譯器不使用它。

有兩點可以解釋為什么swap()不在C中

1.函數調用語義:
包含swap()函數會在C中打破一個非常基本的設計決策: swap()只能使用pass-by-reference語義(C ++添加到語言中,但C語言中沒有),而不是pass-by -值。

2.可用匯編程序指令的多樣性
除此之外,在任何給定的CPU架構上通常都有相當多的匯編指令,它們完全無法從純C中訪問。這包括各種指令,如中斷處理指令,虛擬存儲空間操作指令,I / O指令,位功能指令(谷歌PPC指令rlwimi是一個特別有力的例子),等等。

在像C這樣的通用語言中包含任何大量的這些都是不可能的。

其中一些對於實現操作系統至關重要,這就是為什么任何操作系統必須至少包含一些少量的匯編代碼。 它們通常使用內聯匯編程序封裝在某些函數中,或者在內核頭文件中定義為預處理程序指令。 其他指令不太重要,或者只對優化很有用,這些指令可以通過優化編譯器生成,並且許多編譯器確實生成它們(整個類的向量函數都屬於這一類)。

面對這種巨大的多樣性,C的設計師不得不將它切割到某個地方。 他們選擇提供任何可表示的簡單操作符,如(+, - ,〜,&,|,!,&&,||等),但沒有提供任何需要函數調用語法的東西,如swap()你建議的功能。

除了其他正確答案所說的,你的前提的另一部分是錯誤的。

每次源交換變量時,只有一個非常愚蠢的編譯器才會想要實際發出xchg ,無論是否存在內在函數或運算符。 優化編譯器不只是將C音譯成asm,它們通常轉換為程序邏輯的SSA內部表示,並對其進行優化,以便它們可以用盡可能少的指令實現它(或者實際上以最有效的方式實現;使用多個快速指令可能比單個慢速指令更好。

xchg很少比3 mov指令快,並且一個好的編譯器可以簡單地改變它的本地變量< - > CPU寄存器映射,而在許多情況下不發出任何asm指令。 (或者在循環內部,展開通常可以優化遠程交換。)通常你只需要asm中的1或mov指令,而不是全部3.例如,如果只有一個被交換的C變量需要保留在同一個寄存器中,你可以做:

# start:   x in EAX,  y in ECX 
mov    edx, eax
mov    eax, ecx
# end:     y in EAX,  x in EDX

另請參閱為什么XCHG reg,注冊了關於現代英特爾架構的3微操作指令?

另請注意, xchg [mem], reg是原子(隱式lock前綴),因此是一個完整的內存屏障,比3個mov指令慢得多,並且由於內存屏障效應對周圍代碼的影響要大得多。


如果確實需要交換寄存器,3 mov是相當不錯的。 通常比xchg reg,reg更好xchg reg,reg因為xchg reg,regmov ,代價是更多代碼大小和tmp reg。

編譯器從不使用xchg是有原因的。 如果xchg是一個勝利,編譯器會將其視為窺視孔優化,就像它們在add eax,1xor eax,eax而不是mov eax,0查找inc eax一樣。 但他們沒有。

(半相關: 用8086匯編語言(16位)交換2個寄存器

盡管xchg是一個非常基本的指令,但這並不意味着C必須具有等效性。 C 有時直接映射到裝配的事實並不十分重要; 標准沒有提到“匯編”(為什么映射到匯編而不是另一種低級語言?)。

您可能還會問:為什么C沒有內置向量指令? 他們變得很有可能!

還有編譯器的幫助:交換變量是一種非常明顯的模式,因此這種優化應該不難實現。 如果需要,你也有內聯asm

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM