一個(gè)應(yīng)用系統(tǒng)的匯編語(yǔ)言源程序,無(wú)論其系統(tǒng)工能的要求簡(jiǎn)單還是復(fù)雜,其程序結(jié)構(gòu)的組成基礎(chǔ)總是由簡(jiǎn)單程序、分支程序、循環(huán)程序、子程序、查表程序等結(jié)構(gòu)化程序塊組合而成。這是匯編語(yǔ)言源程序的設(shè)計(jì)基礎(chǔ)。
(1) 簡(jiǎn)單結(jié)構(gòu)程序
簡(jiǎn)單結(jié)構(gòu)程序又稱順序結(jié)構(gòu)程序,是匯編語(yǔ)言程序設(shè)計(jì)中最基本、最單純的程序,在整個(gè)程序設(shè)計(jì)所占比例最大,是程序設(shè)計(jì)的基礎(chǔ)。這里所說(shuō)的簡(jiǎn)單結(jié)構(gòu)程序是指一種無(wú)分支的直接程序,是按照邏輯操作順序,從第一條指令開(kāi)始逐步條順序執(zhí)行,直到最后一條指令為止??梢?jiàn),簡(jiǎn)單結(jié)構(gòu)程序是指其組織成結(jié)構(gòu)簡(jiǎn)單、程序的邏輯流向是一維的,程序的具體內(nèi)為止??梢?jiàn)簡(jiǎn)單結(jié)構(gòu)程序是指其組成結(jié)構(gòu)簡(jiǎn)單,程序邏輯的邏輯流向是一維的,程序的具體內(nèi)容不一定簡(jiǎn)單,在實(shí)際編程中,如何正確選擇指令,合理使用工作寄存器、節(jié)省存儲(chǔ)單元等,是編寫好程序的基本功。現(xiàn)舉例說(shuō)明。
(2) 分支結(jié)構(gòu)程序
很多復(fù)雜的實(shí)際問(wèn)題,總是伴隨著邏輯判斷,從而選擇不同的處理路徑,即程序的走向,從而使計(jì)算機(jī)能根據(jù)肯定某種智能基礎(chǔ)。
分支程序的主要特點(diǎn)是程序的流向從一個(gè)入口、兩個(gè)或兩個(gè)以上的出口,根據(jù)給定的條件進(jìn)行選擇確定。編程的關(guān)鍵是如何確定供判斷或選擇的條件以及選擇的條件以及選擇合適的分支指令A(yù)T89S52的指令集提供了極為豐富、功臣極強(qiáng)的多種分支指令,特別是比較轉(zhuǎn)移和位判跳指令,給復(fù)雜問(wèn)題,尤其是測(cè)控系統(tǒng)的程序設(shè)計(jì)提供了方便。
分支程序又稱復(fù)雜程序。因?yàn)橐粋€(gè)源程序如果包含有無(wú)數(shù)個(gè)分支,每個(gè)分支均有不同的處理程序段,分支中又包含分支,這就使程序的流向十分復(fù)雜。因此 ,程序設(shè)計(jì)時(shí)必須借助程序流程圖,把復(fù)雜的程序流向展現(xiàn)在平面圖上,使之一目了然。為減少程序的復(fù)雜性,應(yīng)盡力少用分支結(jié)構(gòu)程序。
?、?單分支結(jié)構(gòu)程序
單分支結(jié)構(gòu)在程序設(shè)計(jì)中應(yīng)用最廣,擁有的分支指令了也多,其結(jié)構(gòu)一般為一個(gè)入口兩個(gè)出口。常用的流程圖圖形如圖4.3所示。

單分支結(jié)構(gòu)程序的選擇條件一般由運(yùn)算或檢測(cè)的狀態(tài)標(biāo)志提供,選用對(duì)應(yīng)的條件判跳指令來(lái)實(shí)現(xiàn)。
?、凇《喾种ЫY(jié)構(gòu)程序
在實(shí)際應(yīng)用中,常常需要從兩個(gè)以上的流向(出口)中選一。例如,兩個(gè)數(shù)相比較,必然存在大于、等于、小于三種情況,這時(shí)就需從三個(gè)分支中選一。再如多分支跳轉(zhuǎn)(又稱散轉(zhuǎn))將根據(jù)運(yùn)算結(jié)果值在多分支中選一。這就形成了多分支結(jié)構(gòu)。其流程圖形如圖4.4 所示。

