金微
摘 要:隨著網(wǎng)絡(luò)與通信技術(shù)的發(fā)展,正在涌現(xiàn)出大量新的嵌入式系統(tǒng),通常情況用C或者C++完成大部分的編程任務(wù),僅有初始化部分用匯編語言完成。本文主要研究匯編語言和C語言混合編程,在當(dāng)前程序開發(fā)領(lǐng)域提供了新的途徑。
關(guān)鍵詞:匯編程序;C語言;編排技術(shù)
1 引言
在平常編寫程序時(shí),我們一般都希望選擇C、Pascal、Basic等這樣的高級語言來編寫,高級語言由于有編譯器的支持,它們的語法更接近于自然語言,表達(dá)能力強(qiáng),使用靈活,具有強(qiáng)大的庫函數(shù),更重要的是高級語言與機(jī)器無關(guān),可移殖性較好,這樣使程序開發(fā)周期比較短,省時(shí)省力。為了提高程序運(yùn)行速度,或直接訪問硬件,用匯編語言編程可以提高程序的運(yùn)行效率。為了既能縮短程序開發(fā)周期,又能保證程序的執(zhí)行效率,較好的解決辦法是程序的框架或主體部分用C語言編寫,要求執(zhí)行效率高的部分用匯編語言編寫。這里就涉及到了混合編程的問題,這種混合編程的方法將C語言和匯編語言的優(yōu)點(diǎn)結(jié)合起來,所以成為目前單片機(jī)開發(fā)最流行的編程方法?;旌暇幊痰年P(guān)鍵是解決好高級語言與匯編語言的接口問題,可采用兩種方法:一是使用嵌入式匯編,即在高級語言的語句中直接使用匯編語句,這種方法比較簡潔直觀,但功能較弱;另一種方法是獨(dú)立編程,分別產(chǎn)生各自的目標(biāo)文件,然后經(jīng)過連接,形成一個(gè)完整的程序。
2 匯編語言和C語言程序的變量相互調(diào)用
在一個(gè)工程中,一般都會由多個(gè)匯編文件和多個(gè)C/C++程序文件有機(jī)組成。在這些匯編文件和C/C++文件之間就存在變量相互訪問和函數(shù)相互調(diào)用的問題。內(nèi)嵌匯編不用單獨(dú)編輯匯編語言文件,比較簡潔,但是有諸多限制,當(dāng)匯編的代碼較多時(shí)一般放在單獨(dú)的匯編文件中。這時(shí)就需要在匯編和C之間進(jìn)行一些數(shù)據(jù)的傳遞,最簡便的辦法就是使用全局變量。
2.1 匯編程序中訪問C程序變量
在C/C++程序中聲明的全局變量可以被匯編程序通過地址間接訪問。具體訪問方法/步驟如下:
①C/C++程序中聲明全局變量;②在匯編程序使用IMPORT/EXTERN偽指令聲明引用該全局變量;③使用LDR偽指令讀取該變量的內(nèi)存地址;④根據(jù)該數(shù)據(jù)的類型使用相應(yīng)的LDR或STR指令讀取或設(shè)置該變量的值。對于無符號變量,使用LDRB/STRB訪問char;使用LDRH/STRH訪問short;使用LDR/STR訪問integer。對于有符號數(shù),使用LDRSB/LDRSH。
在匯編的源程序中調(diào)用C語言風(fēng)格的字符串需要使用IMPORT偽操作。IMPORT相當(dāng)于C語言中的extern關(guān)鍵字,告訴編譯器引用的符號不是在本文件中定義的,而是在其他的源文件中定義的。
偽操作的格式:
IMPORT symbol[,WEAK]
symbol是聲明的符號的名稱;[,WEAK]指示編譯器如果發(fā)現(xiàn)symbol在所有的源文件中都沒有找到,那么它也不會產(chǎn)生任何的錯(cuò)誤信息。
2.2 C程序中訪問匯編程序變量
在匯編程序中聲明的數(shù)據(jù)可以被C/C++程序所訪問,具體訪問方法/步驟是:在匯編程序中用EX-PORT/GLOBAL偽指令聲明該符號為全局標(biāo)號,可以被其他文件應(yīng)用;C/C++程序中定義相應(yīng)數(shù)據(jù)類型的指針變量;對該指針變量賦值為匯編程序中的全局標(biāo)號,利用該指針訪問匯編程序中的數(shù)據(jù)。
3 匯編語言和C語言程序相互調(diào)用
3.1 在C程序中調(diào)用匯編函數(shù)
在C程序中調(diào)用匯編函數(shù)一般情況下,在C中要調(diào)用一個(gè)匯編編寫的函數(shù),需要首先在C語言中聲明此函數(shù)的函數(shù)原型,同時(shí)C語言希望所有的外部標(biāo)號均以下劃線/_0開頭,如果匯編模塊中定義的函數(shù)及變量準(zhǔn)備供C調(diào)用,應(yīng)以下劃線開頭。如若有函數(shù)F_Sub,要定義為供C調(diào)用的函數(shù),在匯編程序中應(yīng)定義為PUBLIC _F_Sub。因?yàn)镃語言區(qū)別對待大小寫字母,所以在編寫準(zhǔn)備與C模塊相連接的匯編模塊時(shí),應(yīng)該注意符號名的大小寫,以便保持一致。以下是在C中調(diào)用匯編程序的實(shí)例:
//C語言主函數(shù)main()
void F_Sub(void); //聲明要調(diào)用的函數(shù)的函數(shù)原型,此函數(shù)無參數(shù)傳遞
intmain(void){
while(1)
F_Sub(); //調(diào)用匯編函數(shù)
return 0;
}
//匯編子函數(shù)F_Sub()
.CODE
. PUBLIC _F_Sub
_F_Sub:
NOP
RETF
以上程序在IDE集成開發(fā)環(huán)境下編譯連接后即可運(yùn)行。
3.2 在匯編程序中調(diào)用C函數(shù)
在匯編函數(shù)中要調(diào)用C語言的子函數(shù),應(yīng)該根據(jù)C函數(shù)原型所要求的參數(shù)類型,分別把參數(shù)壓入堆棧后,再調(diào)用C函數(shù)。調(diào)用結(jié)束后還須再進(jìn)行彈棧,以恢復(fù)調(diào)用C函數(shù)前的堆棧指針。以下是匯編調(diào)用C函數(shù)的。
例如下面的程序,利用函數(shù)調(diào)用形式輸出字符串″Hello world e″
Extern void display(void)L
Main()
{
display()L
}
.model small
.data
string db ″Hello world e$″
.code
public _display
_display proc
mov ah,9
mov dx,offset string
int 21h
ret
_display endp
end
說明:①在C程序中使用關(guān)鍵字″e(cuò)xtern″對函數(shù)作顯式說明;②對不同的存儲模式要選用不同的匯編語言格式。當(dāng)C程序?yàn)槲⑿?、小型、緊湊型模式時(shí),匯編用近過程;當(dāng)C程序?yàn)橹行?、大型、巨型模式時(shí),匯編用遠(yuǎn)過程;③匯編程序取C的參數(shù)。遠(yuǎn)過程返回地址占四個(gè)字節(jié),BP壓入占二字節(jié),所以第一個(gè)參數(shù)在BP+6所指向的單元,而近過程第一個(gè)參數(shù)在BP+4所指向的單元;④匯編程序中寄存器的保護(hù)。TurboC允許子過程使用SI 和DI存放局部變量,當(dāng)寄存器變量多于兩個(gè)時(shí),多余部分會自動轉(zhuǎn)到堆棧中存儲。因此,匯編過程的格式為:
PUSH BP
MOV BP,SP
PUSH DI
PUSH SI…
…………
…………
…………
POP SI
POP DI
POP BP
RET
⑤返回值。每種C語言的數(shù)據(jù)類型都有一個(gè)標(biāo)準(zhǔn)的返回位置,一般在AX (微型、小型、緊湊型模式)或DX:AX(中型、大型、巨型模式)中,如:char,unsigned char,short int等,返回值位置為AX,且返回?cái)?shù)據(jù)必須放置在RET指令之前。匯編子程序要定義為遠(yuǎn)過程,并用public偽指令把過程名定義為公共。
4 結(jié)束語
本文研究了匯編語言與C語言混合編程的編程問題,重點(diǎn)對編程時(shí)C語言與匯編語言和C語言變量與程序的相互調(diào)用問題進(jìn)行了分析,并給出了實(shí)例。當(dāng)采用兩種或兩種以上的編程語言組合編程,彼此相互調(diào)用,進(jìn)行參數(shù)傳遞,是一種有效的程序設(shè)計(jì)方法。這種方法可以發(fā)揮各種語言的優(yōu)勢和特點(diǎn),充分利用現(xiàn)有的多種實(shí)用程序、庫程序等,使軟件的開發(fā)周期大大縮短,是當(dāng)前程序接口技術(shù)的一個(gè)重要研究和應(yīng)用領(lǐng)域。
[參考文獻(xiàn)]
[1]沈美明,溫冬嬋.IBM-PC匯編語言程序設(shè)計(jì)[M].北京:清華大學(xué)出版社, 2001.
[2]周學(xué)毛.匯編語言程序設(shè)計(jì)[M].北京:高等教育出版社,2002.
[3]張永,黃建宇,劉治生.C語言與匯編語言混合編程的研究與實(shí)現(xiàn)[J].計(jì)算機(jī)與數(shù)字工程,2006.