王 茹
遼寧裝備制造職業(yè)技術(shù)學(xué)院(沈陽(yáng) 110161)
在嵌入式應(yīng)用程序的設(shè)計(jì)中,如果所有的編程任務(wù)都由匯編語(yǔ)言來(lái)完成,雖然目標(biāo)代碼執(zhí)行效率高,但其工作量會(huì)很大且不易維護(hù);如果全部任務(wù)由C/C++語(yǔ)言來(lái)完成,雖然簡(jiǎn)潔明了,但是目標(biāo)代碼執(zhí)行效率低,尤其在實(shí)時(shí)性較強(qiáng)的應(yīng)用中更會(huì)突顯C/C++的不足。因此,一個(gè)嵌入式應(yīng)用程序通常是由匯編語(yǔ)言和 C/C++語(yǔ)言混合編程來(lái)實(shí)現(xiàn)的,除了初始化部分用匯編語(yǔ)言編程外,其主要的編程任務(wù)一般都由C/C++來(lái)完成。主要介紹了ARM匯編語(yǔ)言與C/C++語(yǔ)言混合編程的兩種實(shí)現(xiàn)方法:內(nèi)嵌匯編和ATPCS規(guī)則。
ARM處理器核能通過(guò)相應(yīng)的編譯器實(shí)現(xiàn)匯編語(yǔ)言與 C/C++等語(yǔ)言之間的調(diào)用/切換。為了這些調(diào)用能夠順利的實(shí)施,ARM規(guī)定了一套標(biāo)準(zhǔn)——ATPCS過(guò)程調(diào)用標(biāo)準(zhǔn)。
ATPCS對(duì) ARM 通用寄存器給以了不同的命名,在進(jìn)行編程時(shí)一般使用ATPCS命名寄存器。ARM寄存器與ATPCS對(duì)照表如表1所示。
表1 ARM寄存器與ATPCS對(duì)照表
ATPCS規(guī)定堆棧采用滿遞減類型(FD,Full Descending),即堆棧通過(guò)減小存儲(chǔ)器地址而向下增長(zhǎng),堆棧指針指向內(nèi)含有效數(shù)據(jù)的最低地址。
整數(shù)參數(shù)的前4個(gè)使用R0~R3傳遞,其他參數(shù)使用堆棧傳遞,所以要想?yún)?shù)傳遞簡(jiǎn)單,最好函數(shù)的參數(shù)個(gè)數(shù)小于等于4。
子程序的返回結(jié)果為1個(gè)32位整數(shù)時(shí),通過(guò)R0返回;返回結(jié)果為1個(gè)64位整數(shù)時(shí),通過(guò)R0和R1返回;依此類推。結(jié)果為浮點(diǎn)數(shù)時(shí),通過(guò)浮點(diǎn)運(yùn)算部件的寄存器F0中。
嵌入式應(yīng)用程序開發(fā)一般由匯編語(yǔ)言完成初始化后,切換到C語(yǔ)言實(shí)現(xiàn)應(yīng)用功能的開發(fā)。匯編語(yǔ)言中要用IMPORT偽操作聲明該C語(yǔ)言程序;匯編語(yǔ)言中通過(guò)BL實(shí)現(xiàn)程序的調(diào)用。
實(shí)例1 用匯編語(yǔ)言調(diào)用C語(yǔ)言方法實(shí)現(xiàn)字符串的復(fù)制。
在C語(yǔ)言程序中,用EXTERN聲明匯編程序;在匯編程序中,用EXPORT 聲明可以被調(diào)用的程序。
C++程序調(diào)用C程序時(shí),在C++程序中使用關(guān)鍵詞 extern "C"聲明被調(diào)用的 C程序。對(duì)于C++中的類(class)或者結(jié)構(gòu)(struct),如果它沒有基類和虛函數(shù),則相應(yīng)的對(duì)象的存儲(chǔ)結(jié)構(gòu)和ARM C相同。
匯編程序調(diào)用 C++程序時(shí),在 C++程序中使用關(guān)鍵詞 extern "C"聲明被調(diào)用的 C++程序。對(duì)于C++中的類或者結(jié)構(gòu),如果它沒有基類和虛函數(shù),則相應(yīng)的對(duì)象的存儲(chǔ)結(jié)構(gòu)和ARM C相同。在匯編程序中使用偽操作 IMPORT聲明被調(diào)用的C++程序。在匯編程序中將參數(shù)存放在數(shù)據(jù)棧中,而存放參數(shù)的數(shù)據(jù)棧的單元地址放在r0寄存器中,這樣被調(diào)用的 C++程序就能訪問(wèn)相應(yīng)的參數(shù)。
在 CC++語(yǔ)言中內(nèi)嵌匯編語(yǔ)句可以實(shí)現(xiàn)一些高級(jí)語(yǔ)言不能實(shí)現(xiàn)或者不容易實(shí)現(xiàn)的功能。對(duì)于時(shí)間緊迫的功能也可以通過(guò)在 CC++語(yǔ)言中內(nèi)嵌匯編語(yǔ)句來(lái)實(shí)現(xiàn)。內(nèi)嵌的匯編器支持大部分ARM指令和Thumb指令,但是不支持諸如直接修改PC實(shí)現(xiàn)跳轉(zhuǎn)的底層功能,也不能直接引用C語(yǔ)言中的變量。
在ARM C語(yǔ)言程序中使用關(guān)鍵詞_asm來(lái)標(biāo)識(shí)一段匯編指令程序,其格式如下:
在 ARM C++程序中除了可以使用關(guān)鍵詞_asm來(lái)標(biāo)識(shí)一段匯編指令程序外,還可以使用關(guān)鍵詞 asm來(lái)標(biāo)識(shí)一段匯編指令程序,其格式如下: asm("instruction[; instruction]");
(1)在匯編指令中,逗號(hào)(,)用作分隔符。因此如果指令中的 C\C++表達(dá)式中包含有逗號(hào)(,),則該表達(dá)式應(yīng)該被包含在括號(hào)中。例如:
asm {ADD x, y, (f(), z)}其中,(f(), z)為C\C++表達(dá)式
(2)如果在指令中使用的物理寄存器,應(yīng)該保證該寄存器不會(huì)被編譯器在計(jì)算表達(dá)式值時(shí)破壞。
(3)不要使用物理寄存器去引用一個(gè) C變量。
(4)對(duì)于內(nèi)嵌匯編器可能會(huì)用到的寄存器,編譯器自己會(huì)保存和恢復(fù)這些寄存器,用戶不用保存和恢復(fù)這些寄存器。常量寄存器CPSR和寄存器SPSR外,別的寄存器必須先賦值然后再讀取,否則編譯器將會(huì)報(bào)錯(cuò)。3.3 內(nèi)嵌匯編指令的應(yīng)用
實(shí)例3 C程序中內(nèi)嵌匯編語(yǔ)句,實(shí)現(xiàn)字符串的復(fù)制。
本文主要通過(guò)幾個(gè)簡(jiǎn)單的例子演示了嵌入式開發(fā)中常用的C/C++和ARM匯編混合編程的一些方法和基本的思路,其中內(nèi)嵌匯編的方法比較簡(jiǎn)潔,而ATPCS規(guī)則中調(diào)用方法較多。以上只是拋磚引玉,更詳細(xì)和復(fù)雜的使用方法要結(jié)合實(shí)際應(yīng)用并參考相關(guān)的資料。本文涉及的實(shí)例全部在ADS集成開發(fā)環(huán)境中運(yùn)行實(shí)現(xiàn)。
[1]杜春雷.ARM 體系結(jié)構(gòu)與編程.北京:清華大學(xué)出版社,2003.
[2]史斌.ARM匯編語(yǔ)言與C/C++混合編程方法,電子測(cè)量技術(shù).2006(6).
[3]孫曄.ARM 嵌入式系統(tǒng)及應(yīng)用.南京:江蘇教育出版社,2011.