?? mcs-51單片機實用子程序庫.htm
字號:
時順序號在累加器A中,址在DPTR中;OV=1 時未找到。<BR>影響資源:PSW、A、B、R1~R7、DPTR 堆棧需求:
2字節<BR>FDD2: MOV R2,#0 ;區間低端指針初始化(指向第一個數據)<BR>MOV A,R7<BR>DEC
A<BR>MOV R3,A ;區間高端指針初始化,指向最后一個數據<BR>MOV R6,DPH ;保存表格首址<BR>MOV
R7,DPL<BR>FD81: CLR C ;判斷區間大小<BR>MOV A,R3<BR>SUBB A,R2<BR>JC FD89
;區間消失,查找失敗<BR>RRC A ;取區間大小的一半<BR>ADD A,R2 ;加上區間的低端<BR>MOV R1,A
;得到區間的中心<BR>MOV DPH,R6<BR>CLR C ;計算區間中心的地址<BR>RLC A<BR>JNC
FD82<BR>INC DPH<BR>FD82: ADD A,R7<BR>MOV DPL,A<BR>JNC FD83<BR>INC
DPH<BR>FD83: CLR A ;讀取該點的內容的高字節<BR>MOVC A,@A+DPTR<BR>MOV B,R4
;與待查找內容的高字節比較<BR>CJNE A,B,FD84;不相同<BR>MOV A,#1 ;讀取該點的內容的低字節<BR>MOVC
A,@A+DPTR<BR>MOV B,R5<BR>CJNE A,B,FD84;與待查找內容的低字節比較<BR>MOV A,R1
;取順序號<BR>CLR OV ;查找成功<BR>RET<BR>FD84: JC FD86
;該點的內容比待查找的內容大否?<BR>MOV A,R1 ;偏大,取該點位置<BR>DEC A ;減一<BR>MOV R3,A
;作為新的區間高端<BR>SJMP FD81 ;繼續查找<BR>FD86: MOV A,R1 ;偏小,取該點位置<BR>INC A
;加一<BR>MOV R2,A ;作為新的區間低端<BR>SJMP FD81 ;繼續查找<BR>FD89: MOV DPH,R6
;相同,恢復首址<BR>MOV DPL,R7<BR>SETB OV ;查找失敗<BR>RET<BR> <BR>(30) 標號: DDM1
功能:求單字節十六進制無符號數據塊的平均值<BR><BR><BR>入口條件:數據塊的首址在DPTR中,數據個數在R7中。<BR>出口信息:平均值在累加器A中。<BR>影響資源:PSW、A、R2~R6
堆棧需求: 4字節<BR>DDM1: MOV A,R7 ;保存數據個數<BR>MOV R2,A<BR>PUSH DPH<BR>PUSH
DPL<BR>CLR A ;初始化累加和<BR>MOV R4,A<BR>MOV R5,A<BR>DM11: MOVX A,@DPTR
;讀取一個數據<BR>ADD A,R5 ;累加到累加和中<BR>MOV R5,A<BR>JNC DM12<BR>INC
R4<BR>DM12: INC DPTR ;調整指針<BR>DJNZ R2,DM11 ;累加完全部數據<BR>LCALL D457
;求平均值(R4R5/R7-→R3)<BR>MOV A,R3 ;取平均值<BR>POP DPL<BR>POP
DPH<BR>RET<BR> <BR>(31) 標號: DDM2
功能:求雙字節十六進制無符號數據塊的平均值<BR><BR>入口條件:數據塊的首址在DPTR中,雙字節數據總個數在R7中。<BR>出口信息:平均值在R4、R5中。<BR>影響資源:PSW、A、R2~R6
堆棧需求: 4字節<BR>DDM2: MOV A,R7 ;保存數據個數<BR>MOV R2,A ;初始化數據指針<BR>PUSH DPL
;保持首址<BR>PUSH DPH<BR>CLR A ;初始化累加和<BR>MOV R3,A<BR>MOV R4,A<BR>MOV
R5,A<BR>DM20: MOVX A,@DPTR ;讀取一個數據的高字節<BR>MOV B,A<BR>INC
DPTR<BR>MOVX A,@DPTR ;讀取一個數據的低字節<BR>INC DPTR<BR>ADD A,R5
;累加到累加和中<BR>MOV R5,A<BR>MOV A,B<BR>ADDC A,R4<BR>MOV R4,A<BR>JNC
DM21<BR>INC R3<BR>DM21: DJNZ R2,DM20 ;累加完全部數據<BR>POP DPH
;恢復首址<BR>POP DPL<BR>LJMP DV31 ;求R3R4R5/R7-→R4R5,得到平均值<BR> <BR>(32)
標號: XR1
功能:求單字節數據塊的(異或)校驗和<BR><BR>入口條件:數據塊的首址在DPTR中,數據的個數在R6、R7中。<BR>出口信息:校驗和在累加器A中。<BR>影響資源:PSW、A、B、R4~R7
堆棧需求: 2字節<BR>XR1: MOV R4,DPH ;保存數據塊的首址<BR>MOV R5,DPL<BR>MOV A,R7
;雙字節計數器調整<BR>JZ XR10<BR>INC R6<BR>XR10: MOV B,#0 ;校驗和初始化<BR>XR11:
MOVX A,@DPTR ;讀取一個數據<BR>XRL B,A ;異或運算<BR>INC DPTR ;指向下一個數據<BR>DJNZ
R7,XR11 ;雙字節計數器減一<BR>DJNZ R6,XR11<BR>MOV DPH,R4 ;恢復數據首址<BR>MOV
DPL,R5<BR>MOV A,B ;取校驗和<BR>RET<BR> <BR>(33) 標號: XR2
功能:求雙字節數據塊的(異或)校驗和<BR><BR>入口條件:數據塊的首址在DPTR中,雙字節數據總個數在R6、R7中。<BR>出口信息:校驗和在R2、R3中。<BR>影響資源:PSW、A、R2~R7
堆棧需求: 2字節<BR>XR2: MOV R4,DPH ;保存數據塊的首址<BR>MOV R5,DPL<BR>MOV A,R7
;雙字節計數器調整<BR>JZ XR20<BR>INC R6<BR>XR20: CLR A ;校驗和初始化<BR>MOV
R2,A<BR>MOV R3,A<BR>XR21: MOVX A,@DPTR ;讀取一個數據的高字節<BR>XRL A,R2
;異或運算<BR>MOV R2,A<BR>INC DPTR<BR>MOVX A,@DPTR ;讀取一個數據的低字節<BR>XRL
A,R3 ;異或運算<BR>MOV R3,A<BR>INC DPTR ;指向下一個數據<BR>DJNZ R7,XR21
;雙字節計數器減一<BR>DJNZ R6,XR21<BR>MOV DPH,R4 ;恢復數據首址<BR>MOV
DPL,R5<BR>RET<BR> <BR>(34) 標號: SORT
功能:單字節無符號數據塊排序(增序)<BR><BR>入口條件:數據塊的首址在R0中,字節數在R7中。<BR>出口信息:完成排序(增序)<BR>影響資源:PSW、A、R2~R6
堆棧需求: 2字節<BR>SORT: MOV A,R7<BR>MOV R5,A ;比較次數初始化<BR>SRT1: CLR F0
;交換標志初始化<BR>MOV A,R5 ;取上遍比較次數<BR>DEC A ;本遍比上遍減少一次<BR>MOV R5,A
;保存本遍次數<BR>MOV R2,A ;復制到計數器中<BR>JZ SRT5 ;若為零,排序結束<BR>MOV A,R0
;保存數據指針<BR>MOV R6,A<BR>SRT2: MOV A,@R0 ;讀取一個數據<BR>MOV R3,A<BR>INC R0
;指向下一個數據<BR>MOV A,@R0 ;再讀取一個數據<BR>MOV R4,A<BR>CLR C<BR>SUBB A,R3
;比較兩個數據的大小<BR>JNC SRT4 ;順序正確(增序或相同),不必交換<BR>SETB F0 ;設立交換標志<BR>MOV
A,R3 ;將兩個數據交換位置<BR>MOV @R0,A<BR>DEC R0<BR>MOV A,R4<BR>MOV
@R0,A<BR>INC R0 ;指向下一個數據<BR>SRT4: DJNZ R2,SRT2 ;完成本遍的比較次數<BR>MOV
A,R6 ;恢復數據首址<BR>MOV R0,A<BR>JB F0,SRT1 ;本遍若進行過交換,則需繼續排序<BR>SRT5: RET
;排序結束<BR>END<BR> <BR>(二) MCS-51
浮點運算子程序庫及其使用說明<BR><BR>本浮點子程序庫有三個不同層次的版本,以便適應不同的應用場合:<BR>1.小型庫(FQ51A.ASM):只包含浮點加、減、乘、除子程序。<BR>2.中型庫(FQ51B.ASM):在小型庫的基礎上再增加絕對值、倒數、比較、平方、開平方、<BR>數制轉換等子程序。<BR>3.大型庫(FQ51.ASM):包含本說明書中的全部子程序。<BR>為便于讀者使用本程序庫,先將有關約定說明如下:<BR>1.雙字節定點操作數:用[R0]或[R1]來表示存放在由R0或R1指示的連續單元中的數<BR>據,地址小的單元存放高字節。如果[R0]=1234H,若(R0)=30H,則(30H)=12H,(31H)=34H。<BR>2.二進制浮點操作數:用三個字節表示,第一個字節的最高位為數符,其余七位為<BR>階碼(補碼形式),第二字節為尾數的高字節,第三字節為尾數的低字節,尾數用雙字節<BR>純小數(原碼)來表示。當尾數的最高位為1時,便稱為規格化浮點數,簡稱操作數。在<BR>程序說明中,也用[R0]或[R1]來表示R0或R1指示的浮點操作數,例如:當[R0]=-6.000時,<BR>則二進制浮點數表示為83C000H。若(R0)=30H,則(30H)=83H,(31H)=0C0H,(32H)=00H。<BR>3.十進制浮點操作數:用三個字節表示,第一個字節的最高位為數符,其余七位為<BR>階碼(二進制補碼形式),第二字節為尾數的高字節,第三字節為尾數的低字節,尾數用<BR>雙字節BCD碼純小數(原碼)來表示。當十進制數的絕對值大于1時,階碼就等于整數<BR>部分的位數,如
876.5 的階碼是03H,-876.5 的階碼是 83H;當十進制數的絕對值小于1<BR>時,階碼就等于 80H
減去小數點后面零的個數,例如 0.00382 的階碼是 7EH,-0.00382<BR>的階碼是
0FEH。在程序說明中,用[R0]或[R1]來表示R0或R1指示的十進制浮點操作數。例<BR>如有一個十進制浮點操作數存放在30H、31H、32H中,數值是
-0.07315,即-0.7315乘以10<BR>的-1次方,則(30H)=0FFH,31H=73H,(32H)=15H。若用[R0]來指向它,則應使(R0)=30H。<BR>4.運算精度:單次定點運算精度為結果最低位的當量值;單次二進制浮點算術運算<BR>的精度優于十萬分之三;單次二進制浮點超越函數運算的精度優于萬分之一;BCD碼浮<BR>點數本身的精度比較低(萬分之一到千分之一),不宜作為運算的操作數,僅用于輸入或<BR>輸出時的數制轉換。不管那種數據格式,隨著連續運算的次數增加,精度都會下降。<BR>5.工作區:數據工作區固定在A、B、R2~R7,數符或標志工作區固定在PSW和23H單<BR>元(位1CH~1FH)。在浮點系統中,R2、R3、R4和位1FH為第一工作區,R5、R6、R7和位1EH<BR>為第二工作區。用戶只要不在工作區中存放無關的或非消耗性的信息,程序就具有較好的<BR>透明性。<BR>6.子程序調用范例:由于本程序庫特別注意了各子程序接口的相容性,很容易采用<BR>積木方式(或流水線方式)完成一個公式的計算。以浮點運算為例:<BR>計算
y = Ln √ | Sin (ab/c+d) |<BR>已知:a=-123.4;b=0.7577;c=56.34;d=1.276;
它們分別存放在30H、33H、36H、<BR>39H開始的連續三個單元中。用BCD碼浮點數表示時,分別為a=831234H;b=007577H;<BR>c=025634H;d=011276H。<BR>求解過程:通過調用BTOF子程序,將各變量轉換成二進制浮點操作數,再進行各<BR>種運算,最后調用FTOB子程序,還原成十進制形式,供輸出使用。程序如下:<BR>TEST:
MOV R0,#39H ;指向BCD碼浮點操作數d<BR>LCALL BTOF ;將其轉換成二進制浮點操作數<BR>MOV
R0,#36H ;指向BCD碼浮點操作數c<BR>LCALL BTOF ;將其轉換成二進制浮點操作數<BR>MOV R0,#33H
;指向BCD碼浮點操作數b<BR>LCALL BTOF ;將其轉換成二進制浮點操作數<BR>MOV R0,#30H
;指向BCD碼浮點操作數a<BR>LCALL BTOF ;將其轉換成二進制浮點操作數<BR>MOV R1,#33H
;指向二進制浮點操作數b<BR>LCALL FMUL ;進行浮點乘法運算<BR>MOV R1,#36H
;指向二進制浮點操作數c<BR>LCALL FDIV ;進行浮點除法運算<BR>MOV R1,#39H
;指向二進制浮點操作數d<BR>LCALL FADD ;進行浮點加法運算<BR>LCALL FSIN
;進行浮點正弦運算<BR>LCALL FABS ;進行浮點絕對值運算<BR>LCALL FSQR ;進行浮點開平方運算<BR>LCALL
FLN ;進行浮點對數運算<BR>LCALL FTOB ;將結果轉換成BCD碼浮點數<BR>STOP: LJMP
STOP<BR>END<BR>運行結果,[R0]=804915H,即y=-0.4915,比較精確的結果應該是-0.491437。<BR> <BR>(1)
標號: FSDT
功能:浮點數格式化<BR><BR>入口條件:待格式化浮點操作數在[R0]中。<BR>出口信息:已格式化浮點操作數仍在[R0]中。<BR>影響資源:PSW、A、R2、R3、R4、位1FH
堆棧需求: 6字節<BR>FSDT: LCALL MVR0 ;將待格式化操作數傳送到第一工作區中<BR>LCALL RLN
;通過左規完成格式化<BR>LJMP MOV0 ;將已格式化浮點操作數傳回到[R0]中<BR><BR>(2) 標號: FADD
功能:浮點數加法<BR><BR>入口條件:被加數在[R0]中,加數在[R1]中。<BR>出口信息:OV=0時,和仍在[R0]中,OV=1時,溢出。<BR>影響資源:PSW、A、B、R2~R7、位1EH、1FH
堆棧需求: 6字節<BR>FADD: CLR F0 ;設立加法標志<BR>SJMP AS ;計算代數和<BR><BR>(3) 標號:
FSUB
功能:浮點數減法<BR><BR>入口條件:被減數在[R0]中,減數在[R1]中。<BR>出口信息:OV=0時,差仍在[R0]中,OV=1時,溢出。<BR>影響資源:PSW、A、B、R2~R7、位1EH、1FH
堆棧需求:6字節<BR>FSUB: SETB F0 ;設立減法標志<BR>AS: LCALL MVR1
;計算代數和。先將[R1]傳送到第二工作區<BR>MOV C,F0 ;用加減標志來校正第二操作數的有效符號<BR>RRC
A<BR>XRL A,@R1<BR>MOV C,ACC.7<BR>ASN: MOV 1EH,C
;將第二操作數的有效符號存入位1EH中<BR>XRL A,@R0 ;與第一操作數的符號比較<BR>RLC A<BR>MOV F0,C
;保存比較結果<BR>LCALL MVR0 ;將[R0]傳送到第一工作區中<BR>LCALL AS1
;在工作寄存器中完成代數運算<BR>MOV0: INC R0 ;將結果傳回到[R0]中的子程序入口<BR>INC R0<BR>MOV
A,R4 ;傳回尾數的低字節<BR>MOV @R0,A<BR>DEC R0<BR>MOV A,R3 ;傳回尾數的高字節<BR>MOV
@R0,A<BR>DEC R0<BR>MOV A,R2 ;取結果的階碼<BR>MOV C,1FH ;取結果的數符<BR>MOV
ACC.7,C ;拼入階碼中<BR>MOV @R0,A<BR>CLR ACC.7 ;不考慮數符<BR>CLR OV
;清除溢出標志<BR>CJNE A,#3FH,MV01;階碼是否上溢?<BR>SETB OV ;設立溢出標志<BR>MV01: MOV
A,@R0 ;取出帶數符的階碼<BR>RET<BR>MVR0: MOV A,@R0 ;將[R0]傳送到第一工作區中的子程序<BR>MOV
C,ACC.7 ;將數符保存在位1FH中<BR>MOV 1FH,C<BR>MOV C,ACC.6
;將階碼擴充為8bit補碼<BR>MOV ACC.7,C<BR>MOV R2,A ;存放在R2中<BR>INC R0<BR>MOV
A,@R0 ;將尾數高字節存放在R3中<BR>MOV R3,A<BR>INC R0<BR>MOV A,@R0
;將尾數低字節存放在R4中<BR>MOV R4,A<BR>DEC R0 ;恢復數據指針<BR>DEC
R0<BR>RET<BR>MVR1: MOV A,@R1 ;將[R1]傳送到第二工作區中的子程序<BR>MOV C,ACC.7
;將數符保存在位1EH中<BR>MOV 1EH,C<BR>MOV C,ACC.6 ;將階碼擴充為8bit補碼<BR>MOV
ACC.7,C<BR>MOV R5,A ;存放在R5中<BR>INC R1<BR>MOV A,@R1
;將尾數高字節存放在R6中<BR>MOV R6,A<BR>INC R1<BR>MOV A,@R1
;將尾數低字節存放在R7中<BR>MOV R7,A<BR>DEC R1 ;恢復數據指針<BR>DEC R1<BR>RET<BR>AS1:
MOV A,R6 ;讀取第二操作數尾數高字節<BR>ORL A,R7<BR>JZ AS2 ;第二操作數為零,不必運算<BR>MOV
A,R3 ;讀取第一操作數尾數高字節<BR>ORL A,R4<BR>JNZ EQ1<BR>MOV A,R6
;第一操作數為零,結果以第二操作數為準<BR>MOV R3,A<BR>MOV A,R7<BR>MOV R4,A<BR>MOV
A,R5<BR>MOV R2,A<BR>MOV C,1EH<BR>MOV 1FH,C<BR>AS2: RET<BR>EQ1: MOV
A,R2 ;對階,比較兩個操作數的階碼<BR>XRL A,R5<BR>JZ AS4 ;階碼相同,對階結束<BR>JB
ACC.7,EQ3;階符互異<BR>MOV A,R2 ;階符相同,比較大小<BR>CLR C<BR>SUBB A,R5<BR>JC
EQ4<BR>EQ2: CLR C ;第二操作數右規一次<BR>MOV A,R6 ;尾數縮小一半<BR>RRC A<BR>MOV
R6,A<BR>MOV A,R7<BR>RRC A<BR>MOV R7,A<BR>INC R5 ;階碼加一<BR>ORL A,R6
;尾數為零否?<BR>JNZ EQ1 ;尾數不為零,繼續對階<BR>MOV A,R2 ;尾數為零,提前結束對階<BR>MOV
R5,A<BR>SJMP AS4<BR>EQ3: MOV A,R2 ;判斷第一操作數階符<BR>JNB
ACC.7,EQ2;如為正,右規第二操作數<BR>EQ4: CLR C<BR>LCALL RR1 ;第一操作數右規一次<BR>ORL
A,R3 ;尾數為零否?<BR>JNZ EQ1 ;不為零,繼續對階<BR>MOV A,R5 ;尾數為零,提前結束對階<BR>MOV
R2,A<BR>AS4: JB F0,AS5 ;尾數加減判斷<BR>MOV A,R4 ;尾數相加<BR>ADD A,R7<BR>MOV
R4,A<BR>MOV A,R3 <BR>ADDC A,R6<BR>MOV R3,A<BR>JNC AS2<BR>LJMP RR1
;有進位,右規一次<BR>AS5: CLR C ;比較絕對值大小<BR>MOV A,R4<BR>SUBB A,R7<BR>MOV
B,A<BR>MOV A,R3<BR>SUBB A,R6<BR>JC AS6<BR>MOV R4,B ;第一尾數減第二尾數<BR>MOV
R3,A<BR>LJMP RLN ;結果規格化<BR>AS6: CPL 1FH ;結果的符號與第一操作數相反<BR>CLR C
;結果的絕對值為第二尾數減第一尾數<BR>MOV A,R7<BR>SUBB A,R4<BR>MOV R4,A<BR>MOV
A,R6<BR>SUBB A,R3<BR>MOV R3,A<BR>RLN: MOV A,R3 ;浮點數規格化<BR>ORL A,R4
;尾數為零否?<BR>JNZ RLN1<BR>MOV R2,#0C1H;階碼取最小值<BR>RET <BR>RLN1: MOV
A,R3<BR>JB ACC.7,RLN2;尾數最高位為一否?<BR>CLR C ;不為一,左規一次<BR>LCALL
RL1<BR>SJMP RLN ;繼續判斷<BR>RLN2: CLR OV ;規格化結束<BR>RET<BR>RL1: MOV A,R4
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -