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