浮點運算

浮點運算

浮點運算就是實數運算,因為計算機只能存儲整數,所以實數都是約數,這樣浮點運算是很慢的而且會有誤差。

現在大多數機器都是32位的,也就是說32位都用來表示整數的話,那麼對於無符號整數就是0 到 2^32-1,對於有符號的話就是-2^31 到 2^31-1。

簡介


當我們用不同的電腦計算圓周率時,會發現一台電腦的計算較另一台來講結果更加精確。或者我們在進行槍戰遊戲的時候,當一粒子彈擊中牆壁時,牆上剝落下一塊牆皮,同樣的場面在一台電腦上的表現可能會非常的呆板、做作;而在另外一台電腦上就會非常生動形象,甚至與我們在現實中看到的所差無幾。這都是浮點運算能力的差異導致的。
如果是實數的話,就不是這樣了,機器有兩種辦法表示實數,一種是定點,就是小數點位置是固定的,一種是浮點,就是小數點位置不固定,計算方法也比較麻煩,通常會比整數運算代價大很多。
FPU->Floating Point Unit,浮點運算部件。
BCD->Binary Coded Decimal 壓縮的二進位數,是用4個位來表示數字0~9,一個byte表示兩個十進位數,比如正常二進位數1001111表示79,而BCD中用 0111 1001 來表示79。
科學計數法:a×10的n次冪的形式。將一個數字錶示成(a×10的n次冪的形式),其中1≤|a|<10,n表示整數,這種記數方法叫科學記數法。

數據


浮點運算使用三種不同的數據:
1)整數(Integer),又分為字,短整數(Short Integer)和長整數(longint)。
2)實數(Real)分單精度(Single Real)和雙精度(Double Real)。
3)壓縮的二十進位數(BCD)。
下面是其位數(bits)和能表示的大致範圍和
Type Length Range
-----------------------------------------------
Word Integer 16 bit -32768 to 32768
Short Integer 32 bit -2.14e9 to 2.14e9
Long Integer 64 bit -9.22e18 to 9.22e18
Single Real 32 bit 1.18e-38 to 3.40e38
Double Real 64 bit 2.23e-308 to 1.79e308
extended Real 80 bit 3.37e-4932 to 1.18e4932
Packed BCD 80 bit -1e18 to 1e18
雙精度數和擴展精度數表示範圍對一般應用來說已經足夠大了!

整數

以補碼形式存儲,正數的補碼是其本身,負數補碼是其絕對值的各位變反后加1,下面是實際存儲的例子:
0024 var1 dw 24
FFFE var2 dw -2
000004D2 var3 dd 1234
FFFFFF85 var4 dd -123
0000000000002694var5 dq 9876

BCD數

在FPU中用80位表示正好是浮點堆寄存器的寬度,在其格式如下存儲:
Bit
79___72_71________________________________________0
符號 ---18個二十進位數——————————---
看下面的例子:
00000000000000012345 var1 dt 12345
80000000000000000100 var2 dt -100

浮點數

這個複雜點,有三種格式
單精度:_31_30________23_22___________0
符號 指數 有效數。
雙精度:_63_62__________52_51__________________0
符號 指數 有效數。
擴展精度數:
_79_78____________64_63___________________0
符號 指數 有效數。

部件


