1. 程式人生 > >浮點暫存器及浮點運算

浮點暫存器及浮點運算

原連結:

浮點執行環境的暫存器主要是8個通用資料暫存器和幾個專用暫存器,它們是狀態暫存器、控制暫存器、標記暫存器等

8個浮點資料暫存器(FPU Data Register),編號FPR0 ~ FPR7。每個浮點暫存器都是80位的,以擴充套件精度格式儲存資料。當其他型別資料壓入資料暫存器時,PFU自動轉換成擴充套件精度;相反,資料暫存器的資料取出時,系統也會自動轉換成要求的資料型別。

      8個浮點資料暫存器組成首尾相接的堆疊,當前棧頂ST(0)指向的FPRx由狀態暫存器中TOP欄位指明。資料暫存器不採用隨機存取,而是按照“後進先出”的堆疊原則工作,並且首尾迴圈。向資料暫存器傳送(Load)資料時就是入棧,堆疊指標TOP先減1,再將資料壓入棧頂暫存器;從資料暫存器取出(Store)資料時就是出棧,先將棧頂暫存器資料彈出,再修改堆疊指標使TOP加1。浮點暫存器棧還有首尾迴圈相連的特點。例如,若當前棧頂TOP=0(即ST(0) = PFR0),那麼,入棧操作後就使TOP=7(即使ST(0) = PFR7),資料被壓入PFR7。所以,浮點資料暫存器常常被稱為浮點資料棧。

      為了表明浮點資料暫存器中資料的性質,對應每個FPR暫存器,都有一個2位的標記(Tag)位,這8個標記tag0 ~ tag7組成一個16位的標記暫存器。

 在計算機中,實數的浮點格式(Floating-Point Format)所示,分成指數、有效數字和符號位三個部分。

·  符號(Sign)——表示資料的正負,在最高有效位(MSB)。負數的符號位為1,正數的符號為0。

·  指數(Exponent)——也被稱為階碼,表示資料以2為底的冪。指數採用偏移碼(Biased Exponent)表示,恆為整數。

·  有效數字(Significand)——表示資料的有效數字,反映資料的精度。有效數字一般採用規格化(Normalized)形式,是一個純小數,所以也被稱為尾數(Mantissa)、小數或分數(Fraction)。

      80x87支援三種浮點資料型別:單精度、雙精度和擴充套件精度;它們的長度依次為32、64和80位,即4、8和10個位元組;它們遵循美國IEEE(電子電氣工程師協會)定義的國際標準浮點格式。

·  單精度浮點數(32位短實數)——由1位符號、8位指數、23位有效陣列成。

·  雙精度浮點數(64位長實數)——由1位符號、11位指數、52位有效陣列成。

·  擴充套件精度浮點數(80位臨時實數)——由1位符號、15位指數、64位有效陣列成。很多計算機中並沒有80位擴充套件精度這種資料型別,80x87 FPU主要在內部使用它存貯中間結果,以保證最終數值的精度。

浮點處理單元FPU具有自己的指令系統,共有幾十種浮點指令,可以分成傳送、算術運算、超越函式、比較、FPU控制等類。浮點指令歸屬於ESC指令,其前5位的操作碼都是11011b,它的指令助記符均以F開頭。

1. 浮點傳送類指令

    浮點資料傳送指令完成主存與棧頂st(0)、資料暫存器st(i)與棧頂之間的浮點格式資料的傳送。浮點資料暫存器是一個首尾相接的堆疊,所以它的資料傳送實際上是對堆疊的操作,有些要改變堆疊指標TOP,即修改當前棧頂。

2. 算術運算類指令

    這類浮點指令實現浮點數、16/32位整數的加、減、乘、除運算,它們支援的定址方式相同。這組指令還包括有關算術運算的指令,例如求絕對值、取整等。

3. 超越函式類指令

    浮點指令集中包含有進行三角函式、指數和對數運算的指令。

4. 浮點比較類指令

    浮點比較指令比較棧頂資料與指定的源運算元,比較結果通過浮點狀態暫存器反映。

5. FPU控制類指令

    FPU控制類指令用於控制和檢測浮點處理單元FPU的狀態及操作方式。

採用浮點指令的組合語言程式格式,與整數指令源程式格式是類似的,但有以下幾點需要注意:

·  使用FPU選擇偽指令

      由於彙編程式MASM預設只識別8086指令,所以要加上.8087 / .287 / .387等偽指令選擇彙編浮點指令;有時,還要加上相應的.238/.386等偽指令。

·  定義浮點資料

      我們知道,資料定義偽指令dd(dword) / dq(qword) / dt(tbyte)依次說明32/64/80位資料;它們可以用於定義單精度、雙精度和擴充套件精度浮點數。為了區別於整數定義,MASM 6.11建議採用REAL4、REAL8、REAL10定義單、雙、擴充套件精度浮點數,但不能出現純整數(其實,整數後面補個小數點就可以了)。相應的資料屬性依次是dword、qword、tbyte。另外,實常數可以用E表示10的冪。

·  初始化浮點處理單元

      每當執行一個新的浮點程式時,第一條指令都應該是初始化FPU的指令finit。該指令清除浮點資料暫存器棧和異常,為程式提供一個“乾淨”的初始狀態。否則,遺留在浮點暫存器棧中的資料可能會產生堆疊溢位。另一方面,浮點指令程式段結束,也最好清空浮點資料暫存器。

浮點傳送程式

           .model small

           .8087                 ;識別浮點指令

           .stack

           .data

f32d       dd 100.25             ;單精度浮點數:42C88000 h

f64d       dq -0.2109375         ;雙精度浮點數:BFCB000000000000 h

f80d       dt 100.25e9           ;擴充套件精度浮點數:4023BABAECD400000000 h

i16d       dw 100                ;字整數:0064 h

i32d       dd -1234              ;短整數:FFFFFB2E h

i64d       dq 123456h            ;長整數:0000000000123456 h

b80d       dt 123456h            ;BCD碼數:00000000000000123456 h

ib32       dd ?

bi80       dt ?

           .code

           .startup

start1:    finit                 ;初始化FPU

           fld f32d              ;壓入單精度浮點數f32d

           fld f64d              ;壓入雙精度浮點數f64d

           fld f80d              ;壓入擴充套件精度浮點數f80d

           fld st(1)             ;壓入當前st(1),即f64d

           fild i16d             ;壓入字整數i16d

           fild i32d             ;壓入短整數i32d

           fild i64d             ;壓入長整數i64d

           fbld b80d             ;壓入BCD碼數b80d

start2:    fist dword ptr ib32   ;將棧頂(現為b80d)以短整數儲存

           fxch                  ;st(0)與st(1)互換,現棧頂為i64d

           fbstp tbyte ptr bi80  ;將棧頂彈出成BCD碼數

start3:    .exit 0

           end