單片機原理與應用-第四章_第1頁
單片機原理與應用-第四章_第2頁
單片機原理與應用-第四章_第3頁
單片機原理與應用-第四章_第4頁
單片機原理與應用-第四章_第5頁
已閱讀5頁,還剩38頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領

文檔簡介

第四章

匯編語言程序設計

1

所謂程序設計,就是按照給定的任務要求,編寫出完整的計算機程序。要完成同樣的任務,使用的方法或程序并不是唯一的。因此,程序設計的質(zhì)量將直接影響到計算機系統(tǒng)的工作效率、運行可靠性。前面我們學過了匯編語言形式的指令系統(tǒng),本章重點介紹匯編語言程序結(jié)構(gòu)以及如何利用匯編語言指令進行程序設計的方法。

4.1匯編語言程序設計概述24.1.1匯編語言程序設計步驟

使用匯編語言設計一個程序大致上可分為以下幾個步驟。 (1)分析題意,明確要求。 (2)確定算法。(3)畫程序流程圖,用圖解來描述和說明解題步驟。

圖4.1常用的流程圖符號

(4)分配內(nèi)存工作單元,確定程序與數(shù)據(jù)區(qū)的存放地址。

(5)編寫源程序(6)程序優(yōu)化。(7)上機調(diào)試、修改和最后確定源程序。

34.2.2偽指令語句偽指令并不是真正的指令,也不產(chǎn)生相應的機器碼,它們只是在計算機將匯編語言轉(zhuǎn)換為機器碼時,指導匯編過程,告訴匯編程序如何匯編。下面介紹一些MCS-51匯編程序常用的偽指令。(1)匯編起始偽指令ORG格式:[標號:]ORG16位地址功能:規(guī)定程序塊或數(shù)據(jù)塊存放的起始地址。如:ORG8000HSTART:MOVA,#30H……該指令規(guī)定第一條指令從地址8000H單元開始存放,即標號START的值為8000H。4(2)匯編結(jié)束偽指令END格式:[標號:]END[表達式]功能:結(jié)束匯編。例如:ORG2000H START:MOVA,#00H……ENDSTART表示標號START開始的程序段結(jié)束。(3)等值指令EQU格式:字符名稱EQU項例如,TESTEQUR0 MOVA,TEST5(4)定義字節(jié)指令DB格式:[標號:]DB8位二進制數(shù)表DB命令是從指定的地址單元開始,定義若干個8位內(nèi)存單元的內(nèi)容。例如,ORG1000HTAB;DB23H,73,“6”,“B”TABl:DB110B 以上偽指令經(jīng)匯編以后,將對從1000H開始的若干內(nèi)存單元賦值:(1000H)=23H(1001H)=49H(1002H)=36H(1003H)=42H(1004H)=06H其中36H和42H分別是字符6和B的ASCII碼,其余的十進制數(shù)(73)和二進制數(shù)(110B)也都換算為十六進制數(shù)了。6(5)定義字命令DW格式:[標號:]DW16位二進制數(shù)表例如,ORG1000HTAB:DW1234H,0ABH,10 匯編后: (1000H)=12H(1001H)=34H (1002H)=00H(1003H)=ABH(1004H)=00H(1005H)=0AH DB、DW偽指令都只對程序存儲器起作用,不能用來對數(shù)據(jù)存儲器的內(nèi)容進行賦值或進行其它初始化的工作。

74.2順序程序設計

順序結(jié)構(gòu)程序是一種最簡單、最基本的程序(也稱為簡單程序),它是一種無分支的直線形程序,按照程序編寫的順序依次執(zhí)行。【例4-1】兩個8位無符號數(shù)相加,和仍為8位。假設兩個無符號數(shù)X1,X2分別存放于內(nèi)部RAM60H、61H單元中,求其和并將和送入62H單元。程序如下:ORG0000H

CLRC

MOVR0,#60H;設R0為數(shù)據(jù)指針MOVA,@R0;取X11NCR0