FPU從功能上分為兩個部分:控制單元和運算單元,控制單元主要面向CPU,而算數單元負責具體算數運算.
FPU即浮點部件包括8個通用寄存器,5個錯誤指針寄存器和三個控制寄存器。
1、8個通用寄存器每個80 bit,形成一個寄存器堆棧,所有的計算結果都保存在寄存器堆棧中,其中數據全部是80位的擴展精度格式,即使是BCD,整數,單精度和雙精度等在裝入寄存器的時候都要被FPU自動轉化為80位的擴展精度格式,注意棧頂通常表示為ST(0),然後是ST(1)...ST(i),ST(i)是相對於棧頂而言的。
堆棧很相似,只不過寬度為80bit,映像如下:
_______________________
| ST(0) |
|_______________________|
| ST(1) |
|_______________________|
| ...... |
| ...... |
| ST(i) |
|_______________________|
2、控制寄存器,FPU有三個控制寄存器:狀態寄存器,控制寄存器和標記寄存器。
狀態寄存器->SW
_M_____D________10___9____8___7_________5_________________________0__
| B | C3| TOP| C2 | C1 | C0 | ES | | PE | UE | OE | ZE | DE | IE |
|____|____|____|____|____|____|____|____|____|____|____|____|____|____|
B: 浮點部件正忙。
C0-C3 指示浮點運算的結果,不同指令有不同含義。
TOP 指示棧頂,通常是0。
ES 以下任何位置位 (pe,ue,oe,ze,de,or ie) 則置位。
PE 精度故障。
UE 數字太小無法表示溢出。
OE 現有精度無法表示,數字太大溢出。
ZE 除0錯。
DE 指示至少有一個操作數未規格化。
IE 無效錯誤,指示堆棧上溢或下溢,無效操作數等。
控制寄存器:
_15____________10___9____8___7_________5______________________0__
| |IC | RC | PC | | PM | UM | OM | ZM | DM | IM |
|____|____|____|___|__|_|__|__|____|____|____|____|____|____|____|
IC 無窮大控制,對486,已經無效。
RC 舍入控制。
00 = 朝最接近或者偶數舍入。
01 = 朝負無窮大方向舍入。
10 = 朝正無窮大方向舍入。
11 = 超0方向截斷。
PC 精度控制。
00 = 單精度。
01 = 保留。
10 = 雙精度。
11 = 擴展精度。
PM~IM 屏蔽狀態寄存器低5位指示的錯誤。為1則屏蔽。
標記寄存器:
每2 bit表示一個對應堆棧寄存器的狀態,具體含義如下:
15________________________________________3_____0
|Tag7 |...................................|tag1|
|_____|___________________________________|____|
含義:
00 = 有效。
01 = 零。
10 = 無效或無窮大。
11 = 為空。

格式


單精度:_31_30________23_22___________0
符號 指數 有效數。
雙精度:_63_62__________52_51__________________0
符號 指數 有效數。
擴展精度數: _79_78____________64_63___________________0
符號 指數 有效數。
例子:
C377999A var1 dd -247.6
40000000 var2 dd 2.0
486F4200 var3 real4 2.45e+5
4059100000000000 var4 dq 100.25
3F543BF727136A40 var5 real8 0.00123
C377999A var1 dd -247.6
40000000 var2 dd 2.0
486F4200 var3 real4 2.45e+5
4059100000000000 var4 dq 100.25
3F543BF727136A40 var5 real8 0.001235
400487F34D6A161E4F76 var6 real10 33.9876
DD和real4都可以在asm中來定義單精度浮點數,4 bytes
DQ和real8都可以在asm中來定義雙精度浮點數,8 bytes
DT和real10都可以在asm中來定義擴展精度浮點數,10 bytes
浮點運算
浮點運算

指令系統分類


浮點指令系統分為五類:數據傳送類、算術運算類、超越函數類、比較類、環境及系統控制類。
我並不想列出所有函數的參數以及用法,具體參考資料見文章最後。

1、數據傳送類

這類指令主要是從內存裝入浮點寄存器堆數據,一般目的地址總是棧頂ST(0),用調試器你可以清楚地看到這一點。注意帶P結尾的操作,是在前面操作完成之後出棧,也就是原來ST(1)的內容現在成了ST(0)的內容,注意到這一點,你可以方便地設計出靈活多變的程序。
裝入:
FLD Push real onto stack
FILD Convert two's complement integer to real and push
FBLD Convert BCD to real and push to stack
存儲:
FST Store floating-point number from stack
FSTP Convert top of stack to integer
FIST
FISTP Convert top of stack to integer
FBSTP Store BCD to integer and pop stack
交換:
FXCH Exchange top two stack elements
常數裝載:
FLD1 裝入常數1.0
FLDZ 裝入常數0.0
FLDPI 裝入常數pi (=3.1415926....精度足夠,放心使用)
FLDL2E 裝入常數log(2)e
FLDL2T 裝入常數log(2)10
FLDLG2 裝入常數log(10)2
FLDLN2 裝入常數Log(e)2

