我很難理解在GCC內聯彙編(x86)中扮演的角色約束。我有read the manual,這正好解釋了每個約束的作用。問題是,即使我理解每個約束所做的事情,但我很少理解爲什麼你會使用一個約束而不是另一個約束,或者可能會產生什麼影響。GCC內聯彙編:約束
我意識到這是一個非常廣泛的話題,所以一個小例子應該有助於縮小焦點。以下是一個簡單的asm例程,它只是增加了兩個數字。如果發生整數溢出,它會將值1
寫入輸出C變量。
int32_t a = 10, b = 5;
int32_t c = 0; // overflow flag
__asm__
(
"addl %2,%3;" // Do a + b (the result goes into b)
"jno 0f;" // Jump ahead if an overflow occurred
"movl $1, %1;" // Copy 1 into c
"0:" // We're done.
:"=r"(b), "=m"(c) // Output list
:"r"(a), "0"(b) // Input list
);
現在,這工作正常,除非我必須任意撥弄約束,直到我得到它正常工作。本來,我用了以下的限制:
:"=r"(b), "=m"(c) // Output list
:"r"(a), "m"(b) // Input list
注意,而不是「0」時,我用b
一個「M」的約束。這有一個奇怪的副作用,如果我使用優化標誌進行編譯並調用了兩次函數,出於某種原因,加法操作的結果也將被存儲在c
中。我最終讀到了「matching constraints」,它允許你指定一個變量被用作輸入和輸出操作數。當我將"m"(b)
更改爲"0"(b)
時,它工作正常。
但我不明白爲什麼你會使用另一個約束。我的意思是說,我知道「r」表示變量應該在一個寄存器中,「m」表示它應該在內存中 - 但我不知道什麼是選擇一個而不是另一個的含義,或者是爲什麼如果我選擇特定的約束組合,則添加操作無法正常工作。
問題:1)在上面的示例代碼中,爲什麼b
上的「m」約束會導致c
被寫入? 2)是否有任何教程或在線資源更詳細地討論約束條件?
謝謝 - 這是一個很好的答案。只需要澄清一下:即使'b'和'c'是內存中不同位置的不同變量,爲什麼'='(只寫)約束脩飾符賦予編譯器重用相同內存位置的權利? – Channel72 2010-10-10 03:06:01
@ Channel72:「即使'b'和'c'是在記憶中不同位置的不同變量」 - 這實際上是一個主要假設,通常不適用。如果'b'和'c'是局部變量,那麼很可能它們都是由寄存器實際支持的,而不是內存位置。在這種情況下,內存位置僅僅是一個臨時保存位置,它的設置純粹是爲了適應您的'm'約束 - 在這種情況下,'b'和'c'可以很好地使用相同的臨時位置。 – 2010-10-10 03:17:21
現在,如果'b'和'c'實際上都是由內存位置真正支持的,那麼你就是對的,通常它們不應該重疊。而且,如果一個由內存支持,另一個由註冊支持......那麼這兩種情況都是可能的。 – 2010-10-10 03:19:22