c51單片機浮點數(shù)及其匯編程序設計
在單片機應用系統(tǒng)的數(shù)據(jù)處理過程中,經(jīng)常會遇到小數(shù)的運算問題,如求解BCD的增量算式、線性化處理等。因此,需要用二進制數(shù)來表示小數(shù)。表示小數(shù)的方法一般有兩種,定點數(shù)和浮點數(shù)。定點數(shù)結構簡單,與整數(shù)的運算過程相同,運算速度快。但隨著所表示數(shù)的范圍的擴大,其位數(shù)成倍增加,給運算和存儲帶來不便,而且也不能保證相對精度不變。浮點數(shù)的結構相對復雜,但它能夠以固定的字節(jié)長度保持相對精度不變,用較少的字節(jié)表示很大的數(shù)的范圍,便于存儲和運算,在處理的數(shù)據(jù)范圍較大和要求精度較高時,采用浮點數(shù)。
浮點數(shù)的概念
常用的科學計數(shù)法來表示一個十進制數(shù)如
l234.75=1.23475E3=1.23475×103
在數(shù)據(jù)很大或很小時,采用科學計數(shù)避免了在有效數(shù)字前加0來確定小數(shù)點的位置,突出了數(shù)據(jù)的有效數(shù)字的位數(shù),簡化了數(shù)據(jù)的表示?梢哉J為,科學計數(shù)法就是十進制數(shù)的浮點數(shù)表示方法。
在二進制效中,也可以用類似的方法來表示一個數(shù),如
1234.75=10011010010.11(二進制)=0.1001101001011×211
一般表達式為
N=S×2p
在這種表示方法中,數(shù)值由四個部分組成,即尾數(shù)S及符號,階碼P及符號。
在二進制中,通過定義相應字節(jié)或位來表示這四部分,就形成了二進制浮點數(shù)。二進制浮點數(shù)可以有多種不同的表示方法,下面是一種常見的三字節(jié)浮點數(shù)的格式:
其中尾數(shù)占16位,階碼占6位,階符占1位,數(shù)符占1位。階碼通常用補碼來表示。
在這種表示方法中,小數(shù)點的實際位置要由階碼來確定,而階碼又是可變的,因此稱為浮點數(shù)。
1234.75用這種格式的浮點數(shù)表示就是:
0000 1011 1001 1010 0101 1000
用十六進制表示為
1234.75=0B9A58H
-1234.75=4B9A58H
0.171875=043B00H
-0.171875=443B00H
三字節(jié)浮點數(shù)所能表示的最大值為
1×263=9.22×1018
能表示的最小數(shù)的絕對值為
0.5×2-63=5.42×10-20
其所表示的數(shù)的絕對值范圍=(5.42×10-20~9.22×1018),由此可以看到,比三字節(jié)定點數(shù)表示的數(shù)的范圍大得多。
按同樣方法可以定義一個四字節(jié)的浮點數(shù),以滿足更高精度的需要。
規(guī)格化浮點數(shù)
同一個數(shù)用浮點數(shù)表示可以是不同的,如
1234.75=0B9A58H=0C4D2CH=0D2696H
雖然這幾種表示其數(shù)值是相同的,但其尾數(shù)的有效數(shù)字的位數(shù)不同,分別為16位、15位和14位。在運算過程中,為了最大限度地保持運算精度,應盡量增加尾數(shù)的有效位數(shù)。這就需要對浮點數(shù)進行規(guī)格化處理。
在只考慮用二進制原碼表示尾數(shù)時,尾數(shù)的最高位為l,則該浮點數(shù)為規(guī)格化浮點數(shù)。在規(guī)格化浮點數(shù)中,用尾數(shù)為0和最小階碼表示0,三字節(jié)規(guī)格化浮點數(shù)的0表示為410000H。
浮點數(shù)在運算之前和運算之后都要進行規(guī)格化,規(guī)格化過程包括以下步驟:
(1)首先判斷尾是否為0,如果為0,規(guī)格化結果為410000H;
(2)如果尾數(shù)不為0,判斷層數(shù)的最高位是否為1,如果不為1,尾數(shù)左移,階碼減1;
(3)再判斷層數(shù)的最高位是否為1,如果不為1,繼續(xù)進行規(guī)格化操作,如果為1,則規(guī)格化結束。
浮點數(shù)運算
浮點數(shù)運算包括加、減、乘、除四則運算,比較運算,開方運算,多項式運算和函數(shù)運算。其它運算都可用這些基本運算的組合來完成。本節(jié)主要介紹浮點數(shù)四則運算及其子程序。
1.浮點數(shù)的加、減運算
浮點數(shù)的運算就是求結果的尾數(shù)、數(shù)符、階碼包括階符的過程。在加、減運算中,參加運算的浮點數(shù)的階碼可能是不同的,其尾數(shù)所代表的值也是不同的。在這種情況下,尾數(shù)不能直接相加或相減,必須首先使兩個數(shù)的階相同,這一過程稱為對階。一般是讓小階向大階對齊,尾數(shù)相應右移。對階相當于算術中的小數(shù)點對齊或代數(shù)中的通分。尾數(shù)相加或相減得到了結果的尾數(shù)。數(shù)符由尾數(shù)的運算結果的符號確定。階碼就是兩個數(shù)中較大的階碼。
例1 計算132.25+69.75
解: 132.25+69.75=088444H+078B80H=088444H+0845C0H=08CA00H=202
由于兩個浮點數(shù)的階碼分別為8和7,先將加數(shù)的階碼變?yōu)?,其尾數(shù)右移1位。兩個數(shù)的階碼相同后,尾數(shù)直接相加即為和的尾數(shù),和的尾數(shù)的最高位為1,為規(guī)格化浮點數(shù)。
例2 計算12.39-93.1
解: 12.39-93.1=04C651H-07BA33H=87A169H=-80.71
本例中被減數(shù)小于減數(shù),差為負數(shù),結果的數(shù)符為1。差的階碼為兩個數(shù)中較大的階碼。
2.浮點數(shù)乘法運算
如果設參加運算的兩個操作數(shù)分別表示為
Na=(-1)SSa×Sa×2Pa
Nb=(-1)SSb ×Sb×2Pb
它們的積為
N=Na×Nb=(-1)SSa+SSb×(Sa×Sb)×2Pa+Pb
式中SSa和SSb為兩個數(shù)的數(shù)符。
乘法運算可總結為:
(1)積的數(shù)符為乘數(shù)的符號位和被乘數(shù)的符號位按模2求和,即異或;
(2)積的階為乘數(shù)和被乘數(shù)的階的和;
(3)積的尾數(shù)為被乘數(shù)和乘數(shù)的尾數(shù)的積。
參加運算的浮點數(shù)一般都是規(guī)格化的浮點數(shù),尾數(shù)的積小于1,不需進行右規(guī)格化處理。但有可能小于0.5,所以需進行左規(guī)格化處理,使積為規(guī)格化浮點數(shù)。如果乘數(shù)或被乘數(shù)的尾為0、則積為410000H。由于在尾數(shù)相乘時,積的低16位不能反映在結果中,因此,積可能會產(chǎn)生一定的誤差。
例3 算22.4l×4.23。
解: 22.41×4.23=05B349H×03875EH=07BD9AH=94.8
積的階為乘數(shù)和被乘數(shù)的和,即8。尾數(shù)相乘時,積小于0.5,進行左規(guī)格化處理,階碼變?yōu)?。
例4 計算2586.5×(-6.91)。
解: 2586.5×(-6.91)=0CA1BOH×83DD13H=8F8BA0H=-17872
被乘數(shù)為正數(shù),數(shù)符為0,乘數(shù)為負數(shù),數(shù)符為1,積的數(shù)符為0⊕1=1,積為負數(shù)。
3.浮點數(shù)的除法運算
除法運算可以表示為
N=Na/Nb=[(-1)SSa×Sa×2Pa]/[(-1)SSb×Sb×2Pb ]
=(-1)SSa-SSb×(Sa/Sb) ×2Pa-Pb
浮點數(shù)的除法運算可以總結為:
(1) 商的數(shù)符為被除數(shù)與除數(shù)的符號位的差;
(2) 商的階碼為被除數(shù)和除數(shù)的階碼的差;
(3) 商的尾數(shù)為被除數(shù)和除數(shù)的尾數(shù)的商。
規(guī)格化的浮點數(shù)進行除法運算時,尾數(shù)相除,商不會小于0.5,不需進行左規(guī)格化處理。但有可能大于1,有時需進行右規(guī)格化處理。
例5 計算390.67÷14.3l。
解: 390.67÷14.31=09C357H÷04E511H=05DA4EH=27.3
商的階碼為被除數(shù)與除數(shù)的階碼的差。尾數(shù)相除時,結果的最高位為1,商為規(guī)格化浮點數(shù)。
例6 計算 -6.02÷16.157。
解: -6.02÷16.157=83C0AAH÷058143H=FFBEC8H= -0.373
異號相除時,商為負數(shù)。由于被除數(shù)的尾數(shù)大于除數(shù)的尾數(shù),所以被除數(shù)先進行右規(guī)格化,階碼變?yōu)?,商的階碼為 -1,用補碼來表示。
浮點數(shù)運算子程序
通過前面的分析可以看到,浮點運算比較復雜,有其特有的方法和規(guī)律。這里介紹幾種常用的三字節(jié)浮點數(shù)運算子程序,通過分析、設計這些程序,可以進一步了解浮點數(shù)的運算過程和特點,熟悉復雜程序的設計方法。
1.浮點數(shù)通用規(guī)格化子程序
在浮點數(shù)運算過程中,有時需要左規(guī)格化,有時需要右規(guī)格化。通過規(guī)格化子程序既可實現(xiàn)左規(guī)格化,又可實現(xiàn)右規(guī)格化,其具體功能如下:
當Cy=0時,進行右規(guī)格化:F0=0時.對R6(階)R2R3(尾數(shù))右規(guī)格化1位;F0=1時,對R7(階)R4R5(尾數(shù))右規(guī)格化1位。
當Cy=1時,對R6(階)R3R3(尾數(shù))執(zhí)行左規(guī)格化。
程序開始時,判斷是執(zhí)行左規(guī)格化還是右規(guī)格化。如果是右規(guī)格化,還要判斷是對R6(階)R2R3(尾數(shù))還是對R7(階)R4R5(尾數(shù))進行規(guī)格化。如果是左規(guī)格化,直至把操作數(shù)變?yōu)橐?guī)格化浮點數(shù)。其程序框圖如圖4-13所示。程序為:
FSDT: JC LNORMS
MOV C, 39H ;進行右規(guī)格化
JB F0, NR7
MOV A, R2 ;R2R3右移一位
RRC A ;(Cy)移入尾數(shù)最高位
MOV R2, A
MOV A, R3
RRC A
MOV R3, A
INC R6 ;階碼加1
RET
NR7: MOV A, R4
RRC A
MOV R4, A
MOV A, R5
RRC A
MOV R5, A
INC R7
RET
LNORMS: MOV A, R7
JNZ LSHIFT
CJNE R3, #00H, LSBIT8 ;尾數(shù)為0,階碼41H
MOV R6, #41H
LSEND : RET
LSHIFT: JB ACC.7, LSEND
LSBIT8: MOV C, F0
MOV A, R3
RLC A
MOV R3, A
MOV A, R2
RLC A
MOV R2, A
CLR F0
DEC R6
SJMP LNORMS
2.浮點數(shù)加減運算子程序
參加運算的浮點數(shù)可能是正數(shù),也可能是負數(shù)。對于加法運算.當加數(shù)和被加數(shù)的數(shù)符相同時,尾數(shù)相加,不同時尾數(shù)相減;對于減法運算,當減數(shù)和被減數(shù)的數(shù)符相同時,尾數(shù)相減、不同時尾數(shù)相加。當兩個浮點數(shù)的階碼不同時,要進行對階,使小階與大階相等,因此,結果的階碼與其較大的階碼相同。
在執(zhí)行加法運算時,尾數(shù)有可能大于1,因此要進行右規(guī)格化處理;執(zhí)行減法運算時,尾數(shù)有可能小于0.5,因此,要進行左規(guī)格化處理。
下面是三字節(jié)浮點數(shù)加、減法處理于程序,具體功能為:
R6(階)R2R3(尾)±R7(階)R4R5(尾)→R4(階)R2R3(尾);
當位3AH=0時,執(zhí)行加法;
當位3AH=1時,執(zhí)行減法。
程序框圖如圖4—14所示。程序如下:
FABP: MOV A, R6
MOV C, ACC.7
MOV 38H, C ;存被加數(shù)數(shù)符
XRL A, R7
JNB ACC.7, FAB1 ;數(shù)符相同則轉
CPL 3AH ;數(shù)符不等,求反運算標志
圖4-14
FAB1: MOV A, R6
MOV C, ACC.6 ;擴展階碼符號位
MOV ACC.7, C
MOV R6, A
MOV A, R7
CLR C
MOV A, R6
SUBB A, R7
JZ FAB2 ;階碼相同則轉
CLR F0
JB ACC.7, FAB6
CJNE R4, #00H, FAB7
CJNE R5, #00H, FAB7
FAB2: JB 3AH, FAB9 ;轉向尾數(shù)減法
MOV A, R3 ;執(zhí)行尾數(shù)加法
ADD A, R5
MOV R3, A
ADD A, R2
ADDC A, R4
MOV R2, A
JNC FAB4
SETB 39H
CLR C
FAB3: CLR F0
LCALL FSDT
FAB4: CJNE R2, #00H, FAB5
CJNE R3, #00H, FAB5
MOV R4, #41 ;結果為0,規(guī)格化
RET
FAB5: MOV A, R6
MOV C, 38H
MOV ACC.7, C
XCH A, R4
MOV R6, A
RET
FAB6: CJNE R2, #00H, FAB8
CJNE R3, #00H, FAB8
MOV A, R7
MOV R6, A
SJMP FAB2
FAB7: CPL F0
FAB8: CLR C
LCALL FSDT
SJMP FAB1
FAB9: MOV A, R3 ;尾數(shù)相減
CLR C
SUBB A, R5
MOV R3, A
MOV A, R2
SUBB A, R4
MOV R2, A
JNC FAB10
CLR A
CLR C
SUBB A, R3
MOV R3, A
CLR A
SUBB A, R2
MOV R2, A
CPL 38H
FAB10: SETB C
SJMP FAB3
3. 浮點數(shù)乘法運算子程序
浮點數(shù)相乘時,階碼直接相加即獲得積的階碼,尾數(shù)相乘時,結果可能小于0.5,需進行左規(guī)格化處理。下面是三字節(jié)浮點數(shù)乘法運算子程序,具體功能為:
(Ro)指向的三字節(jié)浮點數(shù)×(R1)指向的三字節(jié)浮點數(shù)→R4(階)R2R3(尾數(shù))。
圖4-15三字節(jié)浮點數(shù)乘法的程序框圖。程序為:
FMUL: LCALL FMLD ;傳送浮點數(shù)
MOV A, R6 ;求積的數(shù)符
XRL A, R7
MOV C, ACC.7
MOV 38H, C
LCALL DMUL ;調(diào)用雙字節(jié)無符號數(shù)乘法子程序
MOV A, R7
MOV C, ACC.7
MOV F0, C
MOV A, @R0
ADD A, @R1
MOV R6, A
SETB C
LCALL FSDT ;進行規(guī)格化操作
圖4-15 三字節(jié)浮點數(shù)乘法子程序
MOV A, R6
MOV C, 38H
MOV ACC.7, C ;置積的數(shù)符
MOV R4, A
RET
注:(1)FMLD為浮點數(shù)取數(shù)子程序,功能為:將(R0)指向的三字節(jié)浮點數(shù)送入R6(階)R2R3(尾數(shù))中,將(R1)指向的三字節(jié)浮點數(shù)送入R7(階)R4R5(尾數(shù))中。
(2)DMUL為雙字節(jié)無符號數(shù)乘法子程序。
4.浮點數(shù)除法運算子程序
在進行除法運算時,被除數(shù)的尾數(shù)可能比除數(shù)的尾數(shù)大很多,使結果大于1。為避免這種情況,如果被除數(shù)尾數(shù)大于除數(shù)的尾數(shù),先將被除數(shù)的尾數(shù)右移,使其小于除數(shù)的尾數(shù)。階碼也相應增加,保持其數(shù)值不變。下面是三字節(jié)浮點數(shù)除法運算程序,其功能為:(R0)指向的三字節(jié)浮點數(shù)除以(R1)指向的三字節(jié)浮點數(shù)→R4(階)R2R3(尾數(shù))中。
程序框圖如圖4-16所示。程序為:
FDIV: LCALL FMLD
MOV A, R6
XRL A, R7 ;求商的數(shù)符
MOV C, ACC.7
MOV 38H, C
CLR A
MOV R6, A
MOV R7, A
CJNE R4, #00H, FDIV1
CJNE R5, #00H, FDIV1
SETB C
RET ;除數(shù)為0返回
FDIV1: MOV A, R3 ;比較被除數(shù)與
SUBB A, R5 ;除數(shù)的尾數(shù)
MOV A, R2
SUBB A, R4
JC FDIV2
CLR F0
CLR 39H
LCALL FDST
RRC A
MOV R7, A
CLR C
SJMP FDIV1
FDIV2: CLR A
XCH A, R6
PUSH ACC
LCALL DDIV ;調(diào)用雙字節(jié)除法程序
POP ACC
ADD A, @R0
CLR C
SUBB A, @R1
MOV C, 38H
MOV ACC.7, C
MOV R4, A
CLR C
RET
編輯:admin 最后修改時間:2018-05-19