ADDCA,@R0;X1+X21NCR0

MOV@R0,A;保存結(jié)果END

8【例4-2】兩個無符號雙字節(jié)數(shù)相加。設被加數(shù)存放在內(nèi)部存儲器30H(高位字節(jié))、31H(低位字節(jié))單元,加數(shù)存放在內(nèi)部存儲器40H(高位字節(jié))、41H(低位字節(jié))單元,和存入30H(高位字節(jié))、31H(低位字節(jié))單元。程序如下:

ORG0000H

CLRC;將C清零MOVR0,#31H;送被加數(shù)首址MOVR1,#41H;送加數(shù)首址MOVA,@R0;取被加數(shù)低字節(jié)

ADDA,@R1;兩個低字節(jié)相加MOV@R0,A;低字節(jié)和存人被加數(shù)低字節(jié)

DECR0;修改指針,指向被加數(shù)高字節(jié)DECR1

;修改指針,指向加數(shù)高字節(jié)MOVA,@R0;取被加數(shù)高字節(jié)

ADDCA,@R1;高字節(jié)相加

MOV@R0,A;存結(jié)果END

9【例4-3】編寫16位二進制數(shù)求補程序二進制數(shù)的求補可歸結(jié)為“求反加1”的過程,求反可用CPL指令實現(xiàn);加1時應注意,加1只能加在低8位的最低位上。因為現(xiàn)在是16位數(shù),有兩個字節(jié),因此要考慮進位問題,即低8位取反加1,高8位取反后應加上低8位加1時可能產(chǎn)生的進位,還要注意這里的加1不能用INC指令,因為INC指令不影響CY標志。程序如下:

ORG0200H

MOVA,R0;低8位送ACPLA;取反ADDA,#01H;加lMOVR2,A;存結(jié)果MOVA,R1;高8位送A

CPLA;取反ADDCA,#00H;加進位MOVR3,A;存結(jié)果END

10【例4-4】編程將20H單元中的8位無符號二進制數(shù)轉(zhuǎn)換成3位BCD碼,并存放在22H(百位)和21H(10位,個位)兩個單元中。程序如下:

ORG1000H

MOVA,20H;取數(shù)送AMOVB,#64H;除數(shù)100送B中DIVAB;商(百位數(shù)BCD碼)在A中,余數(shù)在B中MOV22H,A;百位數(shù)送22HMOVA,B

;余數(shù)送A做被除數(shù)MOVB,#0AH

;除數(shù)10送B中DIVAB;十位數(shù)BCD碼在A中,個位數(shù)在B中

SWAPA;十位數(shù)BCD碼移至高4位ORLA,B;并入個位數(shù)的BCD碼MOV21H,A;十位、個位BCD碼存人21H

END

11分支程序的結(jié)構(gòu)有兩種,如圖4.2所示。

圖4.2分支程序結(jié)構(gòu)

圖4.2(a)結(jié)構(gòu)使用條件轉(zhuǎn)移指令來實現(xiàn)分支,當給出的條件成立時,執(zhí)行程序段A,否則執(zhí)行程序段B。圖4.2(b)結(jié)構(gòu)使用散轉(zhuǎn)指令JMP來實現(xiàn)多分支轉(zhuǎn)移,它首先將分支程序按序號的值來實現(xiàn)分支轉(zhuǎn)移。

12【例4-5】設補碼X放在內(nèi)部RAM30H單元中,函數(shù)Y與X有如下的關系式:

試編寫程序,根據(jù)X的值求出Y,并放回原單元。解取出X后先做取值范圍的判斷,用累加器A狀態(tài)轉(zhuǎn)移指令判斷X是否為0,用位狀態(tài)轉(zhuǎn)移指令判斷X是大于0還是小于0。程序流程圖如圖4.3所示。程序如下:

