凌藝春,黃 飛
(廣西工業(yè)職業(yè)技術(shù)學(xué)院,南寧 530001)
眾所周知,匯編語(yǔ)言是面向機(jī)器的低級(jí)語(yǔ)言,是為特定的計(jì)算機(jī)或系列計(jì)算機(jī)專門(mén)設(shè)計(jì)的。匯編語(yǔ)言的本質(zhì)與機(jī)器語(yǔ)言相同,保持了機(jī)器語(yǔ)言直接和簡(jiǎn)捷的優(yōu)點(diǎn),可有效地訪問(wèn)、控制計(jì)算機(jī)諸如存儲(chǔ)器、CPU、I/O端口等多種硬件設(shè)備。匯編語(yǔ)言的指令采用了英文縮寫(xiě)的標(biāo)識(shí)符,容易識(shí)別和記憶。編程者在編寫(xiě)程序時(shí)需要將每一步的操作用指令的形式寫(xiě)出來(lái),因此匯編語(yǔ)言能夠?qū)芏嚓P(guān)鍵要求做更為準(zhǔn)確的控制,避免因線程共同訪問(wèn)或者硬件設(shè)備共享引起的鎖死,能夠根據(jù)特定的應(yīng)用對(duì)代碼做最佳的優(yōu)化,提高運(yùn)行速度。由于匯編程序的每一句指令只能對(duì)應(yīng)實(shí)際操作過(guò)程中的一個(gè)很細(xì)微的動(dòng)作,因此匯編源程序一般比較冗長(zhǎng)、復(fù)雜、容易出錯(cuò)。相對(duì)高級(jí)語(yǔ)言,匯編編譯器不能夠把其它指令集的匯編源代碼編成本指令集的機(jī)器碼,因此匯編語(yǔ)言的移植不好。在國(guó)內(nèi)有許多學(xué)者做過(guò)匯編語(yǔ)言移植性的研究,成果雖然不少,但真正實(shí)用的卻不多。筆者從事匯編編程教育工作及應(yīng)用匯編語(yǔ)言從事開(kāi)發(fā)工作多年,積累了大量匯編編程經(jīng)驗(yàn),在匯編編程移植性的研究上也頗有心得,筆者下面就在單片機(jī)應(yīng)用領(lǐng)域,從匯編程序結(jié)構(gòu)標(biāo)準(zhǔn)化、子程序模型標(biāo)準(zhǔn)化方面入手,提出由匯編程序結(jié)構(gòu)標(biāo)準(zhǔn)化和子程序模型標(biāo)準(zhǔn)化兩個(gè)方面構(gòu)成的匯編程序模塊共識(shí)標(biāo)準(zhǔn)概念,并研究其移植實(shí)用性。
匯編程序的特點(diǎn)決定了匯編編程極其容易實(shí)現(xiàn)個(gè)性化,因此編寫(xiě)的程序在結(jié)構(gòu)上五花八門(mén),難以統(tǒng)一。匯編程序結(jié)構(gòu)到底能不能規(guī)范,以實(shí)現(xiàn)相對(duì)簡(jiǎn)潔易懂的結(jié)構(gòu)標(biāo)準(zhǔn)呢?筆者認(rèn)為完全可以,而且認(rèn)為匯編程序結(jié)構(gòu)標(biāo)準(zhǔn)化是實(shí)現(xiàn)匯編程序模塊共識(shí)標(biāo)準(zhǔn)移植的第一步。下面提出一個(gè)參考的匯編程序標(biāo)準(zhǔn)化結(jié)構(gòu)圖如圖1所示。
1.1.1 定義部分
這部分程序放在整個(gè)程序的開(kāi)始,在不同的匯編程序結(jié)構(gòu)模型中定義部分的編寫(xiě)基本一樣,其內(nèi)容主要包含對(duì)使用到的隨機(jī)存儲(chǔ)器(RAM)進(jìn)行字節(jié)定義和位定義。
1.1.2 程序開(kāi)始及主程序跳轉(zhuǎn)
在模型中,這部分程序放在程序定義部分之后,其任務(wù)主要是對(duì)程序及主程序跳轉(zhuǎn)在程序存儲(chǔ)器(ROM)中的存放進(jìn)行定位。實(shí)際匯編編程中需不需要主程序跳轉(zhuǎn)部分視程序前后的銜接而定。在推出的模型中,把主程序跳轉(zhuǎn)部分作為一個(gè)環(huán)節(jié)加以保留,主要是想在保持程序結(jié)構(gòu)的明了、易懂的前提下實(shí)現(xiàn)靈活。
1.1.3 中斷部分
這部分程序包含了兩大部分,第一部分是中斷入口及中斷跳轉(zhuǎn),安排在程序開(kāi)始及主程序跳轉(zhuǎn)之后,第二部分是中斷服務(wù)程序群,安排在主程序部分之后。本結(jié)構(gòu)考慮了不同的CPU,所以給出了N個(gè)中斷。
在實(shí)際應(yīng)用中,不同的項(xiàng)目使用的中斷數(shù)量不一樣,有的一個(gè),有的幾個(gè),有的一個(gè)也沒(méi)有,因此這部分程序也與之相應(yīng),有的較短,有的較長(zhǎng),有的沒(méi)有。1.1.4 主程序部分
這部分程序同樣包含了兩大部分,第一部分為程序初始化部分,位置安排在中斷入口及中斷跳轉(zhuǎn)后,其功能是給用到的各個(gè)RAM地址賦值或?qū)σ褂玫膯纹瑱C(jī)內(nèi)部某些功能部件進(jìn)行設(shè)置;第二部分為主程序循環(huán)體部分,位置則在程序初始化部分之后。在實(shí)際任務(wù)中,常把任務(wù)分解成若干連續(xù)的控制,每一控制對(duì)應(yīng)著相應(yīng)的程序,那么若干連續(xù)的控制也就是相應(yīng)的程序串聯(lián),要想獲得持續(xù)的控制,有時(shí)需要反復(fù)地執(zhí)行相應(yīng)的程序,這也就是主程序循環(huán)體部分的功能,有時(shí)只需執(zhí)行一遍便相應(yīng)的程序便可獲得持續(xù)的控制,這種程序循環(huán)體就轉(zhuǎn)變成原地踏步。
1.1.5 子程序群及表格
這部分程序包含了子程序群和各種表格,子程序群實(shí)際上就是在主程序部分和各中斷服務(wù)程序以及各子程序中用到的所有子程序。在實(shí)際應(yīng)用中,各子程序的位置擺放在ROM中可以是隨意的,在這里提出的程序標(biāo)準(zhǔn)化結(jié)構(gòu)推薦以子程序名出現(xiàn)的先后順序安排各子程序的位置。在匯編編程中表格的擺放位置要根據(jù)使用表格的程序而定,放得太遠(yuǎn)就會(huì)超出查表的范圍。因此,在這里推薦將各種表格安插在子程序群中,而且擺放到調(diào)用它的程序附近的位置上。
圖1 匯編程序標(biāo)準(zhǔn)化結(jié)構(gòu)
匯編程序標(biāo)準(zhǔn)化結(jié)構(gòu)是從大量的匯編程序例子研究中提煉出來(lái)的一種結(jié)構(gòu),它的特點(diǎn)是具有廣泛的代表性,符合匯編常識(shí)和規(guī)范,簡(jiǎn)單、易懂、清晰。如:“廣泛的代表性,符合匯編常識(shí)和規(guī)范”主要體現(xiàn)在程序的排序上,在匯編編程中的程序定義、程序開(kāi)始及主程序跳轉(zhuǎn)、中斷入口及中斷跳轉(zhuǎn)、主程序、中斷服務(wù)程序、子程序群及表格等內(nèi)容的排序都與現(xiàn)有的大多數(shù)匯編程序相同,易于形成共識(shí)標(biāo)準(zhǔn),容易為人們所接受。再如:“簡(jiǎn)單、易懂、清晰”主要體現(xiàn)在該結(jié)構(gòu)將程序分成程序定義、中斷、主程序、子程序群及表格四大部分,形成一個(gè)較為簡(jiǎn)單的形式,便于記憶,消除了由于編程者風(fēng)格不一樣,在實(shí)際編程中存在的復(fù)雜、難懂、無(wú)法可依情形。另外,需要加以說(shuō)明的是,匯編程序結(jié)構(gòu)標(biāo)準(zhǔn)化結(jié)構(gòu)雖然給出了一個(gè)較為全面的結(jié)構(gòu),但是在實(shí)際應(yīng)用中要求靈活運(yùn)用,如碰到一些較為簡(jiǎn)單的編程,上面所提及的內(nèi)容不需要,則可以在對(duì)應(yīng)的編排順序上省略該內(nèi)容。
在匯編編程中,子程序的格式較為簡(jiǎn)單,很多人在編寫(xiě)子程序時(shí)較為隨意,容易使編寫(xiě)的子程序條理不清、功能混亂,不利于程序移植。因此編寫(xiě)匯編子程序要提升到標(biāo)準(zhǔn)化的高度才能使子程序具有通用性。子程序模型標(biāo)準(zhǔn)化是實(shí)現(xiàn)匯編程序模塊共識(shí)標(biāo)準(zhǔn)移植的第二步,也是最為關(guān)鍵的一步。如何能實(shí)現(xiàn)子程序具有通用性呢?子程序編寫(xiě)功能化是一條途徑。筆者在這項(xiàng)研究中提出三種基本的子程序功能化結(jié)構(gòu),它們分別是函數(shù)功能結(jié)構(gòu)、延時(shí)結(jié)構(gòu)和混合結(jié)構(gòu)。
這種結(jié)構(gòu)表現(xiàn)為有一個(gè)以上的輸入和有一個(gè)以上的輸出,以及有一個(gè)以上的參與運(yùn)算的中間變量。輸出和輸入的關(guān)系反映了整個(gè)結(jié)構(gòu)的功能。可用如下的圖2模型所示。
圖2 函數(shù)結(jié)構(gòu)
數(shù)學(xué)表達(dá)式為
在單片機(jī)中如何實(shí)現(xiàn)呢?可以使用RAM隨機(jī)存儲(chǔ)空間來(lái)實(shí)現(xiàn),將用戶使用的RAM分成對(duì)應(yīng)的一部輸入用和輸出用,以及參與計(jì)算的中間變量用(有時(shí)子程序沒(méi)有中間變量其原因是編程無(wú)需中間變量)。下面有兩個(gè)MCS-51匯編編程的例子,其中一個(gè)有中間變量,另一個(gè)沒(méi)有中間變量。
『例子1』
子程序名:測(cè)鍵入子程序;輸入:X1= XZK0,X2= ZY-K1,X2= JY-K2;輸出:Y1=(C) ;中間變量:無(wú)。
KEY_TEST: JNB XZ-K0,KEY-TEST-OK
JNB ZY-K1,KEY-TEST-OK
JNB JY-K2,KEY-TEST-OK
CLR C
RET
KEY-TEST-OK:SETB C
RET
『例子2』
子程序名:加1鍵修改子程序;輸入:X1=
SIXTY-ONE-FLAG; 輸出:Y1= SIXTY,Y2=
SIXTY -ONE;中間變量:R1=A。
ADD1:JB SIXTY-ONE-FLAG,ADD1-1
MOV A,SIXTY
INC A
MOV SIXTY,A
LJMP ADD1-END
ADD1_1:MOV A,SIXTY-ONE
INC A
MOV SIXTY-ONE,A
ADD1-END:RET
這種結(jié)構(gòu)沒(méi)有輸入端和輸出端,只有部分中間變量參與計(jì)算,子程序的功能就是為了實(shí)現(xiàn)軟件的延時(shí)。如圖3所示。
圖3 延時(shí)結(jié)構(gòu)
這種結(jié)構(gòu)在匯編程序中很常見(jiàn),也很容易理解。下面就是一個(gè)這種類型的MCS-51匯編編程例子。
『例子3』
子程序名:1MS的延時(shí)子程序;輸入:無(wú);輸出:無(wú);中間變量:R1=A。
這種結(jié)構(gòu)表現(xiàn)為除了有一個(gè)以上的輸入和一個(gè)以上的輸出以及有一個(gè)以上的參與運(yùn)算的中間變量外。還含有一個(gè)以上的內(nèi)部子程序,這些子程序一些可看作輸入,一些可看作輸出,其余的可看作中間變量。輸出和輸入的關(guān)系同樣反映了整個(gè)結(jié)構(gòu)的功能。可用如下的圖4模型所示。
圖4 混合結(jié)構(gòu)
數(shù)學(xué)表達(dá)式為:
這種結(jié)構(gòu)由于含有內(nèi)部子程序,在編程理解上較為復(fù)雜。對(duì)某些內(nèi)部子程序,編程者只是使用其輸出功能,因此這類內(nèi)部子程序在整個(gè)子程序中表現(xiàn)為輸入功能,相當(dāng)一個(gè)輸入端;對(duì)另一些內(nèi)部子程序,編程者則使用其輸入功能,因而這類內(nèi)部子程序表現(xiàn)為輸出功能,相當(dāng)一個(gè)輸出端;編程者有時(shí)還在子程序中使用內(nèi)部延時(shí)子程序,這些延時(shí)子程序在整個(gè)子程序中則相當(dāng)于一個(gè)中間變量。下面就是一個(gè)這種類型的MCS-51匯編編程例子。
『例子4』
子程序名:掃描鍵盤(pán)程序;輸入子程序1:KEY_TEST,輸入子程序2= KEY-SCAN;輸入:無(wú);輸出子程序1= SELECT1, 輸出子程序2=ADD1,輸出子程序3= SUB1;輸出:無(wú);中間變量:R1=CY位,R2=K0-FLAG位,R3=K1-FLAG位,R4=K2-FLAG位。
SCAN_KEY:
LCALL KEY_TEST ;判斷有無(wú)鍵被按下的判斷子程序
JC RETEST
LJMP RETURE1
RETEST: LCALL KEY-SCAN ;設(shè)置對(duì)應(yīng)鍵被按下的標(biāo)志
JB K0-FLAG,PRO-K0
JB K1-FLAG,PRO-K1
JB K2-FLAG,PRO-K2
LJMP RETURE1
PRO-K0: LCALL SELECT1 ;選擇子程
SJMP RETURE1
PRO-K1: LCALL ADD1 ;加1子程
LJMP RETURE1
PRO-K2: LCALL SUB1 ;減1子程
SJMP RETURE1
RETURE1:RET
從前面提出的匯編程序模塊共識(shí)標(biāo)準(zhǔn),不難看出其已經(jīng)形成了較好的移植性。首先由于匯編程序結(jié)構(gòu)標(biāo)準(zhǔn)化,使得匯編編程在程序結(jié)構(gòu)上獲得了一個(gè)相對(duì)固定的結(jié)構(gòu),給編程者一個(gè)清晰可操作的參照,編程趨于統(tǒng)一、明朗和簡(jiǎn)潔,不同項(xiàng)目的匯編編程可以方便地移植程序結(jié)構(gòu)。其次由于子程序模型標(biāo)準(zhǔn)化,原來(lái)子程序編程五花八門(mén)、千變?nèi)f化的形式可以忽略,在子程序編寫(xiě)上只需關(guān)注子程序的功能,按照匯編程序模塊共識(shí)標(biāo)準(zhǔn)對(duì)各種子程序進(jìn)行功能提煉,形成子程序庫(kù)。只要子程序的功能相同,子程序中使用的RAM單元在整個(gè)編程中不沖突,則子程序就可以在匯編程序間相互移植。即使子程序中使用的RAM單元在整個(gè)編程中有沖突,也可以很方便地通過(guò)調(diào)整使用的RAM單元來(lái)完成子程序移植。
綜上所述,匯編程序模塊共識(shí)標(biāo)準(zhǔn)可較好地解決原來(lái)匯編編程移植性差的問(wèn)題,形成了一種相對(duì)簡(jiǎn)單、容易理解、操作方便、移植性好的編程方式。即便對(duì)于不同CPU處理器的匯編程序,只要處理好匯編編程上的命令集和編寫(xiě)結(jié)構(gòu)的差異,也能實(shí)現(xiàn)較好的移植。
筆者多次成功地利用這種編程方式來(lái)解決實(shí)際的項(xiàng)目編程,同時(shí)通過(guò)一些學(xué)術(shù)交流活動(dòng)將這種編程方式推介給同行并獲得認(rèn)可。筆者目前已將匯編程序模塊共識(shí)標(biāo)準(zhǔn)這一內(nèi)容編寫(xiě)成高職高專單片機(jī)匯編編程教材通過(guò)正規(guī)出版社正式出版。
[1] 靳達(dá).單片機(jī)應(yīng)用系統(tǒng)開(kāi)發(fā)實(shí)例導(dǎo)航[M].人民郵電出版社,2003.
[2] 曹巧媛.單片機(jī)原理及應(yīng)用[M].電子工業(yè)出版社,2002.
[3] 施威銘研究室.PIC單片機(jī)輕松入門(mén)[M].清華大學(xué)出版社,2001.
[4] 李朝青.行為引導(dǎo)教學(xué)法在高職實(shí)踐課教學(xué)中的實(shí)踐與研單片機(jī)學(xué)習(xí)輔導(dǎo)測(cè)驗(yàn)及解答講義[M].北京航空航天大學(xué)出版社,2003.
[5] 侯伯民,等.單片機(jī)控制技術(shù)[M].中國(guó)電力出版社,2008.