混合使用C、C++和匯編語(yǔ)之:內(nèi)聯(lián)匯編和嵌入型匯編的使用
3.嵌入式匯編程序表達(dá)式和C或C++表達(dá)式之間的差異
嵌入式匯編表達(dá)式和C或C++表達(dá)式之間存在以下差異。
①匯編程序表達(dá)式總是無(wú)符號(hào)的。相同的表達(dá)式在匯編程序和C或C++中有不同值。例如:
MOVr0,#(-33554432/2)//結(jié)果為0x7f000000
MOVr0,#__cpp(-33554432/2)//結(jié)果為0xff000000
②以0開(kāi)頭的匯編程序編碼仍是十進(jìn)制的。例如:
MOVr0,#0700//十進(jìn)制700
MOVr0,#__cpp(0700)//八進(jìn)制0700等于十進(jìn)制448
③匯編程序運(yùn)算符優(yōu)先順序與C和C++不同。例如:
MOVr0,#(0x23:AND:0xf+1)//((0x230xf)+1)=>4
MOVr0,#__cpp(0x230xf+1)//(0x23(0xf+1))=>0
④匯編程序字符串不是以空字符為終止標(biāo)志的:
DCBnotrailingnull//16bytes
DCB__cpp(Ihaveatrailingnull!!)//25bytes
注意 | 在_cpp標(biāo)識(shí)符作用范圍之內(nèi)使用C或C++語(yǔ)法規(guī)則。 |
4.嵌入式匯編函數(shù)的生成
由關(guān)鍵字__asm聲明的嵌入式匯編程序,在編譯時(shí)將作為整個(gè)文件體傳遞給ARM匯編器。傳遞過(guò)程中,__asm函數(shù)的順序保持不變(用模板實(shí)例生成的函數(shù)除外)。正是由于嵌入式匯編的這個(gè)特性,使得由一個(gè)__asm標(biāo)識(shí)的嵌入式匯編程序調(diào)用在同一文件中的另一個(gè)嵌入式匯編程序是可以實(shí)現(xiàn)的。
當(dāng)使用編譯器armcc時(shí),局部鏈接器(PartialLink)將匯編程序產(chǎn)生的目標(biāo)文件與編譯C程序的目標(biāo)文件相結(jié)合,產(chǎn)生單個(gè)目標(biāo)文件。
編譯程序?yàn)槊總€(gè)__asm函數(shù)生成AREA命令。例如,以下__asm函數(shù):
#includecstddef>
structX{intx,y;voidaddto_y(int);};
__asmvoidX::addto_y(int){
LDRr2,[r0,#__cpp(offsetof(X,y))]
ADDr1,r2,r1
STRr1,[r0,#__cpp(offsetof(X,y))]
BXlr
}
對(duì)于此函數(shù),編譯程序生成:
AREA||.emb_text||,CODE,READONLY
EXPORT|_ZN1X7addto_yEi|
#linenumfile
|_ZN1X7addto_yEi|PROC
LDRr2,[r0,#4]
ADDr1,r2,r1
STRr1,[r0,#4]
BXlr
ENDP
END
由上面的例子可以看出,對(duì)于變量offsetof的使用必須加__cpp()標(biāo)識(shí)符才能引用,因?yàn)樵撟兞渴窃赾stddef頭文件中定義的。
由__asm聲明的常規(guī)函數(shù)被放在名為.emb_text的段(Section)中。這一點(diǎn)也是嵌入式匯編和內(nèi)聯(lián)匯編最大的不同。相反,隱式實(shí)例模板函數(shù)(ImplicitlyInstantiatedTemplateFunction)和內(nèi)聯(lián)匯編函數(shù)放在與函數(shù)名同名的區(qū)域(Area)內(nèi),并為該區(qū)域增加公共屬性。這就確保了這類(lèi)函數(shù)的特殊語(yǔ)義得以保持。
由于內(nèi)聯(lián)和模板函數(shù)的區(qū)域的特殊命名,所以這些函數(shù)不按照文件中定義的順序排列,而是任意排序。因此,不能以__asm函數(shù)在原文件中的排列順序,來(lái)判斷它們的執(zhí)行順序,也就是說(shuō),即使兩個(gè)連續(xù)排列的__asm函數(shù),也不一定能順序執(zhí)行。
5.關(guān)鍵字__cpp
可用__cpp關(guān)鍵字從匯編代碼中訪(fǎng)問(wèn)C或C++的編譯時(shí)常量表達(dá)式,其中包括含有外部鏈接的數(shù)據(jù)或函數(shù)地址。標(biāo)識(shí)符__cpp內(nèi)的表達(dá)式必須是適合用作C++靜態(tài)初始化的常量表達(dá)式(請(qǐng)參閱ISO/IEC14882:1998中的3.6.2非本地對(duì)象初始化一節(jié)和本書(shū)的常量表達(dá)式一節(jié))。
編譯時(shí),編譯器將使用__cpp(expr)的地方用匯編程序可以使用的常量所取代。例如:
LDRr0,=__cpp(some_variable)
LDRr1,=__cpp(some_function)
BL__cpp(some_function)
MOVr0,#__cpp(some_constant_expr)
__cpp表達(dá)式中的名稱(chēng)可在__asm函數(shù)的C++上下文中查閱。__cpp表達(dá)式結(jié)果中的任何名稱(chēng)按照要求被損毀并自動(dòng)為其生成IMPORT語(yǔ)句。
6.手動(dòng)重復(fù)解決方案
可以在嵌入式匯編中使用C++轉(zhuǎn)換為非虛擬函數(shù)調(diào)用解決重復(fù)。例如:
voidg(int);
voidg(long);
structT{
intmf(int);
intmf(int,int);
};
__asmvoidf(T*,int,int){
BL__cpp(static_castint(T::*)(int,int)>(T::mf))//callsT::mf(int,int)
BL__cpp(static_castvoid(*)(int)>(g))//callsg(int)
MOVpc,lr
}
c語(yǔ)言相關(guān)文章:c語(yǔ)言教程
c++相關(guān)文章:c++教程
評(píng)論