134.3分支程序設計MOVA,30HJZZER0JNBACC.7,PLUSADDA,#5MOV30H,APLUS:SJMP$ZERO:MOV30H,#20HSJMP$END

14

【例4-6】內(nèi)部RAM40H和41H單元中各有一無符號數(shù),比較其大小,將大數(shù)存放于內(nèi)部RAM60H單元,小數(shù)存放于內(nèi)部RAM61H單元,如兩數(shù)相等,則分別送往這2個單元。 解用比較不等轉(zhuǎn)移指令CJNE比較兩個無符號數(shù),先確定它們是否相等,若不相等時再根據(jù)借位標志確定這兩個無符號數(shù)的大小。程序框圖如圖4.4所示。 程序如下:

15

MOVA,40H

MOV61H,41H

CJNEA,41H,LOOP

AJMPAGEQ

LOOP:

JNCAGEQ;A≥(41H)則無借位

XCHA,61H;A<(41H)有借位AGEQ:MOV60H,A;A與(61H)交換

SJMP$

END

16

【例4-7】某溫度控制系統(tǒng),采集的溫度值(Ta)放在累加器A中。此外,在內(nèi)部RAM54H單元存放控制溫度下限制(T54),在55H單元存放控制溫度上限制(T55)。若Ta>T55,程序轉(zhuǎn)向JW(降溫處理程序);若Ta<T54,則程序轉(zhuǎn)向SW(升溫處理程序);T55≥Ta≥T54,則程序轉(zhuǎn)向FH(返回主程序)。程序如下:

CJNEA,55H,LOOP1;Ta≠T55,轉(zhuǎn)向LOOPl

AJMPFH;Ta=T55,返回LOOPl:JNCJW;若(CY)=0,表明Ta>T55,轉(zhuǎn)降溫處理程序

CJNEA,54H,LOOP2;Ta≠T54,轉(zhuǎn)向LOOP2

AJMPFH;Ta=54,返回LOOP2:JCSW;若(CY)=1,表明Ta<T54,轉(zhuǎn)升溫處理程序FH:RET

;T55≥Ta≥T54,返回主程序17

【例4-8】將ASCII碼制轉(zhuǎn)換為十六進制數(shù)。如果不是十六進制數(shù)得ASCII碼,用戶標志位置1。解:由ASCII碼表知,30H~39H為0~9的ASCII碼,41H~46H為A~F的ASCII碼。在這一范圍的ASCII碼減去37H就可以獲得對應的十六進制。設ASCII碼放在累加器A中,轉(zhuǎn)換結(jié)果放回A中。程序流程圖如圖4.5所示18START:CLCCSUBBA,#30HJCNASCCJNEA,#0AH,NNMM:JCASCSUBBA,#07HCJNEA,#0AH,NNNN:JCNASCCJNEA,#10H,LLLL:JCASCNASC:SETBF0ASC:RET

19【例4-9】N路分支程序,N≤8。要求程序根據(jù)其運行中所產(chǎn)生的寄存器R3的值,來決定如何進行分支。解:為實現(xiàn)N路分支,可以多次使用比較轉(zhuǎn)移指令:CJNER3,#data,rel流程圖如圖4.6所時,但這樣比較次數(shù)太多,當N較大時,執(zhí)行速度就較慢。 我們可以用變址尋址的轉(zhuǎn)移指令JMP@A+DPTR使問題得到解決。首先安排存放一個轉(zhuǎn)移分支入口的地址表,把入口地址表的首地址送到DPTR,再把R3的內(nèi)容送累加器A?,F(xiàn)以4個分支為例寫出程序。假設4個分支的不同功能分別是給不同的位置。程序如下:

20MOVA,R3MOVDPTR,#BRTABMOVCA,@A+DPTRJMP@A+DPTRBRTABDBBR0-BRTABDBBRl-BRTABDBBR2-BRTABDBBR3-BRTABBR0:SETBP1.0SJMPBRKBR1:SETBP1.1SJMPBRKBR2:SETBP1.2SJMPBRKBR3:SETBP1.3BRK:SJMPBRK