MCS-51單片機(jī)指令集設(shè)有散轉(zhuǎn)指令:
JMP @A+DPTR
其中數(shù)據(jù)指針DPTR為存放轉(zhuǎn)移指令串(S0~Sn)的首地址,由累加器A的內(nèi)
容動(dòng)態(tài)選擇對(duì)應(yīng)的轉(zhuǎn) 指令。因此,可多達(dá)256(n=1~256)個(gè)分支程序中選一。
?、邸》种ЫY(jié)構(gòu)程序的形式
單分支選擇結(jié)構(gòu)程序有以下三種典型形式:
圖4.3:條件成立則執(zhí)行分支程序(1),否則執(zhí)行分支程序(2),兩者選一。圖4.5a:條件成立則跳過(guò)程序段(2),執(zhí)行程序段(3),否則順序執(zhí)行。圖4.5b:條件成立則順序往下執(zhí)行,否則重復(fù)執(zhí)行程序段(1),直至條件成立,程序順序往下執(zhí)行。


(a)
圖4.5單分支結(jié)構(gòu)程序的典型形式
對(duì)于第三種形式,可以程序段(1)重復(fù)執(zhí)行次數(shù)作為判別條件,當(dāng)重復(fù)次數(shù)達(dá)到條件滿足時(shí)停止重復(fù),程序順序往下執(zhí)行,這是分支程序結(jié)構(gòu)的一種特殊形式。其中判別條件也可能是一個(gè)定量或狀態(tài)標(biāo)志,而重復(fù)次數(shù)是不定的,只要條件一滿足,立即停止重復(fù)。也可能條件不滿足時(shí)直接轉(zhuǎn)向判跳指令本身,一旦條件成立,立即結(jié)束。這種方式常用于狀態(tài)檢測(cè)。例如: LOOP:JB P1.X,LOOP;
本例是等待P1.X引腳上的電平出現(xiàn)“1”→“0”的急跳變而結(jié)束循環(huán)等待,程序順序往下執(zhí)行。
分支結(jié)構(gòu)程序允許嵌套,即一個(gè)分支接著一個(gè)分支,形成樹根式多級(jí)分支程序結(jié)構(gòu)。匯編語(yǔ)言程序本身并不限止這種嵌套層次數(shù),但過(guò)多的嵌套層次將使程序結(jié)構(gòu)變得十分復(fù)雜和雍腫,以致造成邏輯上的混亂和錯(cuò)誤,因而應(yīng)盡力避免。

