2014-06-05 135 views
0

在GCC內聯彙編中,有兩種方法可以防止優化:__volatile__關鍵字並將"memory"插入到clobber寄存器列表中。GCC內聯彙編 - 與__volatile__和「內存」有什麼不同?

我的問題是與__volatile__"memory"有什麼區別 - 看起來它們是一樣的......但是,今天我遇到了奇怪的情況,這表明它們是完全不同的! (當我使用"memory"時,我的程序在端口I/O功能上存在一個錯誤,但當我使用__volatile__時,它會變得很好。)

有什麼區別?

回答

2

我對GCC文檔的閱讀是__volatile__關鍵字是用於彙編的,它有副作用:也就是說,它除了產生輸出的輸入外還有其他的作用。在你的情況下,我想象「端口I/O功能」會導致副作用。

0123bclobber僅用於讀取/寫入輸入/輸出操作數以外的內存的程序集。雖然這是一個副作用,但並非所有副作用都涉及記憶。

manual

典型的使用擴展asm語句的是操縱輸入值,以產生輸出值。但是,您的財務報表也可能產生副作用。如果是這樣,您可能需要使用volatile限定符來禁用某些優化。

的「記憶」撞告訴彙編代碼執行存儲器讀或寫操作比在輸入和輸出操作數列出的其他項目(例如訪問存儲器由一個指向的編譯器的輸入參數)。
+0

子集?嗯,那麼,有沒有什麼情況應該是'__volatile__',而''memory''是不需要的?你能告訴我其中的一個嗎? – ikh

+0

假設我明白手冊沒問題,從系統時鐘(顯然是'rdtsc'指令)加載一個時間就是其中一種情況。這有幫助嗎? –

+0

子集不正確。這意味着volatile還會執行內存clobber(它不會)。 「記憶」不僅僅意味着你讀/寫記憶也很重要。這是你讀/寫的內存「,除了在輸入和輸出操作數中列出的內容」。例如,如果你只是更新一個輸出參數(「+ m」),你不(必然)需要內存clobber。但是,如果你只是傳遞一個void指針給asm(例如做一個memset),那麼gcc無法弄清楚你可能會改變多少內存。使用內存clobber告訴它假設你改變了一切。 –

0

使用__volatile__您保證總是從RAM中檢索到值爲的CPU旁路。正如Michael Rawson的回答中所述,這產生了副作用,但是通過CPU高速緩存的正常優化是「禁用的」,除此之外沒有其他意義。

在你的情況下,從I/O端口(並存儲在變量中)產生的值可以比CPU緩存失效更快地更新,因此你可以讀取「舊」值。使用__volatile__你總是讀取非緩存值

您還可以看到:this post(我不知道你的架構是ARM,但te概念是相同的)。

+0

嗯。沒有。雖然鏈接文章很有用,但內存clobber與CPU緩存無關。 –