214.4循環(huán)程序設計

循環(huán)程序一般由4部分組成。(1)置循環(huán)初值。(2)循環(huán)體。(3)循環(huán)修改。(4)循環(huán)控制。圖4.7(a)結(jié)構(gòu)是“先執(zhí)行后判斷”,適用于循環(huán)次數(shù)已知的情況。圖4.7(b)結(jié)構(gòu)是“先判斷后執(zhí)行”,適用于循環(huán)次數(shù)未知的情況。22

23二、程序清單

ORGOOOOH

START:MOVA,#01H;使L1燈亮,其它不亮LOOP:MOVP1,A;從P1口輸出到發(fā)光二極管

MOVR1,#10H;延時1秒DEL1:MOVR2,#200

DEL2:MOVR3,#126

DEL3:DJNZR3,DEL3

DJNZR2,DEL2

DJNZR1,DEL1

RLA;左移一位,下一個發(fā)光二極管亮

AJMPLOOP;循環(huán)

END

24【例4-10】多個單字節(jié)數(shù)求知。已知有10個單字節(jié)數(shù),依次存放在內(nèi)部RAM40H單元開始的數(shù)據(jù)存儲區(qū)中,求和并將結(jié)果存人寄存器R2、R3中(高位存R2,低位存R3)。本題中,要重復進行加法運算,因此采用循環(huán)結(jié)構(gòu)程序。循環(huán)次數(shù)就是數(shù)據(jù)塊字節(jié)數(shù),這是已知的。在置初值時,將數(shù)據(jù)塊長度置人寄存器R5;將數(shù)據(jù)塊首地址送人寄存器R0,即以R0作為數(shù)據(jù)塊的地址指針,采用間接尋址方式:每做一次加法之后,修改地址指針,以便取出下一個數(shù)來相加,并且使計數(shù)器R5減l。到R5減為0時,求和結(jié)束。程序流程圖如圖4.8所示。

25

ORG2000H

SUM:MOVR0,#40H;設地址指針

MOVR5,#0AH;計數(shù)器初值送R5SUM:MOVA,#00H

MOVR2,A

LP:ADDA,@R0

JNCLP1

INCR2;若有進位,和的高八位+1LP1:INCR0;地址指針+1

DJNZR5,LP;判循環(huán)結(jié)束條件

MOVR3,A;存和的低八位

END

26【例4-11】從內(nèi)存BLOCK單元開始有一個無符號數(shù)的數(shù)據(jù)塊,其長度為LEN,試求出其最大值,并存入MAX單元。 這是一個搜索問題。這里采用依次進行比較和取代的方法來尋找最大值。具體做法是:先取出第一個數(shù)作為基準,和第二個數(shù)比較,若比較結(jié)果基準數(shù)大,不作變動;若比較結(jié)果基準數(shù)小,則用大數(shù)來代替原基準數(shù),然后再和下一個數(shù)作比較。到比較結(jié)束時,基準數(shù)就是所求的最大值。 為了進行兩數(shù)的比較,采用兩數(shù)相減以后判斷CY的值來確定哪個數(shù)大,這比用CJNE指令更簡單。比較時將基準數(shù)放在累加器A中。若A中先放人零,比較次數(shù)等于LEN;若A中先放人第一個數(shù),則比較次數(shù)等于LEN-1。采用R2作為計數(shù)器,R1作為地址指針。程序流程如圖4.9所示。

27

ORG8000H

COMP:CLRA

MOVR2,#LEN

MOVR1,#BLOCK

LOOP:CLRC

;清CY

SUBBA,@R1;用減法作比較

JNCNEXT

;若(A)>((R1)),轉(zhuǎn)移

MOVA,@R1;若(A)<((R1)),則((R1))→(A)

SJMPNEXT1

NEXT:ADDA,@R1;恢復(A)NEXT1:INCR1

