




版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領
文檔簡介
第4章MCS-51匯編語言程序設計
4.1簡單程序設計
4.2分支程序設計
4.3循環(huán)程序設計
4.4散轉程序設計4.5子程序和參數傳遞方法
4.6查表程序設計4.7數制轉換習題與思考題程序設計是為了解決某一個問題而將指令有序地組合在一起的過程。程序有簡有繁,但復雜程序往往是由簡單的基本程序所構成的。本章將通過一些基本程序,介紹部分常用的程序設計方法。程序設計的過程大致可以分為以下幾個步驟:(1)編制要解決問題的程序框圖。(2)確定數據結構、算法、工作單元、變量設定。(3)根據所用計算機的指令系統,按照已編制的程序框圖用匯編語言編制出源程序。(4)將編制的程序在計算機上調試,直至實現預定的功能。4.1簡單程序設計
簡單程序又稱順序程序。計算機是按指令在存儲器中存放的先后次序來順序執(zhí)行程序的。
【例4-1】兩個8位的無符號數相加的和仍是8位。設內部RAM的40H、41H單元中分別存放8位數N1、N2,兩數相加的結果送42H單元。程序如下:
AD1:MOV
R0,#40H;設R0為數據指針
MOVA,@R0;取N1
INCR0;修改指針
ADDA,@R0;N1+N2
INCR0
MOV@R0,A;存結果
END
【例4-2】將兩個半字節(jié)數合并成一個一字節(jié)數。設內部RAM的40H、41H單元中分別存放著8位二進制數,要求取出兩個單元中的低半字節(jié),并將其合并成一個字節(jié)后存放在42H單元。程序如下:START:MOV
R1,#40H
MOVA,@R1ANLA,#0FH;取第一個半字節(jié)
SWAPA;移至高4位
INCR1XCHA,@R1;取第二個字節(jié)
ANLA,#0FH;取第二個半字節(jié)
ORLA,@R1;拼字
INCR1MOV@R1,A;存放結果
END以上程序均采用了寄存器尋址方式,可以方便地取數、存數。例4-2中用XCHA,@R1指令,既取出了數,又保存了中間結果。4.2分支程序設計
在處理實際事務中,只用簡單程序設計的方法是不夠的,因為大部分程序總包含有判斷、比較等情況,程序將根據判斷、比較的結果轉向不同的分支。下面舉兩個分支程序的例子。
【例4-3】兩個無符號數比較大小。設存儲單元ST1和ST2中存放著兩個不帶符號的二進制數,找出其中的大數存入ST3單元中。流程圖如圖4-1所示。圖4-1兩個無符號數的比較流程程序如下:
ST1:EQU8040H
ORG8000H
START1:CLRC;進位位清0
MOVDPTR,#ST1;設數據指針
MOVXA,@DPTR;取第一個數
MOVR2,A;暫存于R2
INCDPTR
MOVXA,@DPTR;取第二個數
SUBBA,R2;兩數比較
JNCBIG1
XCHA,R2;第一個數大BIG0:INCDPTR
MOVX@DPTR,A;存大數
RETBIG1:MOVXA,@DPTR;第二個數大
SJMPBIG0
END上面程序中,用減法指令SUBB來比較兩數的大小。由于這是一條帶借位的減法指令,因此在執(zhí)行該指令前,應先把進位位清0。用減法指令通過借位(CY)的狀態(tài)判別兩數的大小,是兩個無符號數比較大小時常用的方法。設有兩數x,y,執(zhí)行x-y,當x≥y時,結果無借位產生,則CY=0;反之,則CY=1,表示x<y。用減法指令比較大小,會破壞累加器中的內容,故做減法前先保存累加器中的內容。執(zhí)行JNC指令后,形成了分支。執(zhí)行SJMP指令后,實現了程序的轉移。
【例4-4】編制計算符號函數y=SGN(x)的程序。設自變量x已存入標號為ARE的單元:-128≤x≤127。y存入標號為BUF的單元。流程圖見圖4-2。圖4-2計算符號函數流程源程序如下:
ARE
EQU8050H
BUF
EQU8060H
NEG
EQU8070H
ORG
8000H
START2:MOVDPTR,#ARE
MOVXA,@DPTR
JZSUL;x=0,轉SUL
JBACC.7,NEG;判x的符號位
MOVA,#01;x>0,1→A
SUL:MOVDPTR,#BUF
MOVX@DPTR,A
END
NEG:MOVA,#FFH;x<0,-1→A
SJMPSUL這是一個二次判斷的程序,它與例4-3不同。例4-3程序只有一次判斷,所以是單分支程序,本例則是二分支程序。分支程序在實際使用中用處很大,除了用于比較數的大小之外,常用于控制子程序的轉移。在4.4節(jié)中將詳細介紹分支程序的使用。4.3循環(huán)程序設計在程序設計中,只有簡單程序和分支程序是不夠的。因為簡單程序每條指令只執(zhí)行一次,而分支程序則根據條件的不同,會跳過一些指令,執(zhí)行另一些指令。它們的特點是,每一條指令至多執(zhí)行一次。在處理實際事務時,有時會遇到多次重復處理的問題,用循環(huán)程序的方法來解決就比較合適。循環(huán)程序中的某些指令可以反復執(zhí)行多次。采用循環(huán)程序,可以縮短程序,節(jié)省存儲單元。當重復次數越多時,循環(huán)程序的優(yōu)越性就越明顯。但是程序的執(zhí)行時間并不節(jié)省。由于要有循環(huán)準備、結束判斷等指令,速度要比簡單程序稍慢些。循環(huán)程序一般由五部分組成:(1)初始化部分:為循環(huán)程序做準備。如設置循環(huán)次數計數器的初值、地址指針置初值、為循環(huán)變量賦初值等。
(2)處理部分:為反復執(zhí)行的程序段,是循環(huán)程序的實體。(3)修改部分:每執(zhí)行一次循環(huán)體后,對指針作一次修改,使指針指向下一數據所在位置,為進入下一輪處理做準備。(4)控制部分:根據循環(huán)次數、計數器的狀態(tài)或循環(huán)條件等檢查循環(huán)是否能繼續(xù)進行,若循環(huán)次數到或循環(huán)條件不滿足時,應退出循環(huán),否則繼續(xù)循環(huán)。通常(2)、(3)、(4)部分又稱為循環(huán)體。(5)結束部分:分析及存放執(zhí)行結果。循環(huán)程序的結構一般有兩種形式:(1)先進入處理部分,再控制循環(huán),即至少執(zhí)行一次循環(huán)體,如圖4-3(a)所示。(2)先控制循環(huán),后進入處理部分,即根據判斷結果控制循環(huán)的執(zhí)行與否,有時可以不進入循環(huán)體就退出循環(huán)程序,如圖4-3(b)所示。圖4-3循環(huán)程序的結構形式循環(huán)結構的程序,不論是先處理后判斷,還是先判斷后處理,其關鍵是控制循環(huán)的次數。根據需解決問題的實際情況,對循環(huán)次數的控制有多種:循環(huán)次數已知的,用計數器控制循環(huán);循環(huán)次數未知的,可以按條件控制循環(huán),也可以用邏輯尺控制循環(huán)。循環(huán)程序又分單循環(huán)程序和多重循環(huán)程序。下面舉例說明循環(huán)程序的使用。
1.單循環(huán)程序
1)循環(huán)次數已知的循環(huán)程序下面舉幾個循環(huán)次數已知的循環(huán)程序例子。
【例4-5】工作單元清0。在程序設計時,有時需要將存儲器中的部分地址作為工作單元,存放程序執(zhí)行的中間值和結果。工作單元清0工作常常放在程序的初始化部分中。設有50個工作單元,其首址存放在DPTR中,循環(huán)次數存放在R2寄存器中,每執(zhí)行一次循環(huán),R2的內容減1,直至R2=0時,循環(huán)程序結束。流程圖見圖4-4圖4-4工作單元清0流程圖
CLEAR:CLR
A[KG8]
MOVR2,#32H;置計數值
LOOP:MOVX@DPTR,A
INCDPTR;修改地址指針
DJNZR2,LOOP;控制循環(huán)
END本例中循環(huán)次數是已知的。用R2作循環(huán)次數計數器,用DJNZ指令修改計數器值,控制循環(huán)的結束與否。
【例4-6】多個單字節(jié)數據求和。已知有n個單字節(jié)數據,依次存放在內部RAM的40H單元開始的連續(xù)單元中,要求把計算結果存入R2、R3中(高位存R2,低位存R3)。流程圖見圖4-5。圖4-5多個單字節(jié)數據求和流程圖程序如下:
NUMEQU0AH
ORG8000H
SAD:MOVR0,#40H;設數據指針
MOVR5,#NUN;計數值0AH→R5
SAD1:MOVR2,#0;和的高8位清0
MOVR3,#0;和的低8位清0
LOOP:MOVA,@R3;取加數
ADDA,@R0
MOVR3,A;存和的低8位
JNCLOP1
INCR2;有進位,和的高8位+1
LOP1:INCR0;指向下一數據地址
DJNZR5,LOOP
END上述程序中,用R0作間址寄存器,每做一次加法,R0加1,數據指針指向下一數據地址,R5為循環(huán)次數計數器,控制循環(huán)的次數。
2)循環(huán)次數未知的循環(huán)程序以上介紹的幾個循環(huán)程序例子,它們的循環(huán)次數是已知的,適合用計數器置初值的方法。而有些循環(huán)程序事先不知道循環(huán)次數,不能用以上方法。這時需要根據判斷循環(huán)條件的成立與否,或用建立標志的方式控制循環(huán)程序的結束。
【例4-7】測試字符串長度。設有一串字符依次存放在內部RAM的從50H單元開始的連續(xù)單元中。該字符串以回車符為結束標志。測字符串長度程序,即將該字符串中的每一個字符依次與回車符相比;若比較不相等,則統計字符串長度的計數器加1;若比較相等,則表示該字符串結束,計數器中的值就是字符串的長度。程序如下:
CONT:MOVR2,#0FFH
MOVR0,#4FH;數據指針R0置初值
LOOP:INCR0
INCR2
CJNE@R0,#0DH,LOOP
END
待測字符以ASCII碼形式存放在RAM中,回車符的ASCII碼為0DH,程序中用一條CJNZ@R0,#0DH,LOOP指令實現字符比較及控制循環(huán)的任務,當循環(huán)結束時,R2的內容為字符串長度。
3)用邏輯尺控制循環(huán)次數的循環(huán)程序在實際應用中,有時并不要求按一定的固有順序執(zhí)行循環(huán)處理,而要求處理部分是不規(guī)則的循環(huán)過程。如調用處理部分的子程序PRG0、PRG1共8次。調用順序為:第1、3、4、7次是調用PRG1;其余是調用PRG0。程序的設計方法是:設總的調用次數為循環(huán)次數,并且另設一個標志,用來識別調用哪個子程序。兩個子程序可以用0和1兩種邏輯狀態(tài)識別,如用0狀態(tài)表示調用PRG0,用1狀態(tài)表示調用PRG1。由于總共調用8次,因此用一個寄存器的8位作為8個標志位,按調用子程序的順序,把0、1存放在寄存器的不同位上。當執(zhí)行程序時,由寄存器的第0位或第7位起逐位測試,根據此位的狀態(tài)決定調用哪個子程序。因此該寄存器好像一把“尺”,它的內容猶如“尺”的“刻度”,作為識別調用子程序的標志,人們稱它為“邏輯尺”。“邏輯尺”的長寬視需要而定,一個字節(jié)不夠用,可以把相鄰的字節(jié)串聯起來,或者設定n把“邏輯尺”。
【例4-8】邏輯尺使用。設R0為原始數首地址,R1存放結果首地址,R3為邏輯尺,流程圖如圖4-6所示。圖4-6邏輯尺程序流程圖程序如下:
PRG0EQU
8360H
PRG1EQU
8200H
ORG8000HTEST:MOVR2,#08H;邏輯尺長度
MOVR3,#10110010B;設定邏輯尺
LOOP:MOVA,@R0;取數據
XCHA,R3RLCA;左移,讀尺刻度
XCHA,R3JCLOOP1;轉調用PRG1LCALLPRG0;是0,調用PRG0SJMPRELT
LOOP1:LCALLPRG1RELT:MOV@R1,A;存結果
INCR0
INCR1
DJNZR2,LOOP;R2≠0,繼續(xù)循環(huán)END
2.多重循環(huán)程序
如果在一個循環(huán)體中又包含了其他的循環(huán)程序,即循環(huán)中還套著循環(huán),則這種程序稱為多重循環(huán)程序。
【例4-9】
10s延時程序。延時程序與MCS-51執(zhí)行指令的時間有關,如果使用6MHz晶振,則一個機器周期為2μs,計算出執(zhí)行一條指令以及一個循環(huán)所需要的時間,給出相應的循環(huán)次數,便能達到延時的目的。程序如下:
DEL:MOVR5,#100
DEL0:MOVR6,#200
DEL1:MOVR7,#248
DEL2:DJNZR7,DEL2;248*2+4
DJNZR6,DEL1;(248*2+4)*200+4DJNZR5,DEL0;((248*2+4)*200+4)*100+4
RET上例延時程序實際延時為10.000406s。它是一個三重循環(huán)程序,利用程序嵌套的方法對時間實行延遲是程序設計中常用的方法。使用多重循環(huán)程序時,必須注意以下幾點:(1)循環(huán)嵌套必須層次分明,不允許產生內外層循環(huán)交叉。(2)外循環(huán)可一層層向內循環(huán)進入,結束時由里往外一層層退出。(3)內循環(huán)體可以直接轉入外循環(huán)體,實現一個循環(huán)由多個條件控制的循環(huán)結構方式。
【例4-10】冒泡程序。設有N個數,它們依次存放于LIST地址開始的存儲區(qū)域中,將N個數比較大小之后,使它們按由小到大(或由大到?。┑拇涡蚺帕校娣旁谠鎯^(qū)域中。編制該程序的方法:依次將相鄰兩個單元的內容作比較,即第一個數和第二個數比較,第二個數和第三個數比較……如果符合從小到大的順序則不改變它們在內存中的位置,否則交換它們之間的位置。如此反復比較,直至數列排序完成為止。由于在比較過程中將小數(或大數)向上“冒”,因此這種算法稱為“冒泡法”或稱為排序法。下列表格可以說明冒泡法的比較過程。第一輪經過6次兩兩比較后,得到一個最大數。第二輪經過5次兩兩比較后,得到一個次大數。
……每輪比較后均得到本輪最大數(或最小數),該數就不再參加下一輪的兩兩比較,故進入下一輪時,兩兩比較次數減1。為了加快數列排序速度,程序中設置一個標志位,只要在比較過程中兩數之間沒有發(fā)生過交換,就表示數列已按大小順序排列了,可以結束比較。根據以上分析,可畫出流程圖如圖4-7所示。圖4-7冒泡程序流程圖設數列首地址在R0寄存器中,R2為外循環(huán)次數計數器,R3為內循環(huán)次數計數器,R1為交換標志。程序如下:
CONTEQU07H
LIST
DB0,13,3,90,27,32,11
ORG8000H
MOVR2,#CNT-1;數列個數-1
LOOP1:MOVA,R2;外循環(huán)計數值
MOVR3,A;內循環(huán)計數值
MOVR1,#01;交換標志置1LOOP2:MOVA,@R0;限數據
MOV
B,A;暫存B
INC
R0
CLR
C
SUBB
A,@R0;兩數比較
JC
LESS;Xi<Xi+1,轉LESS
MOV
A,B;取大數
XCH
A,@R0;兩數交換位置
DEC
R0
MOV@R0,A
INC
R0;恢復數據指針
MOV
R1,#02;置交換標志為2LESS:DJNZR3,LOOP2;內循環(huán)計數減1,判一遍是否查完
DJNZR2,LOOP3;外循環(huán)計數減1,判排序是否結束STOP:RETLOOP3:R1,LOOP1;交換轉移
SJMP
STOP
ORG
50H;(內部RAM)
END
3.循環(huán)程序應用舉例
1)不帶符號數的多字節(jié)加法在處理多字節(jié)運算時,應注意低字節(jié)向高字節(jié)的進位(或借位)(用進位CY判別,當CY=0時,表示無進位或借位,反之則表示有進位或借位)。在進行不帶符號的單字節(jié)二進制數加減運算時,用進位CY判別數的溢出與否。
【例4-11】兩個多字節(jié)數P、Q均以低字節(jié)在前,高字節(jié)在后的次序,分別存放在由R0、R1指出的內部RAM中,相加后存入P數據區(qū),見圖4-8。圖4-8
RAM數據存儲示意程序如下:
N1
EQU0AH
ORG
8000H
START1:CLR
C;清進位
MOV
R2,#N1;取字節(jié)數
MADD:MOV
A,@R0;取加數(一個字節(jié))
ADDC
A,@R1;兩數相加(由低字節(jié)開始)MOV@R0,A
INC
R0
INC
R1
DJNZ
R2,MADD;兩數加完?JC
ERR;和字節(jié)數大于n,則溢出錯RET
ERR:…
END上例中若將ADDCA,@R1指令改為SUBBA,@R1指令,則該程序就是多字節(jié)減法程序。無符號數的減法運算,被減數必須大于減數。不帶符號的十進制數加法程序的設計思想與上例相同。
MCS-51指令系統中沒有直接的十進制數加法指令,要做十進制BCD碼加減運算,只要在加、減指令后跟一條DAA指令,即可使運算結果成為十進制數的形式。
2)帶符號數的加減運算帶符號的定點二進制數加減運算程序和無符號的定點二進制數加減運算程序基本相同,只是判斷溢出的條件不同。帶符號的兩個定點二進制數參加運算時,應先判斷兩數符號,然后決定其加減運算。即首先應判兩數符號是否相同。若兩運算數符號相同,則數值部分相加。加法結果有溢出時,轉溢出處理;加法結果無溢出時,最后結果的符號與被加數的符號相同。如兩運算數符號不同,則執(zhí)行減法。如夠減,則結果符號為被減數符號;不夠減則應將差取補,結果符號為減數符號。對減法運算,可以先把減數符號取反,再進行加法運算。根據上述算法,可畫出原碼加減運算的流程圖,見圖4-9。圖4-9原碼加減運算流程圖
【例4-12】雙字節(jié)原碼加減法程序。
R2R3±R4R5→R6R7已知:R2R3、R4R5分別存放16位帶符號二進制數;R2、R4的最高位分別是兩數的符號位,0代表正數,1代表負數;結束時CY=1表示溢出,CY=0表示無溢出。
BSUB為原碼減法程序入口;BADD為原碼加法程序入口。程序如下:
F0
EQU
20H
ORG
8000HBSUB:MOV
A,R4
CPL
ACC.7;減數符號位取反
MOV
R4,ABADD:MOV
A,R2
MOV
C,ACC.7
MOVF0,C;保存被加數符號位
XRL
A,R4MOV
C,ACC.7;兩數同號,CY=0;兩數異號,CY=1MOV
A,R2
CLR
ACC.7;符號位清0
MOV
R2,A;取數值部分
MOV
A,R4
CLR
ACC.7;符號位清0
MOV
R4,A;取數值部分
JC
BX2ADD1:MOVA,R3;同號,兩個雙字節(jié)數相加ADDA,R5;低位相加MOVR7,A;存低位和MOVA,R2ADDCA,R4;高位相加MOVR4,A;存高低和JB
ACC.7,BERR
BX1:
MOV
C,F0;恢復結果符號MOV
ACC.7,CMOV
R4,ARETBERR:SETB
CRETBX2:MOVA,R3;異號,兩個雙字節(jié)數相減
CLRCSUBBA,R5;低位相減
MOVR7,A;存低位結果MOVA,R2SUBBA,R4;高位相減MOVR6,A;存高位結果
JNBACC.7,BX1;判結果符號,為正則轉
BX1BMP:MOVA,R7;符號為負,則對差求補
CPLAADDA,#1MOVR7,AMOVA,R6CPLAADDCA,#0MOVR6,ACPLF0;保存在用戶標志位F0中的符號取反SJMP
BX1
END本例分為四個部分處理,其中第一部分是符號處理,這是為了使數值以正整數形式參加運算;第二部分是加法運算;第三部分是減法運算;第四部分是結果取補運算。
3)乘法運算在MCS-51指令系統中有專門的單字節(jié)乘法指令MULAB,該指令功能為A*B→BA。下面將用這條乘法指令實現無符號雙字節(jié)數的乘法運算。兩個單字節(jié)數相乘,結果為雙字節(jié),可以用字節(jié)為單位的豎式乘法擴展其為雙字節(jié)數的乘法。采用乘法和加法結合實現乘法運算的示意圖見圖4-10,其執(zhí)行速度比移位相加方法要快得多。圖4-10采用乘法和加法結合實現乘法運算
【例4-13】
R2R3*R6R7→R4R5R6R7。雙字節(jié)被乘數在R2、R3中,雙字節(jié)乘數在R6、R7中,R3*R7→R3R7、R2*R7→R2R7;同理,R3*R6→R3R6,R2*R6→R2R6。執(zhí)行四次乘法后,每次乘積經累加器,最后R4R5R6R7中。程序如下:
F0
EQU20
ORG8000HDBMU1:MOVA,R3MOVB,R7MULAB;R3*R7XCHA,R7;乘積低位→R7,R7→A準備乘數MOVR5,B;乘積高位暫存R5MOV
B,R2MUL
AB;R7*R2ADD
A,R5;乘積低位加上一次的乘積高位暫存R4MOV
R4,ACLR
A;清累加器ADDCA,B;高位加從低位來的進位后暫存R5MOV
R5,AMOV
A,R6MOV
B,R3MUL
AB;R6*R3ADD
A,R4;第三次乘積低位加R5暫存R6XCH
A,R6XCH
A,BADDC
A,R5;第三次乘積高位加R5暫存R5MOV
R5,AMOV
F0,C;保存進位位MOV
A,R2MUL
AB;R2*R6ADD
A,R5;第4次乘積低位加R5暫存R5MOV
R5,ACLR
AMOVACC.0,CMOVC,F0ADDCA,B;第4次乘積高位加低位來的進位后存于R4MOVR4,ARETEND
4)除法運算除法是乘法的逆運算,用移位、相減的方法完成。根據手算除法的原則,上商前先比較被除數與除數,如果被除數大于除數,商上1,然后做減法,否則商上0,說明不夠減,不執(zhí)行減法。在計算機中,判斷夠減不夠減的方法是做一次減法,由余數的符號決定,如果余數為正說明夠減,商為1,否則商為0。根據上述算法思想,畫出除法程序的流程圖,如圖4-11所示。圖4-11除法流程圖
【例4-14】無符號雙字節(jié)數的除法:
R4R5R6R7÷R2R3→R6R7,余數→R4R5已知:被除數存放在R4R5R6R7中,除數存放在R2R3中,商送R6R7中。由商送R6R7可知,本題中商為16位,若商大于16位則稱為溢出。在進行除法前,先比較R4R5和R3R2的內容,如被除數高字節(jié)(兩個字節(jié))大于等于除數,則溢出,不執(zhí)行除法,F0置1,表示出錯直接返回;否則執(zhí)行除法,這時F0=0。用減法實現被除數和除數比較,結果保存在累加器A和寄存器R1中,如果夠減,商上1,回送減法結果,否則不回送。商上1用加1的方法實現,商上0不加1。程序如下:
F0
EQU20H
ORG8000HBDIV:MOVA,R5;判商是否產生溢出
CLRC
SUBBA,R3
MOVA,R4
SUBBA,R2
JNCDIV1;被除數高位字節(jié)大于除數,轉溢出處理
MOV
B,#16;無溢出則執(zhí)行除法,置循環(huán)次數DIV2:CLR
C;被除數向左移一位,低位送0
MOV
A,R7
RLC
A
MOV
R7,A
MOV
A,R6
RLC
A
MOV
R6,A
MOV
A,R5
RLC
A
MOV
R5,AXCH
A,R4RLC
AXCH
A,R4MOV
F0,C;保護移出的最高位CLR
CSUBB
A,R3;被除數與除數比較MOV
R1,AMOV
A,R4SUBB
A,R2JB
F0,DV2;高位移出位為1,夠減轉DV2JC
DV3
DV2:MOV
R4,A;回送減法結果MOV
A,R1MOV
R5,AINC
R7;商上1DV3:DJNZ
R1,DIV2;不夠減,循環(huán)次數-1CLR
F0;正常執(zhí)行無溢出,F0=0RETDIV1:SETB
F0;置溢出標志RETEND
【例4-15】帶符號二進制數的除法。
R4R5R6R7÷R2R3→R6R7,余數→R4R5被除數和除數以原碼表示,符號位在最高位。帶符號的原碼除法,對符號位的處理方法與帶符號的原碼乘法對符號位的處理方法是相同的,即將兩數符號位作異或運算后的結果設為結果的符號。除法運算時,先確定商的符號,然后把被除數、除數作無符號除法運算,最后把符號送商的符號位。程序如下:
F0
EQU20H
ORG8000HDDIV:MOVA,R2;被除數符號異或除數符號XRLA,R2
MOVC,ACC.7;商的符號通過進位送(20H)保存
MOVF0,C
MOVA,R4;被除數轉換成無符號數形式CLRACC.7
MOVR4,A
MOVA,R2;除數轉換成無符號數形式
CLRACC.7
MOVR2,A
ACALLDDIV;調用無符號雙字節(jié)除法子程序MOVA,R6
JBACC.7,DDIV1;溢出,轉出錯處理MOV
C,F0;回送商的符號
MOV
ACC.7,C
MOV
R6,ADDIV1:SETB
F0;出錯F0=1
RET
END4.4散轉程序設計
散轉程序是分支程序的一種,它由輸入條件或運算結果來確定轉入何種處理程序。有多種方法能實現散轉程序,但通常用逐次比較法,即把所有情況逐一進行比較,若有符合條件便轉向對應的處理程序。由于每一種情況都有判斷和轉移,如對n種情況,需要n次判斷和轉移,因此它的缺點是程序比較長。MCS-51指令系統中有一條跳轉指令JMP@A+DPTR,用它可以很容易地實現散轉功能。該指令把累加器作為轉移指令的地址。執(zhí)行該指令后,累加器和16位數據指針的內容均不受影響。
1.用轉移指令表實現散轉
在許多場合中,要根據某一單元的值(0,1,2,…,n)分別轉向相應處理程序(處理程序0,處理程序1……處理程序n),這時可以用轉移指令AJMP(或LJMP)組成一個轉移表。
【例4-16】根據R6的內容(R6=0,轉PRGM0;R6=1,轉PRGM1……R6=n,轉PRGMn),轉向各個處理程序。把轉移標志送累加器A,轉移表首地址送DPTR,利用JMP@A+DPTR指令實現轉移。程序如下:
PJD:MOV
DPTR,#TAB1
MOV
A,R6
ADD
A,R6;R6*2→A
JNC
PAD
INC
DPH;R6*2>256,16位數據指針高8位加1
PAD:JMP@A+DPTR
TAB1:AJMP
PRGM0;轉處理程序0的首地址
AJMP
PRGM1;轉處理程序1的首地址
AJMP
PRGMn;轉處理程序n的首地址本例適用于散轉表首地址TAB1和處理程序入口地址PRGM0、PRGM1……PRGMn在同一個2KB范圍存儲區(qū)內的情形。如一個2KB范圍的存儲區(qū)內放不下所有的處理程序時,則把一些較長的處理程序放在其他存儲區(qū)域,只要在該處理程序的入口地址內調用LJMP指令即可。方法有兩種:(1)例如處理程序PRGM0、PRGM3比較長,要把兩個程序轉至其他區(qū)域,則分別把它們的入口地址用符號PPRGM0、PPRGM3表示,以實現程序的轉移。
PRGM0:LJMPPPRGM0
PRGM3:LJMPPPRGM3(2)可以直接用LJMP指令組成轉移表。由于LJMP是3字節(jié)的指令,因此在組成指令轉移表后,當執(zhí)行JMP@A+DPTR指令時,可能出現DPTR低8位向高8位進位的情況,所以必須先用加法指令調整DPTR的值后才能用JMP@A+DPTR指令實現跳轉。程序如下:PJ2:MOV
DPTR,#TAB2
CLR
C
MOV
R5,#0
MOV
A,R6
RLC
A;R6*2
JNC
P1
INC
R5;有進位,高8位加1P1:ADD
A,R6;R3*3
JNC
P2
INC
R5;有進位,高8位加1P2:MOV
A,R5
ADD
A,DPH;DPTR高8位調整MOV
A,R6
JMP@A+DPTR;得散轉地址TAB2:LJMP
PRGM0LJMP
PRGM1
LJMP
PRGMn用AJMP組成的散轉表為2字節(jié)一項,而用LJMP組成的散轉表則為3字節(jié)一項,根據R6中的內容或乘2,或乘3,得每一處理程序的入口地址表指針。
2.用轉移地址表實現散轉當轉向范圍比較大時,可直接使用轉向地址表方法,即把每個處理程序的入口地址直接置于地址內。用查表指令,找到對應的轉向地址,把它裝入DPTR中。將累加器清0后用JMP@A+DPTR直接轉向各個處理程序的入口。
【例4-17】根據R3的內容轉向對應處理程序。處理程序的入口分別為PR0~PRn。程序如下:PJ3:MOV
DPTR,#TAB3
MOV
A,R3
ADD
A,R3;R3*2
JNC
CAD
INC
DPH;有進位,DPTR高位加1CAD:MOV
R2,A;暫存R2
MOVCA,@A+DPTR
XCHA,R2;處理程序入口地址高8位暫存R2
INC
A
MOVC
A,@A+DPTR
MOV
DPL,A;處理程序入口地址低8位暫存DPL
MOV
DPH,R2
CLR
A
JMP@A+DPTR
TAB3:DW
PR0
DW
PR1
DW
PRn本例可實現64KB范圍內的轉移,但散轉數n應小于256。如大于256時,應采用雙字節(jié)數加法運算修改DPTR。
3.用RET指令實現散轉以上介紹的兩種方法均采用JMP@A+DPTR指令實現散轉功能。這里要介紹的散轉方法不是把轉向地址裝入DPTR,而是將它壓入堆棧,然后通過RET指令把轉向地址退棧到PC中,使棧指針恢復原值。
【例4-18】根據R5R6內容,轉向不同的處理程序。程序如下:PJ4:MOV
DPTR,#TAB4
MOV
A,R6
CLR
C
RLC
A
XCH
A,R5
RLC
A
ADD
A,DPH
MOV
DPH,A;R5R6*2高8位加到DPH
MOV
DPH,A;R5R6*2低8位存A
MOV
A,R5;從表中得到處理程序入口地址高8位
MOVCA,@A+DPTR
XCHA,R5
INC
DPTR
MOVCA,@A+DPTR;從表中得到處理程序入口地址低8位
PUSH
ACC;地址低8位進棧
MOV
A,R5
PUSH
ACC;地址高8位進棧
RET;轉向地址退棧裝入PC中TAB4:DW
PR0
DW
PR1
DW
PRn4.5子程序和參數傳遞方法
在實際程序中,常常會多次進行一些相同的計算和操作,如數制轉換、函數式計算等等。如果每次都從頭開始編制一段程序,不僅麻煩,而且浪費存儲空間。因而將一些常用的程序段以子程序的形式,事先存放在存儲器的某一個區(qū)域,當主程序在運行中需要用子程序時,只要執(zhí)行調用子程序的指令,使程序轉至子程序即可。當子程序處理完畢后,返回主程序,繼續(xù)進行以后的操作。調用子程序有幾個優(yōu)點:(1)避免了對相同程序段的重復編制。(2)簡化程序的邏輯結構,同時也便于子程序調試。(3)節(jié)省存儲器空間。
MCS-51指令系統中,提供了兩條調用子程序指令:ACALL及LCALL,并提供了一條返回主程序的指令RET。對于子程序的調用,一般包含兩個部分:保護現場和恢復現場。由于主程序每次調用子程序的工作是事先安排的,因此根據實際情況,有時可以省去保護現場的工作。調用子程序時,主程序應先把有關的參數存放在約定的位置,子程序在執(zhí)行時,可以從約定的位置取得參數;當子程序執(zhí)行完后,將得到的結果存入約定的位置,返回主程序后,主程序可以從這些約定的位置上取到需要的結果,這就是參數的傳遞。下面結合MCS-51單片機的特點,介紹幾種參數傳遞方法。
1.用累加器或寄存器進行參數的傳遞
用累加器和寄存器存放輸入參數及結果參數,可以提高程序的運算速度,而且程序也很簡單。如本章例4-15的帶符號的原碼除法子程序就是采用此方法。它的不足之處是參數不能傳遞得很多,因為寄存器的數量有限;主程序在調用子程序前必須將參數先送入寄存器;由于子程序參數的個數是固定的,因此主程序不能任意設定參數的多少。
2.用指針寄存器進行參數的傳遞
當程序中所需處理的數據量比較大時,常常用存儲器存放數據,而不用寄存器。用指針指示數據在存儲器中所處的位置,可以大大節(jié)省參數傳遞中的工作量。使用指針的方法能實現數據長度可變的運算。MCS-51指令系統中提供的由R0、R1作間址寄存器的指令很多,當參數存放在內部RAM時,用R0、R1作指針使參數的傳遞十分方便。如例4-6的多個單字節(jié)數據求和程序,調用時R0作為存放參數的地址指針,R5存放參數長度,R2R3存放運算結果,作為子程序被調用時,其入口地址為SAD。當參數在外部RAM或在程序存儲器時,可用DPTR作指針。對可變長度的數據做運算時,數據長度可由寄存器指出,也可采用在數據后設置標志的方法。
3.用堆棧進行參數傳遞堆??梢杂糜谥鞒绦蛘{用子程序時相互之間的參數傳遞。調用前,主程序用PUSH指令把參數壓入堆棧,子程序在執(zhí)行中按堆棧指針間接訪問棧中參數,并且把運算結果送回堆棧。返回主程序后,主程序用POP指令得到堆棧中的結果參數。利用堆棧傳遞參數的方法比較簡單,而且傳遞參數量比用寄存器來傳遞參數多得多,也不必為特定的參數分配存儲單元。下面舉幾個例子介紹用堆棧進行參數傳遞的方法。
【例4-19】一位十六進制數轉換成ASCII碼。程序如下:
HEASC:MOVR0,SP;借用R0為堆棧指針
DECR0
DECR0;R0指向被轉換參數地址
XCHA,@R0;保護累加器,取被轉換參數
ANLA,#0FH
ADDA,#2;PC表首地址
MOVCA,@A+PC;查表
XCH
A,@R0;結果送回堆棧
RETATAB:DB
30H,31H,32H,33H,34H,
35H,36H,37H,38H,39H
DB
41H,42H,43H,44H,45H,46HEND調用上述子程序后,后一位十六進制數轉換成對應的ASCII碼。輸入參數位于棧頂,進入子程序時,堆棧中又壓入了兩個字節(jié)的返回地址,將原來的輸入參數變成新棧頂起的第三個字節(jié)。R0的內容經兩次減1后,指向原來的輸入參數。利用兩條XCH指令實現了兩個操作:被轉換輸入參數的提取及轉換后的結果參數送回原堆棧中的操作,而A的內容沒有破壞。
【例4-20】把內部RAM中40H單元1字節(jié)的十六進制數轉換成2位ASCII碼,存放在R1指出的兩個單元中,調用HEASC子程序。程序如下:
ORG
8000HMAIN:MOV
A,40H;直接尋址,(40H)→A
SWAPA;2位十六進制數半字節(jié)交換
PUSH
ACC
ACALLHEASC
POP
ACC
MOV@R1,A;高半字節(jié)轉換成ASCII碼,存結果
INC
R1
PUSH40H
ACALLHEASC
POP
ACC
MOV@R1,A;低半字節(jié)轉換成ASCII碼,存結果
END由于HEASC子程序每次只能完成1位十六進制數對ASCII碼的轉換,因此對于1字節(jié)的十六進制數轉換,需要在主程序中兩次調用HEASC。如果被轉換的十六進制數是多字節(jié)時,則調用程序將占去很多存儲空間。下面仍采用堆棧傳遞參數法,介紹1字節(jié)的2位十六進制數轉換成ASCII碼的子程序。
【例4-21】被轉換數據存放在R0指出的堆棧地址中,結果送原單元及其下一單元。程序如下:
HEAS2:MOVR0,SP;借用R0為堆棧指針
DECR0
DECR0;R0指向被轉換參數地址
PUSHACC;保護累加器
MOVA,@R0;取出參數
ANLA,#0FH;取右半字節(jié)
ADDA,#14;得
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經權益所有人同意不得將文件中的內容挪作商業(yè)或盈利用途。
- 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
- 6. 下載文件中如有侵權或不適當內容,請與我們聯系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 產業(yè)園區(qū)入駐合同協議
- 關于推進跨部門合作項目的工作計劃
- 關于采購流程的往來文書說明
- 商務會議溝通要點及會議紀要模板
- 健康管理平臺的構建及運營規(guī)劃
- 機器人智能化生產線建設委托代理合同
- 交通物流調度管理系統建設方案
- 房屋預約買賣合同
- 木材原木購銷合同
- 2025年版《認識大熊貓》課件發(fā)布
- 中國計量大學《微機原理及其應用》2021-2022學年第一學期期末試卷
- 中國技能大賽-第45屆世界技能大賽全國選拔賽“水處理技術”項目技術工作文件
- 混凝土工安全教育培訓試題及答案
- 臨床家庭化產房開展經驗分享
- 安徽省六安市裕安區(qū)六安市獨山中學2024-2025學年高一上學期11月期中生物試題(含答案)
- 低血糖的護理查房
- GB/T 44718-2024城市軌道交通無障礙運營服務規(guī)范
- DB41T 2567-2023 消防技術服務機構服務規(guī)范
- 2024年職工普法教育宣講培訓課件
- 音樂鑒賞與實踐 第一單元第四課音樂的力量(下)
- 《外科護理學(第七版)》考試復習題庫-上(單選題)
評論
0/150
提交評論