2、算術運算類

加法:
FADD/FADDP Add/add and pop
FIADD Integer add
減法:
FSUB/FSUBP Subtract/subtract and pop
FSUBR/FSUBRP Subtract/subtract and pop with reversed operands
FISUB Integer subtract
FISUBR Integer subtract/subtract with reversed operands
乘法:
FMUL/FMULP Multiply/multiply and pop
FIMUL Integer multiply
除法:
FDIV/FDIVP Divide/divide and pop
FIDIV Integer divide
FDIVR/FDIVRP Divide/divide and pop with reversed operands
FIDIVR integer divide with reversed operands
其他:
FABS Calculate absolute value
FCHS Change sign
FRNDINT Round to integer
FSQRT Calculate square root
FSCALE Scale top of stack by power of 2
FXTRACT Separate exponent and mantissa
FPREM Calculate partial remainder
FPREM1 Calculate partial remainder in IEEE format
如果指令後面未帶操作數,其默認的操作數為ST(0)和ST(1),關於帶R後綴的指令是正常操作數的順序變反,比如fsub執行的是x-y,fsubr執行的就是y-x。

3、超越函數類

FSIN Calculate sine
FCOS Calculate cosine
FSINCOS Calculate quick sine and cosine
FPTAN Calculate partial tangent
FPATAN Calculate partial arctangent
Log類
FYL2X Calculate y times log base 2 of x
FYL2XP1 Calculate y times log base 2 of (x+1)
F2XM1 Calculate (2^x)-1

4、比較類

FCOM Compare
FCOMP Compare and pop
FICOM Integer compare
FTST Integer compare and pop
FUCOM Unordered compare
FUCOMP Unordered compare and pop
FXAM Set condition code bits for value at top of stack
FSTSW Store status word
會根據結果設置,C0~C3,在上面並未就C0~C3進行具體介紹,C1是用來判斷上溢或者下溢的,C0相當於EFLAGS裡面的CF,作用也基本一致,C2相當於PF,C3相當於ZF,可能會看到如下指令:
FSTSW ax
SAHF
JZ label
為什麼如此呢,因為用如上指令將狀態字存入EFLAGS,C0正好置於CF位,C3正好置於ZF位.

5、環境及系統控制類

FLDCW Load control word
FSTCW Store control word
FSTSW Store status word
FLDENV Load environment block
FSTENV Store environment block
FSAVE Save coprocessor state
FRSTOR Restore coprocessor state
FINIT Initialize coprocessor
FCLEX Clear exception flags
FINCSTP Increment stack pointer
FDECSTP Decrement stack pointer
FFREE Mark element as free
FNOP No operation
FWAIT Wait until floating-point instruction complete

例子


計算機里整數和小數形式就是按普通格式進行存儲,例如1024、3.1415926等等,這個沒什麼特點,但是這樣的數精度不高,表達也不夠全面,為了能夠有一種數的通用表示法,就發明了浮點數
浮點數的表示形式有點像科學計數法(*.*****×10^***),它的表示形式是0.*****×10^***,在計算機中的形式為 .***** e ±***),其中前面的星號代表定點小數,也就是整數部分為0的純小數,後面的指數部分是定點整數。利用這樣的形式就能表示出任意一個整數和小數,例如1024就能表示成0.1024×10^4,也就是 .1024e+004,3.1415926就能表示成0.31415926×10^1,也就是 .31415926e+001,這就是浮點數。浮點數進行的運算就是浮點運算。
浮點運算比常規運算更複雜,因此計算機進行浮點運算速度要比進行常規運算慢得多。

其他


另外,浮點運算的常見形式是開方運算。目前所有的計算機都用的是浮點運算,普通人的電腦也用的是浮點運算。
浮點運算
浮點運算