天天看點

第64部分- Linux x86 64位彙編 FPU之一介紹第64部分- Linux x86 64位彙編 FPU之一介紹示例FPU基本使用例子

第64部分- Linux x86 64位彙編 FPU之一介紹

FPU是一個自持單元,使用與标準處理器寄存器分離的一組寄存器處理浮點操作。包括8個80位資料寄存器和3個16位寄存器(用于狀态,控制和标記)。

FPU資料寄存器稱為R0到R7,它們連接配接在一起形成一個堆棧(R7是頂端就是st0寄存器)。

狀态寄存器

FPU有自己的狀态寄存器,包含在一個16位寄存器中。可以通過fstsw指令來讀取。

第64部分- Linux x86 64位彙編 FPU之一介紹第64部分- Linux x86 64位彙編 FPU之一介紹示例FPU基本使用例子

控制寄存器

控制FPU内的浮點功能,用于計算浮點值的精度以及用于舍入浮點結果的方法。可以通過fstcw把控制寄存器進行加載。

第64部分- Linux x86 64位彙編 FPU之一介紹第64部分- Linux x86 64位彙編 FPU之一介紹示例FPU基本使用例子

精度控制可以設定為四位

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資料寄存器中的值。

第64部分- Linux x86 64位彙編 FPU之一介紹第64部分- Linux x86 64位彙編 FPU之一介紹示例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)

繼續閱讀