DJNZR2,LOOP;判循環(huán)結(jié)束條件

MOVMAX,A;存最大數(shù)

SJMP$

LENEQU0AH

MAXEQU40H

ENDEQU41H

28

圖4.8程序流程圖圖4.9程序流程圖29

【例4-12】假設從內(nèi)存RAM的50H單元,連續(xù)存放一串字符,以回車符(其ASCII碼為0DH)作為結(jié)束標志,要求測出該字符串的長度。測試方法可采用將該字符串的每一個字符與回車符依次相比,若不相等,則將統(tǒng)計字符串長度的計數(shù)器加l,繼續(xù)比較;若比較相等,則表示該字符串結(jié)束,這時計數(shù)器中的值就是字節(jié)符串的長度。

程序如下:ORG8000HCOUNT:MOVR2,#0FFHMOVR0,#4FHLOOP:INCR0INCR2CJNE@R0,#0DH,LOOPSJMP$

30程序中使用指令CJNE@R0,#0DH,LOOP實現(xiàn)字符串比較及控制循環(huán)的任務。由于在循環(huán)體中比較轉(zhuǎn)移之前,將R2和R0的內(nèi)容加1,因此R2和R0的初值要減去1。循環(huán)次數(shù)由對于循環(huán)條件的判定而定,當循環(huán)結(jié)束時,R2中的內(nèi)容就是字符串的長度。

【例4-13】編制用軟件方法延時1S的程序 軟件延時時間與執(zhí)行指令的時間有關。如果使用6MHz晶振,一個機器周期為2μs。計算出執(zhí)行每一條指令以及一個循環(huán)所需要的時間,根據(jù)要求的延時時間確定循環(huán)次數(shù),如果單循環(huán)時間不夠長,可以采用多重循環(huán)。

31程序如下: MOVR5,#05HDELY0:MOVR6,#0C8HDELY1:MOVR7,#0F8HNOPDELY2:DJNZR7,DELY2DJNZR6,DELY1DJNZR5,DELY0這是一個三重循環(huán)程序。前4條指令的機器周期數(shù)為1,后3條指令的機器周期數(shù)為2。執(zhí)行內(nèi)循環(huán)所用的機器周期數(shù)為248×2=496,執(zhí)行中間循環(huán)所用的機器周期數(shù)(496+4)×200=100000;執(zhí)行外循環(huán)所用的機器周期數(shù)為(100000+3)×5=500015,再加上1(執(zhí)行第一條指令)就是執(zhí)行整段程序所用的機器周期數(shù)。因此這段程序的延時時間位(500015+1)×2μs=1.000032s。32【例4-14】編寫無符號數(shù)排序程序。假設在片內(nèi)RAM中,起始地址為40H的10個單元中存放有10個無符號數(shù)。試進行升序排序。解數(shù)據(jù)排序常用方法是冒泡排序法。這種方法的過程類似水中氣泡上浮,故稱冒泡法。執(zhí)行時從前向后進行相鄰數(shù)的比較,如數(shù)據(jù)的大小次序與要求的的順序不符就將這兩個數(shù)互換,否則不互換。對于升序排序通過這種相鄰數(shù)的互換,使小數(shù)向前移動,大數(shù)向后移動;從前向后進行一次冒泡(相鄰數(shù)的互換),就會把最大的數(shù)換到最后;再進行一次冒泡就會把次大的數(shù)排在倒數(shù)第二的位置。依此類推,完成由小到大的排序。

編程中選用R7做比較次數(shù)計數(shù)器,初始值為09H,位地址00H作為冒泡過程中是否有數(shù)據(jù)互換的標志位,若(00H)=0,表明無互換發(fā)生,已排序完畢。(00H)=1,表明有互換發(fā)生。流程圖如圖4-11所示。

33

ORG0400H

START:MOVR0,#40H;數(shù)據(jù)區(qū)首址送R0

