ARM嵌入式開發(fā)中的GCC內(nèi)聯(lián)匯編簡(jiǎn)介嵌入式開發(fā)交流群280352802,歡迎加入! 在針對(duì)ARM體系結(jié)構(gòu)的編程中,一般很難直接使用C語(yǔ)言產(chǎn)生操作協(xié)處理器的相關(guān)代碼,因此使用匯編語(yǔ)言來(lái)實(shí)現(xiàn)就成為了唯一的選擇。但如果完全通過(guò)匯編代碼實(shí)現(xiàn),又會(huì)過(guò)于復(fù)雜、難以調(diào)試。因此,C語(yǔ)言內(nèi)嵌匯編的方式倒是一個(gè)不錯(cuò)的選擇。然而,使用內(nèi)聯(lián)匯編的一個(gè)主要問題是,內(nèi)聯(lián)匯編的語(yǔ)法格式與使用的編譯器直接相關(guān),也就是說(shuō),使用不同的C編譯器內(nèi)聯(lián)匯編代碼時(shí),它們的寫法是各不相同的。下面介紹在ARM體系結(jié)構(gòu)下GCC的內(nèi)聯(lián)匯編。GCC內(nèi)聯(lián)匯編的一般格式:
在C代碼中嵌入?yún)R編需要使用asm關(guān)鍵字,在asm的修飾下,代碼列表、輸出運(yùn)算符列表、輸入運(yùn)算符列表和被更改的資源列表這4個(gè)部分被3個(gè)“:”分隔。下面,我們看一個(gè)例子:
注:換行符和制表符的使用可以使得指令列表看起來(lái)變得美觀。你第一次看起來(lái)可能有點(diǎn)怪異,但是當(dāng)C編譯器編譯C語(yǔ)句的是候,它就是按照上面(換行和制表)生成匯編的。 函數(shù)test中內(nèi)嵌了一條匯編指令實(shí)現(xiàn)將立即數(shù)1賦值給寄存器R1的操作。由于沒有任何形式的輸出和輸入,因此輸出和輸入列表的位置上什么都沒有填寫。但是,在匯編代碼執(zhí)行過(guò)程中R1寄存器會(huì)被修改,因此為了通知編譯器,在被更改資源列表中,需要寫上寄存器R1。 寄存器被修改這種現(xiàn)象發(fā)生的頻率還是比較高的。例如,在調(diào)用某段匯編程序之前,寄存器R1可能已經(jīng)保存了某個(gè)重要數(shù)據(jù),當(dāng)匯編指令被調(diào)用之后,R1寄存器被賦予了新的值,原來(lái)的值就會(huì)被修改,所以,需要將會(huì)被修改的寄存器放入到被更改資源列表中,這樣編譯器會(huì)自動(dòng)幫助我們解決這個(gè)問題。也可以說(shuō),出現(xiàn)在被更改資源列表中的資源會(huì)在調(diào)用匯編代碼一開始就首先保存起來(lái),然后在匯編代碼結(jié)束時(shí)釋放出去。所以,上面的代碼與如下代碼從語(yǔ)義上來(lái)說(shuō)是等價(jià)的。
這段代碼中的內(nèi)聯(lián)匯編既無(wú)輸出又無(wú)輸入,也沒有資源被更改,只留下了匯編代碼的部分。由于程序在修改R1之前已經(jīng)將寄存器R1的值壓入了堆棧,在使用完之后,又將R1的值從堆棧中彈出,所以,通過(guò)被更改資源列表來(lái)臨時(shí)保存R1的值就沒什么必要了。 在以上兩段代碼中,匯編指令都是獨(dú)立運(yùn)行的。但更多的時(shí)候,C和內(nèi)聯(lián)匯編之間會(huì)存在一種交互。C程序需要把某些值傳遞給內(nèi)聯(lián)匯編運(yùn)算,內(nèi)聯(lián)匯編也會(huì)把運(yùn)算結(jié)果輸出給C代碼。此時(shí)就可以通過(guò)將適當(dāng)?shù)闹盗性谳斎脒\(yùn)算符列表和輸出運(yùn)算符列表中來(lái)實(shí)現(xiàn)這一要求。請(qǐng)看下面的例子:
上面的代碼中有一條mov指令,該指令將%0賦值給R4。這里,符號(hào)%0代表出現(xiàn)在輸入運(yùn)算符列表和輸出運(yùn)算符列表中的第一個(gè)值。如果%1存在的話,那么它就代表出現(xiàn)在列表中的第二個(gè)值,依此類推。所以,在該段代碼中,%0代表的就是“r”(tmp)這個(gè)表達(dá)式的值了。 與輸入運(yùn)算符列表的應(yīng)用方法一致,當(dāng)C語(yǔ)言需要利用內(nèi)聯(lián)匯編輸出結(jié)果時(shí),可以使用輸出運(yùn)算符列表來(lái)實(shí)現(xiàn),其格式應(yīng)該是下面這樣的。
在上面的代碼中,原本應(yīng)出現(xiàn)在輸入運(yùn)算符列表中的運(yùn)算符,現(xiàn)在出現(xiàn)在了輸出運(yùn)算符列表中,同時(shí)變量tmp將會(huì)存儲(chǔ)內(nèi)聯(lián)匯編的輸出結(jié)果。這里有一點(diǎn)可能已經(jīng)引起大家的注意了,上面的代碼中操作符r的前面多了一個(gè)“=”。這個(gè)等號(hào)被稱為約束修飾符,其作用是對(duì)內(nèi)聯(lián)匯編的操作符進(jìn)行修飾。幾種修飾符的含義如下表所示: 當(dāng)一個(gè)操作符沒有修飾符對(duì)其進(jìn)行修飾時(shí),代表這個(gè)操作符是只讀的。當(dāng)我們需要將內(nèi)聯(lián)匯編的結(jié)果輸出出來(lái),那么至少要保證該操作符是可寫的。因此,“=”或者“+”也就必不可少了。 |
|