FPU環境
FPU 寄存器棧
8個80位的數據寄存器(R0~R7)
16位的狀態寄存器
狀態位
描述
0
不合法的操作
1
不規範化的操作
2
除數爲0的異常
3
上溢出異常
4
下溢出異常
5
精度異常
6
棧錯誤
7
錯誤總體狀態
8
狀態碼C0
9
狀態碼C1
10
狀態碼C2
11~13
棧頂指針
14
狀態碼C3
15
FPU忙標誌
* 示例
# getstatus.s - Get the FPU Status register contents
.section .bss
.lcomm status, 2
.section .text
.globl _start
_start:
nop
fstsw %ax
fstsw status
movl $1, %eax
movl $0, %ebx
int $0x80
* 16位的控制寄存器
* 狀態位
控制位
描述
0
不合法的操作異常掩碼
1
不合規範的操作異常掩碼
2
除於0異常掩碼
3
上溢出異常掩碼
4
下溢出異常掩碼
5
精度異常掩碼
6-7
保留
8-9
精度控制
10-11
湊整控制
12
無窮控制
13-15
保留
* 精度控制
值
描述
00
單精度(24位有效位)
01
沒有使用
10
雙精度(53位有效位)
11
雙擴展精度(64位有效位)default
* 湊整控制
值
描述
00
向最近值取整 default
01
向下取整
10
向上取整
11
向0取整
* 示例
# setprec.s - An example of setting the precision bits in the Control Register
.section .data
newvalue:
.byte 0x7f, 0x00
.section .bss
.lcomm control, 2
.section .text
.globl _start
_start:
nop
fstcw control
fldcw newvalue
fstcw control
movl $1, %eax
movl $0, %ebx
int $0x80
* 16位的標籤寄存器
* 格式
14-15
12-13
10-11
8-9
6-7
4-5
2-3
0-1
R7
R6
R5
R4
R3
R2
R1
R0
* 值
* 00 : 合法的雙擴展精度值
* 01 : 零值
* 10 : 一個特殊的單精度值
* 11 : 空值
* 使用FPU棧
* 示例
# stacktest.s - An example of working with the FPU stack
.section .data
value1:
.int 40
value2:
.float 92.4405
value3:
.double 221.440321
.section .bss
.lcomm int1, 4
.lcomm control, 2
.lcomm status, 2
.lcomm result, 4
.section .text
.globl _start
_start:
nop
finit
fstcw control
fstsw status
filds value1
fists int1
flds value2
fld1 value3
fst %st(4)
fxch %st(1)
fstps result
movl $1, %eax
movl $0, %ebx
int $0x80
* 說明
FINIT : 初始化狀態和控制寄存器
FILDS : 將一個雙字整數放入FPU寄存器
FISTS : 檢索棧頂元素,並放入目的地址
FLDS: 將一個單精度的浮點數放入寄存器
FLDL: 將一個雙精度的浮點數放入寄存器
FST: 將ST0寄存器的值存入另外一個寄存器,不取出棧頂元素
FSTP: 取出棧頂值並放入另外一個寄存器
FXCH: 用於和ST0寄存器交換元素
基本的浮點數運算
指令
描述
FADD
浮點數加法
FDIV
浮點數除法
FDIVR
逆向浮點數加法
FMUL
浮點數乘法
FSUB
浮點數減法
FSUBR
逆向浮點數減法
* 指令描述
FADD source : source + ST0 -> ST0
FADD %st(x), %st(0) : STX + ST0 -> ST0
FADD %st(0) , %st(x) : ST0 + STX -> STX
FADDP %st(0), %st(x) : ST0 + STX -> STX, pop ST0
FADDP : ST0 + ST1 -> ST1, pop ST0
FIADD source : source( 16 or 32 bits int) + ST0 -> ST0
# ((43.65 / 22) + (76.34 * 3.1)) / ((12.43 * 6) - (140.2 / 94.21))
# fpmath.s - An example of basic FPU math
.section .data
value1:
.float 43.65
value2:
.int 22
value3:
.float 76.34
value4:
.float 3.1
value5:
.float 12.43
value6:
.float 6
value7:
.float 140.2
value8:
.float 94.21
output:
.asciz "The result is %f\n"
.section .text
.globl _start
_start:
nop
finit
flds value1
fidiv value2
flds value3
flds value4
fmul %st(1), %st(0)
fadd %st(2), %st(0)
flds value5
fimul value6
flds value7
flds value8
fdivrp
fsubr %st(1), %st(0)
fdivr %st(2), %st(0)
subl $8, %esp
fstpl (%esp)
pushl $output
call printf
add $12, %esp
pushl $0
call exit
高級的浮點數運算
指令
描述
F2XM1
計算ST0的2次方,然後減一
FABS
計算ST0的絕對值
FCHS
對ST0的值取反
FCOS
計算ST0的餘弦值
FPATAN
計算ST0的局部飯正切
FPREM
計算ST0/ST1的餘數
FPREM1
計算ST0/ST1的IEEE格式餘數
FPTAN
計算ST0的正切
FRNDINT
四捨五入ST0到整數
FSCAL
計算ST0的ST1次方
FSIN
計算ST0的正弦
FSINCOS
計算ST0的正弦和餘弦
FSQRT
計算ST0的平方根
FYL2X
計算ST1*logST0(base 2)
FYL2XP1
計算ST1*log(ST0+1)(base 2)
# fpmath2.s - An example of the FABS, FCHS, and PSQRT instructions
.section .data
value1:
.float 395.21
value2:
.float -9145.290
value3:
.float 64.0
.section .text
.globl _start
_start:
nop
finit
flds value1
fchs
flds vlaue2
fabs
flds value3
fsqrt
mov $1, %eax
mov $0, %ebx
int $0x80
(gdb) info all
# roundtest.s - An example of the FRNDINT instruction
.section .data
value1:
.float 3.65
rdown:
.byte 0x7f, 0x07
rup:
.byte 0x7f, 0x0b
.section .bss
.lcomm result1, 4
.lcomm result2, 4
.lcomm result3, 4
.section .text
.globl _start
_start:
nop
finit
flds value1
frndint
fists result1
fldcw rdown
flds value1
frndint
fists result2
fldcw rup
flds value1
frndint
fists result3
movl $1, %eax
movl $0, %ebx
int $0x80
# premtest.s - An example of using the FPREM1 instruction
.section .data
value1:
.float 20.65
value2:
.float 3.97
.section .bss
.lcomm result, 4
.section .text
.globl _start
_start:
nop
finit
flds value2
flds value1
loop:
fprem1
fstsw %ax
testb $4, %ah
jnz loop
fsts result
movl $1, %eax
movl $0, %ebx
int $0x80
# trigtest.s - An example of using the FSIN and FCOS instructions
.section .data
degree1:
.float 90.0
val180:
.int 180
.section .bss
.lcomm radian1, 4
.lcomm result1, 4
.lcomm result2, 4
.section .text
.globl _start
_start:
nop
finit
flds degree1
fidivs val180
fldpi
fmul %st(1), %st(0)
fsts randian1
fsin
fsts result1
flds randian1
flds randian1
fcos
fsts result2
movl $1, %eax
movl $0, %ebx
int $0x80
浮點數的條件分支
指令
描述
FCOM
比較ST0與ST1
FCOM ST(x)
比較ST0與STX
FCOM source
比較ST0與source
FCOMP
比較ST0與ST1,popST0
FCOMP ST(X)
比較後出棧
FCOMP source
比較後出棧
FCOMPP
比較後出棧2次
FTST
比較ST0與0
條件
C3
C2
C0
ST0 > source
0
0
0
ST0 < source
0
0
1
ST0 == source
1
0
0
# fcomtest.s - An example of the FCOM instruction
.section .data
value1:
.float 10.923
value2:
.float 4.5532
.section .text
.globl _start
_start:
nop
flds value1
fcoms value2
fstsw
sahf
ja greater
jb lessthan
movl $1, %eax
movl $0, %eax
int $0x80
greater:
movl $1, %eax
movl $2, %eax
int $0x80
lessthan:
movl $1, %eax
movl $1, %eax
int $0x80
指令
描述
FCOMI
比較ST0與ST1
FCOMIP
比較ST0與ST(X), 然後出棧
FUCOMI
比較前檢查無序值
FUCOMIP
比較前檢查無序值並出棧
條件
ZF
PF
CF
ST0 > ST(x)
0
0
0
ST0 < ST(x)
0
0
1
ST0 = ST(x)
1
0
0
# fcomitest.s - An example of the FCOMI instruction
.section .data
value1:
.float 10.923
value2:
.float 4.5532
.section .text
.globl _start
_start:
nop
flds value2
flds value1
fcomi %st(1), %st(0)
ja greater
jb lessthan
movl $1, %eax
movl $0, %eax
int $0x80
greater:
movl $1, %eax
movl $2, %eax
int $0x80
lessthan:
movl $1, %eax
movl $1, %eax
int $0x80
指令
描述
FCMOVB
如果ST0 < ST(x) 移動
FCMOVE
如果ST0 = ST(x) 移動
FCMOVBE
如果ST0 <= ST(x) 移動
FCMOVU
如果ST0無序 移動
FCMOVNB
如果!ST0 < ST(x) 移動
FCMOVNE
如果 !ST0 = ST(x) 移動
FCMOVNBE
如果! ST0 <= ST(x) 移動
FCMOVNU
如果!ST0無序 移動
# fcmovtest.s - An example of the FCMOVxx instruction
.section .data
value1:
.float 20.5
value2:
.float 10.90
.section .text
.globl _start
_start:
nop
finit
flds value1
flds value2
fcomi %st(1), %st(0)
fcmovb %st(1), %st(0)
movl $1, %eax
movl $0, %ebx
int $0x80
保存和設置FPU狀態
保存和重載FPU環境
命令
FSEENV
保存內容
控制寄存器
狀態寄存器
標籤寄存器
FPU指令指針偏移
FPU數據指針
FPU上次操作碼執行結果
示例
# fpuenv.s - An example of the FSTENV and FLDENV instructions
.section .data
value1:
.float 12.34
value2:
.float 56.789
rup:
.byte 0x7f, 0x0b
.section .bss
.lcomm buffer, 28
.section .text
.globl _start
_start:
nop
finit
flds value1
flds value2
fldcw rup
fstenv buffer
finit
flds value2
flds value1
fldenv buffer
movl $1, %eax
movl $0, %ebx
int $0x80
#fpusave.s - An example of the FSAVE and FRSTOR instructions
.section .data
value1:
.float 12.34
value2:
.float 56.789
rup:
.byte 0x7f, 0x0b
.section .bss
.lcomm buffer, 108
.section .text
.globl _start
_start:
nop
finit
flds value1
flds value2
fldcw rup
fsave buffer
flds value2
flds value1
frstor buffer
movl $1, %eax
movl $0, %ebx
int $0x80
指令
描述
FNCLEX
清除浮點數異常標識
FNSAVE
保存FPU狀態
FNSTCW
保存FPU控制寄存器
FNSTENV
保存FPU環境
FNSTSW
保存FPU狀態寄存器
優化浮點數運算
確保浮點數沒有溢出
設置單精度浮點數的精度控制標識
對簡單的三角函數運算使用查找表
將鏈式運算拆解
儘量長的保存方程式的值
儘量將INT轉換成浮點數,再運算
使用FCOMI 代替FCOM