圖4.6循環(huán)程序的典型形式
一個(gè)較復(fù)雜的程序,總是包含多個(gè)分支程序段,為防止分支流向的混亂,應(yīng)采用程序流程圖具體標(biāo)明每個(gè)分支的確切條件和走向。
(3) 循環(huán)結(jié)構(gòu)程序
循環(huán)結(jié)構(gòu)程序是控制主機(jī)多次、重復(fù)執(zhí)行同一個(gè)程序段的一種基本程序結(jié)構(gòu)。從本質(zhì)上講,它是分支結(jié)構(gòu)程序中的一個(gè)特殊形式。由于它在程序設(shè)計(jì)中的重要性,故而配以專用指令,單獨(dú)作為一種程序結(jié)構(gòu)的形式進(jìn)行設(shè)計(jì)。
在某些情況下采用循環(huán)程序結(jié)構(gòu),可使原程序大大縮短和簡(jiǎn)化。例如,利用軟件延時(shí)lms,若采用NOP指令來(lái)實(shí)現(xiàn),當(dāng)fosc=12MHz時(shí),需近1000條NOP指令組成。如果采用循環(huán)結(jié)構(gòu)程序,只需少數(shù)幾條指令即可完成??梢?jiàn)其程序的簡(jiǎn)化效率。
?、?循環(huán)結(jié)構(gòu)程序的組成
循環(huán)結(jié)構(gòu)程序如圖4.6所示,它由下述4個(gè)主要部分組成。
A、初始化部分
程序在進(jìn)入循環(huán)處理程序段部分之前需設(shè)備初值,如循環(huán)次數(shù)、有關(guān)單元清0、變量設(shè)置、地址指針等。
B、循環(huán)處理部分
循環(huán)處理部分又稱循環(huán)程序主體。是循環(huán)結(jié)構(gòu)程序的核心,是循環(huán)執(zhí)行需完成某種功能的主體。
C、循環(huán)控制部分
在重復(fù)執(zhí)行循環(huán)體的過(guò)程中,不斷修改和判斷循環(huán)控制變量,直到符合結(jié)束循環(huán)條件。循環(huán)控制變量可以是循環(huán)遞減計(jì)數(shù)或條件控制。前者是每循環(huán)執(zhí)行一次,控制變量減1,并判是否減為0,若不為0,繼續(xù)執(zhí)行循環(huán)體程序;若控制變量減1后結(jié)果值為0,則結(jié)束循環(huán)程序的執(zhí)行,進(jìn)入結(jié)束處理。這些工作均由循環(huán)指令自動(dòng)完成。后者判別結(jié)束條件上是否成立,例如計(jì)算結(jié)果達(dá)到給定精度要求或達(dá)到某一給定條件時(shí)就結(jié)束循環(huán),這時(shí)的循環(huán)次數(shù)是不固定的。常用條件判跳指令來(lái)完成。
D、結(jié)束處理部分
這是對(duì)循環(huán)程序全部執(zhí)行結(jié)束后的結(jié)果進(jìn)行處理和存儲(chǔ)。
?、?循環(huán)結(jié)構(gòu)程序舉例
有兩條功能極強(qiáng)的循環(huán)轉(zhuǎn)移指令:
DJNZ Rn,rel ;以工作寄存器Rn為控制寄存器
DJNZ direct,rel ;以直接尋址單元作控制寄存器
這兩條基本指令可派生出很多條不同控制計(jì)數(shù)器的循環(huán)轉(zhuǎn)移指令,大大擴(kuò)展了應(yīng)用范圍和多重循環(huán)的層次。
控制計(jì)數(shù)器的計(jì)數(shù)方式一般均為不斷減1計(jì)數(shù)(遞減方式),即每循環(huán)一次,計(jì)數(shù)器自動(dòng)減1計(jì)數(shù),并判控制計(jì)數(shù)器是否為0,若不為0,繼續(xù)執(zhí)行循環(huán);若為0,則結(jié)束循環(huán)程序的執(zhí)行,脫離循環(huán)程序順序往下執(zhí)行。循環(huán)次數(shù)在初始化時(shí)預(yù)置,循環(huán)次數(shù)范圍1-255,如超過(guò)此范圍,則要采用多重循環(huán)方式。多重層次原則上不受限。
?、?多重循環(huán)結(jié)構(gòu)程序
某些復(fù)雜問(wèn)題或者循環(huán)數(shù)超過(guò)256,則需采用多重循環(huán)的程序結(jié)構(gòu),即循環(huán)程序中包含循環(huán)程序或一個(gè)大循環(huán)中包含多個(gè)小循環(huán)程序,稱多重循環(huán)程序結(jié)構(gòu),又稱循環(huán)嵌套。循環(huán)的重?cái)?shù)不限,但必須每循環(huán)的層次分明,不能有相互交叉!
例如:雙重軟件延時(shí)。
START:MOV R3,#DATA1 ;外層循環(huán)計(jì)數(shù)初值
LOOP1:MOV R2, ;內(nèi)層循環(huán)計(jì)數(shù)初值
LOOP2:NOP
NOP
NOP
DJNZ R2,LOOP2 ;(R2)-1≠0,轉(zhuǎn)LOOP2
DJNZ R3,LOOP1 ;(R3)-1≠0,轉(zhuǎn)LOOP1
END ;結(jié)束
此例為典型的二重循環(huán)程序結(jié)構(gòu) ,可根據(jù)實(shí)際需要設(shè)計(jì)任意重循規(guī)蹈矩環(huán)。其執(zhí)行過(guò)程是由內(nèi)向外逐層展開(kāi)。內(nèi)層循環(huán)全部執(zhí)行完后,外層則執(zhí)行一次循環(huán),依此類推。如內(nèi)層循環(huán)次數(shù)為M,外層循規(guī)蹈矩環(huán)次數(shù)為N,則總的循規(guī)蹈矩環(huán)次數(shù)為NM次。
(4) 子程序結(jié)構(gòu)程序
在實(shí)際應(yīng)用中常會(huì)遇到帶有通用性的問(wèn)題,例如,數(shù)制轉(zhuǎn)換、浮點(diǎn)運(yùn)算等,且在同一個(gè)源程序中可能需多次用到。這就應(yīng)該把它單獨(dú)設(shè)計(jì)成通用子程序供隨時(shí)調(diào)用,這樣可使程序緊湊,縮短程序長(zhǎng)度,調(diào)試方便。從執(zhí)行時(shí)間看,每調(diào)用一次需附加斷點(diǎn)保護(hù)、參量進(jìn)棧、出棧等開(kāi)銷。
① 子程序結(jié)構(gòu)
能供調(diào)用的子程序,其結(jié)構(gòu)應(yīng)具備:
A、必須標(biāo)明子程序的入口地址,又稱首地址,以便再教育程序調(diào)用;
B、必須以返回指令RET結(jié)束子程序。
在匯編語(yǔ)言源程序中調(diào)節(jié)器用子程序時(shí),一般應(yīng)注意兩個(gè)問(wèn)題:參數(shù)傳遞和現(xiàn)場(chǎng)保護(hù)。
在使用調(diào)用指令不附帶任何參數(shù)時(shí),參數(shù)的互相傳遞要由設(shè)計(jì)者通過(guò)程序安排。一般可采用以下方法:
A、傳遞數(shù)據(jù)。將需傳遞的參數(shù)通過(guò)工作寄存器Rn或累加器A傳遞給子程序。即在主程序調(diào)用子程序前將參數(shù)差額主選定的工作寄存器組R0~R7、累加器A中,供子程序讀取或者將參數(shù)在調(diào)用前先壓入堆棧,進(jìn)入子程序后再?gòu)亩褩V凶x出。
B、傳遞地址。將要傳遞的參數(shù)存放在數(shù)據(jù)存儲(chǔ)器中,將其地址通過(guò)工作寄存器R0、R1或數(shù)據(jù)指針DPTR傳遞,供子程序讀取參數(shù)。
主程序的現(xiàn)場(chǎng)保護(hù)和恢復(fù)。子程序(包括中斷服務(wù)程序)是個(gè)獨(dú)立的程序段,在子程序執(zhí)行過(guò)程中常需用到通用單元,例如:工作寄存器R0~R7、累加器A、數(shù)據(jù)指針DPTR,以及有關(guān)標(biāo)志、狀態(tài)位等。而這個(gè)單元中的原內(nèi)容在調(diào)用子程序結(jié)束之后 的主程序中仍有用,需進(jìn)行保護(hù),稱現(xiàn)場(chǎng)保護(hù)。在執(zhí)行完子程序并返回繼續(xù)執(zhí)行主程序前應(yīng)恢復(fù)其原內(nèi)容,稱現(xiàn)場(chǎng)恢復(fù)。一般有兩種現(xiàn)場(chǎng)保護(hù)/恢復(fù)方式:
A、調(diào)用前保護(hù)、返回后恢復(fù)。這種方式是在主程序邏輯的調(diào)節(jié)器用指令前進(jìn)行現(xiàn)場(chǎng)保護(hù),在調(diào)用指令之后,即返回原斷點(diǎn)處進(jìn)行恢復(fù)現(xiàn)場(chǎng)。其程序結(jié)構(gòu)如下所示:
主程序
PUSH PSW ;將PSW、A、DPTR等入棧保護(hù)
PUSH ACC
PUSH B
PUSH DPL
PUSH DPH
PUSH PSW,#10H ;選用工作寄存器組2,將0組保護(hù)
LCALL addr16 ;調(diào)用子程序addr16
POP DPH ;出棧
POP DPL
POP B
POP ACC
POP PSW
這種結(jié)構(gòu)靈活,可根據(jù)實(shí)際需要實(shí)現(xiàn)現(xiàn)場(chǎng)保護(hù)/恢復(fù)。
B、調(diào)用后保護(hù)、返回前恢復(fù)。這種結(jié)構(gòu)是在子程序的開(kāi)始部分進(jìn)行現(xiàn)場(chǎng)保護(hù),而在子程序的結(jié)束部分、返回指令前恢復(fù)。其程序結(jié)構(gòu)如下所示:
ADDR:PUSH PSW ;子程序現(xiàn)場(chǎng)保護(hù)
PUSH ACC
PUSH B
PUSH DPL
PUSH DPH
MOV PSW,#08H ;選用工作寄存器組1,0組保護(hù)
…………… ;子程序主體
POP DPH ;現(xiàn)場(chǎng)恢復(fù)
POP DPL
POP B
POP ACC
POP PSW
RET ;返回
這是子程序標(biāo)準(zhǔn)格式,現(xiàn)場(chǎng)保護(hù)/恢復(fù)內(nèi)容固定,但程序規(guī)范、清晰。
上述兩種方式可由設(shè)計(jì)者任選。
② 子程序特性
隨著匯編語(yǔ)言程序設(shè)計(jì)技術(shù)的發(fā)展,子程序的應(yīng)用越顯重要。因此,對(duì)子程序的設(shè)計(jì)具有較高要求,除通常在程序設(shè)計(jì)中應(yīng)遵循的原則外,還應(yīng)具備以下特性:
A、通用性
嚴(yán)格講,子程序有通用和專用兩種。前者如數(shù)制轉(zhuǎn)換、浮點(diǎn)運(yùn)算等子程序可廣泛應(yīng)用于同系列單片機(jī)的任何應(yīng)用系統(tǒng),后者僅限用于同一個(gè)應(yīng)用系統(tǒng)中。特別是前者,都應(yīng)注意子程序的通用性。
子程序中某些可變的量稱為參量,這些參量在子程序的定義中是“啞變量”,占用一定的變量單元,每次調(diào)用均由實(shí)際變量或數(shù)據(jù)賦值。因此,一個(gè)子程序可以對(duì)不同的變量或參數(shù)進(jìn)行處理。為了使子程序具有通用性,在設(shè)計(jì)中要解決的一個(gè)重要問(wèn)題,就是確定哪些變量作為參量以及何傳遞參量。
B、可浮動(dòng)性
可浮動(dòng)性是指子程序段可安置在程序存儲(chǔ)器的任何區(qū)域。為此,在子程序中應(yīng)避免選用絕對(duì)轉(zhuǎn)移地址。
C、可遞歸和可重入性
子程序能自己調(diào)用自己和同時(shí)能被多個(gè)任務(wù)(或多個(gè)用戶程序)調(diào)用的特性,分別稱之為子程序的可遞歸性和可重入性。這類子程序常在龐大而復(fù)雜的程序中應(yīng)用,在單片機(jī)應(yīng)用程序設(shè)計(jì)中較少用到。
D、子程序說(shuō)明文件
對(duì)于通用子程序,為便于各種應(yīng)用程序的選用,要求在子程序編制、調(diào)試完成后應(yīng)提供一個(gè)說(shuō)明文件。其內(nèi)容應(yīng)包含以下內(nèi)容。
Ø ·子程序名。標(biāo)明子程序功能的名稱。
Ø ·子程序功能。簡(jiǎn)要說(shuō)明子程序能完成的主要功能,包括重要算法、參量要求及有關(guān)存儲(chǔ)單元配置等。
Ø ·子程序調(diào)用。指明本子程序還需調(diào)用哪些子程序。
Ø ·附子程序流程圖及程序清單。
由于子程序結(jié)構(gòu)在程序設(shè)計(jì)中應(yīng)用極為普遍,因此,一般在指令集中均設(shè)有子程序調(diào)用指令。AT89S系列的指令集中,考慮到程序存儲(chǔ)器空間的限制和節(jié)省,特設(shè)置了絕對(duì)調(diào)用和長(zhǎng)調(diào)兩條指令,供實(shí)際應(yīng)用時(shí)選擇。
?、邸∽映绦蚺e例
子程序的設(shè)計(jì)除它本身的特殊性外,其余完全同典型程序設(shè)計(jì)要求,只是其功能單一、程序量小、結(jié)構(gòu)簡(jiǎn)單、易于編制與調(diào)試。通常它總是只完成整個(gè)任務(wù)中的某一個(gè)單一而獨(dú)立的,又需多次調(diào)用的部分功能。如任務(wù)中的 DELAY 程序段為延時(shí)子程序。
(5) 查表結(jié)構(gòu)程序
在很多情況下,直接通過(guò)查表方式求得的值(變量的值)比通過(guò)計(jì)算解決要簡(jiǎn)單、方便得多,而且速度快,實(shí)時(shí)性強(qiáng)。有些數(shù)值轉(zhuǎn)換,例如八段顯示編碼與顯示數(shù)值必須經(jīng)過(guò)轉(zhuǎn)換,都需通過(guò)查表程序來(lái)實(shí)現(xiàn)。為此,AT89S系列的指令集專門提供了如下查表指令:
MOVC A,@A+DPTR和MOVC A,@A+PC
待查的表數(shù)一般是一串有規(guī)律、按順序排列的固定常量。因此,常把它固化在程序存儲(chǔ)器的數(shù)據(jù)區(qū)域,所以MOVC指令是專訪程序存儲(chǔ)器表格類數(shù)據(jù)的指令。編程時(shí)可很方便地通過(guò)DB偽指令對(duì)指定的存儲(chǔ)單元設(shè)置不同:選用DPTR為首地址指針時(shí)表格參量可存放在64KB范圍內(nèi)的任何區(qū)段,可供無(wú)限次查表,選用PC當(dāng)前值為首地址指針時(shí)表硌參量必須設(shè)置在緊跟查表指令(MOVC)之后,基本上只能一次性查表,編程時(shí)應(yīng)根據(jù)實(shí)際情況進(jìn)行選擇,一般以選擇DPTR為基址指針的查表指令靈活、方便,可省去一些麻煩。
選用DPTR作為基地址的查表指令時(shí),其操作可分3步進(jìn)行:
A、將待查表格的首地址置入DPTR基址寄存器;
B、將待查的表格具體項(xiàng)數(shù)值置入變址寄存器A中;
C、執(zhí)行指令
MOVC A,@A+DPTR
將查表結(jié)果值讀入累加器A中。
選用PC當(dāng)前值作為基地址的查表指令時(shí),由于PC的當(dāng)前值正是查表指令的下一條指令的第一個(gè)字節(jié)的地址值,亦即表格數(shù)據(jù)串的首地址,當(dāng)執(zhí)行完查表指令,讀取到表格數(shù)據(jù)后仍需從這個(gè)PC的當(dāng)前值繼續(xù)往下執(zhí)行,顯然兩者發(fā)生重疊,為解決這個(gè)矛盾,勢(shì)必將表格下移若干個(gè)字節(jié),以便設(shè)置一條跳轉(zhuǎn)指令跳過(guò)表格串繼續(xù)安排順序往下執(zhí)行的程序。把表格串下移的字節(jié)數(shù)加到變址寄存器A中,即在查表指令前加一條指令。
ADD A,#data
A中為經(jīng)動(dòng)態(tài)運(yùn)算得到的待查表格數(shù)的項(xiàng)數(shù)。Data為表格串下移的字節(jié)數(shù),亦即PC的當(dāng)前值到下移后的表格串首地址的距離數(shù)。這個(gè)距離數(shù)顯然不宜太大,因?yàn)樗鼘⒂绊懕砀翊拈L(zhǎng)度,兩者之和不能超過(guò)565B,這種表格一般屬一次性查找,因?yàn)镻C的當(dāng)前值隨程序的執(zhí)行而改變。
如任務(wù)中查找字型碼,就是采用查表程序?qū)崿F(xiàn)的。它先建立了TABLE表格,利用
MOV DPTR,#TABLE 確定表格首址,再用MOV A,@A+DPTR指令查表。
以上介紹了幾種組成源程序設(shè)計(jì)的基要結(jié)構(gòu),一般單片機(jī)應(yīng)用程序不管如何復(fù)雜,都是這幾種基本程序結(jié)構(gòu)的有機(jī)組合。在充分掌握這幾種基本程序結(jié)構(gòu)的基礎(chǔ)上,結(jié)合具體算法,施展程序設(shè)計(jì)技巧,就能設(shè)計(jì)出符合要求的、正確可靠、具有較高水平的優(yōu)秀程序。
(6) 單片機(jī)源程序的基本格式
由于不同類型的單片機(jī)系列因有關(guān)資源的地址分配不同,故而其對(duì)應(yīng)的源程序格式也各不相同。對(duì)于51系列單片機(jī),因其中斷矢量被設(shè)置在程序存儲(chǔ)器的0003H~0033H地址區(qū)域、而源程序的起始地址又必須從0000H單元開(kāi)始,因而源程序的首條指令設(shè)置在0000H~0002H單元,而且必是跳轉(zhuǎn)指令,以跳過(guò)中斷矢量地址區(qū)域,開(kāi)始主程序的順序執(zhí)行。這是由51系列單片機(jī)的硬件結(jié)構(gòu)所決定的。
在單片機(jī)的指令集中,無(wú)程序啟動(dòng)運(yùn)行指令,系統(tǒng)復(fù)位后立即啟動(dòng)并開(kāi)始執(zhí)行應(yīng)用系統(tǒng)源程序,由于復(fù)位后的程序存儲(chǔ)器指針PC值為0000H,所以程序必定從0000H單元開(kāi)始執(zhí)行。為此,在000H~0002H三個(gè)單元專門用于設(shè)置一條跳轉(zhuǎn)指令(長(zhǎng)跳轉(zhuǎn)LJMP屬三字節(jié)指令),從而滿足源程序既從0000H存儲(chǔ)單元開(kāi)始啟動(dòng)并執(zhí)行,又跳過(guò)中斷矢量地址區(qū)域段,跳轉(zhuǎn)到應(yīng)用系統(tǒng)主程序順次執(zhí)行。
在中斷矢量地址區(qū)段,由于分配給每個(gè)中斷服務(wù)程序的地址空間只有8個(gè)存儲(chǔ)單元,一般是不夠用的。實(shí)際應(yīng)用中也常安排一條跳轉(zhuǎn)指令,從中斷矢量處跳轉(zhuǎn)到對(duì)應(yīng)的中斷服務(wù)程序去執(zhí)行。這樣,一般中斷服務(wù)程序總是安排在主程序的高地址方向空余的存儲(chǔ)器區(qū)域。此外,一個(gè)應(yīng)用系統(tǒng)軟件,總有若干個(gè)子程序供主程序調(diào)用,一般也都安排在程序存儲(chǔ)器高地址方向,主程序地址空間之外空余的地址單元區(qū)段。
有些應(yīng)用系統(tǒng)軟件,常有一些固定的表格參數(shù)存放在程序存儲(chǔ)器中,例如LED顯示編碼等,以供主程序或子程序等查用,一般也安排在主程序之后的高地址方向區(qū)段。
因此,任一個(gè)51系列單片機(jī)的應(yīng)用系統(tǒng)源程序,其基本地址空間可劃分為:中斷矢量地址空間段、主程序地址空間段、中斷服務(wù)程序和了程序地址空間段、固定表格參數(shù)地址空間段四部分。除中斷矢量地址實(shí)間是固定的外,其作均應(yīng)視程序量和執(zhí)行方便等任意分配地址空間,其順序也不受此限制。
1) 單片機(jī)應(yīng)用系統(tǒng)源程序的基本格式及其部分地址分配如下例所示:
ORG 0000H
LJMP START ;轉(zhuǎn)向主程序
ORG 0003H
LJMP INTE0 ;轉(zhuǎn)向外中斷0服務(wù)子程序
ORG 000BH
LJMP INTTFO ;轉(zhuǎn)向定時(shí)/計(jì)數(shù)器0服務(wù)子程序
…… ;可按實(shí)際需要設(shè)置服務(wù)子程序
ORG 0030H
START:MOV A,#00H ;主程序從0030H單元開(kāi)始
MOV R1,#data
MOV R0,#00H
DJNZ R1,LOOP0
…… ;初始化程序段
…… ;主程序主體區(qū)段
ORG 3100H
A0: … ;子程序A0
RET
A1 … ;子程序A1
RET
……
ORG 3100h
INTIE0: ;外部中斷0中斷服務(wù)程序
RETI
ORG 4800H
INTTFO: ;定時(shí)/計(jì)數(shù)器0中斷服務(wù)程序
RETI
…… ;其他中斷服務(wù)程序段
ORG 5500H
DBL0:DB 43,56, ;}固定表格參量區(qū)段
END ;結(jié)束
上例中的地址分配是為了便于示例。在實(shí)際應(yīng)用中應(yīng)根據(jù)具體情況而定。在主程序段應(yīng)包含有關(guān)單元清0、方式選擇、參數(shù)設(shè)置以及有關(guān)部分的初始化程序等。主程序是整個(gè)源程序的核心、主體、其他程序段均從屬于它,必須切實(shí)設(shè)計(jì)好主程序。其他程序段的具體格格不入與要求,已于前述。這里就不再述/
由于單片機(jī)特定的應(yīng)用環(huán)境,其源程序設(shè)計(jì)定型付諸實(shí)際應(yīng)用后,一般不再改變,而且多為周面復(fù)始運(yùn)行。因此,它一般均固化于程序存儲(chǔ)器(ROM)中。這是與典型微型計(jì)算機(jī)的主要區(qū)別之一。
