第64部分- Linux x86 64位彙編 FPU之一介紹
FPU是一個自持單元,使用與标準處理器寄存器分離的一組寄存器處理浮點操作。包括8個80位資料寄存器和3個16位寄存器(用于狀态,控制和标記)。
FPU資料寄存器稱為R0到R7,它們連接配接在一起形成一個堆棧(R7是頂端就是st0寄存器)。
狀态寄存器
FPU有自己的狀态寄存器,包含在一個16位寄存器中。可以通過fstsw指令來讀取。

控制寄存器
控制FPU内的浮點功能,用于計算浮點值的精度以及用于舍入浮點結果的方法。可以通過fstcw把控制寄存器進行加載。
精度控制可以設定為四位
00 單精度
01 未使用
10 雙精度
11 擴充雙精度(預設為擴充雙精度)
舍入控制
00 舍入到最近值(預設舍入到最近值)
01 向下舍入
10 向上舍入
11 向零舍入
示例
.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
執行過中,檢視擷取到的寄存器的值。
(gdb) x /x &control
0x6000d6 <control>: 0x00000000
(gdb) s
(gdb) x /x &control
0x6000d6 <control>: 0x0000037f
(gdb) s
(gdb) s
(gdb) x /x &control
0x6000d6 <control>: 0x0000007f
标記寄存器
标記寄存器用于辨別8個80位FPU資料寄存器中的值。
每個标記值對應一個實體的FPU寄存器。每個寄存器對應2位值可以表明寄存器内容的4個特殊代碼之一。
00 一個合法的擴充雙精度
01 零值
10 特殊的浮點值
11 無内容
FPU基本使用例子
.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;//初始化FPU
fstcw control;//控制器寄存器
fstsw status;//狀态寄存器
filds value1;//把一個雙字整數值加載到FPU寄存器堆棧中,st0。
fists int1;//擷取寄存器堆棧頂部的值,并存放到目标位置
flds value2;//加載values2的單精度浮點值到FPU寄存器堆棧中
fldl value3;// 加載values3的雙精度浮點值到FPU寄存器堆棧中
fst %st(4) ;//将st0寄存器傳送到st4
fxch %st(1) ;//交換st0和st1
fstps result;//将st0加載到result,并彈出st0.
movl $1, %eax
movl $0, %ebx
int $0x80
as -o stacktest.o stacktest.s
ld -o stacktest stacktest.o
執行後如下:
(gdb) i r st0
st0 221.440321000000011509 (raw 0x4006dd70b8e086bdf800)
(gdb) i r st1
st1 92.44049835205078125 (raw 0x4005b8e1890000000000)
(gdb) i r st2
st2 40 (raw 0x4004a000000000000000)