MOVR7,#09H;各次冒泡比較次數(shù)送R7

CLR00H;互換標志位清零LOOP:MOVA,@R0;取前數(shù)送A中

MOV2BH,A;暫存到2BH單元中

INCR0;修改地址指針

MOV2AH,@R0;取后數(shù)暫存到2AH單元中

CLRC;清CY

SUBBA,@R0;前數(shù)減后數(shù)

JCNEXT;前數(shù)小于后數(shù),則轉(zhuǎn)(不互換)

MOV@R0,2BH;前數(shù)大于后數(shù),兩數(shù)交換

DECR0

MOV@R0,2AH

INCR0;地址加1,準備下一次比較

SETB00H;置互換標志NEXT:DJNZR7,LOOP;未比較完,進行下一次比較

JB00H,START;有交換,表示未排完序,進行下一輪冒泡

END

;無交換,表示已排好序,結(jié)束34

圖4.10程序流程圖354.5子程序設計

在匯編語言源程序中使用子程序時,一般要注意兩個問題:參數(shù)傳遞和現(xiàn)場保護。參數(shù)傳遞一般可采用以下方法:傳遞數(shù)據(jù)。將數(shù)據(jù)通過工作寄存器R0~R7或累加器來傳送。即主程序和子程序在交接處,上述寄存器和累加器存儲的是同一參數(shù)。傳送地址。數(shù)據(jù)存放在數(shù)據(jù)寄存器中,參數(shù)傳遞時只通過R0、R1、DPTR傳遞數(shù)據(jù)所存放的地址。通過堆棧傳遞參數(shù)。在調(diào)用之前,先把要傳送的參數(shù)壓入堆棧,進入子程序之后,再將壓入堆棧的參數(shù)彈出到工作寄存器或者其他內(nèi)存單元。

36通過位地址傳送參數(shù)。例如:SUBROU:PUSHACC PUSHB PUSHR0POPR0 POPB POPPSW POPACC RET至于每個具體的子程序是否需要現(xiàn)場保護,以及哪些參數(shù)應該保護,則應視具體情況而定?!纠?-15】單字節(jié)二進制數(shù)據(jù)轉(zhuǎn)換為BCD碼子程序SBTOD。功能:將單字節(jié)二進制數(shù)轉(zhuǎn)換為三位BCD碼。入口:R2中存放要轉(zhuǎn)換的二進制數(shù)。37

出口:(R0)給出百位BCD碼的存放地址。(R0)+1給出十位和個位BCD碼的存放地址,高半字節(jié)放十位,低半字節(jié)放個位。

占用寄存器:A,B,R0,R2。

SBTOD:MOVSP,#60H

PUSHACC

MOVA,R2;取數(shù)

MOVB,#64H

DIVAB;除以100,(A)為百位數(shù)

MOV@R0,A;存人(R0)單元

MOVA,#0AH

XCHA,B;余數(shù)(B)送A

DIVA,B;除以10,得十位和個位

SWAPA;十位數(shù)放于高半字節(jié)

ADDA,B;個位數(shù)放于低半字節(jié)

INCR0

MOV@R0,A;個位存入(R0)+1單元

POPACC

RET

38

【例4-16】將內(nèi)部數(shù)據(jù)存儲器某一單元中的一個字節(jié)的十六進制數(shù)轉(zhuǎn)換成兩位ASCII碼,結(jié)果存放在內(nèi)部數(shù)據(jù)存儲器的兩個連續(xù)單元中。假設一個字節(jié)的十六進制數(shù)在內(nèi)部數(shù)據(jù)存儲器40H單元,結(jié)果存于41H、42H單元中,用堆棧進行參數(shù)傳遞。

MAIN:MOVSP,#55H

MOVR1,#41H;R1為存結(jié)果指針

MOVA,40H;取要轉(zhuǎn)換的數(shù)據(jù)

SWAPA;先轉(zhuǎn)換高位字節(jié)

PU

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
  • 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論