天天看點

第70部分- Linux x86 64位彙編 FPU之儲存和恢複第70部分- Linux x86 64位彙編 FPU之儲存和恢複FSAVE示例

第70部分- Linux x86 64位彙編 FPU之儲存和恢複

FPU資料寄存器用于自己的FPU計算完,還用于MMX技術的計算。

是以涉及到FPU狀态的儲存和恢複。

FSTENV指令用于把FPU環境存儲到一個記憶體塊中。

會儲存如下寄存器:

控制寄存器/狀态寄存器/标記寄存器/FPU指令指針偏移量/FPU資料指針/FPU最後執行的操作碼,并沒有儲存資料,如果要儲存資料,則必須要使用FSAVE指令。

FLDENV指令用于把記憶體塊的值加載會FPU環境中。

FSTENV示例

.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;//初始化FPU,所有stx設定為0
   flds value1;//加載value1到st0
   flds value2;// 加載value2到st0,value1到st1中。
   fldcw rup;//加載控制器内容為0x7f,0x0b
   fstenv buffer;//加載FPU環境到buffer
   finit;//初始化FPU
   flds value2;//重新加載value2到st0
   flds value1;// 重新加載value1到st0,value2到st1中。
   fldenv buffer;//從buffer中恢複FPU環境

   movq $60,%rax
   syscall
           

as -g -o fpuenv.o fpuenv.s

ld -o fpuenv fpuenv.o

這裡例子通過gdb來進行反彙編檢視。

通過(gdb) x /28b &buffer來檢視buffer中内容。儲存之後内容如下:

(gdb) x /28b &buffer

0x600100 <buffer>: 0x7f    0x0b    0xff    0xff    0x00    0x30    0xff    0xff

0x600108 <buffer+8>:   0xff    0x0f    0xff    0xff    0xbb    0x00    0x40    0x00

0x600110 <buffer+16>:  0x00    0x00    0x00    0x00    0x00    0x00    0x00    0x00

0x600118 <buffer+24>:  0x00    0x00    0xff    0xff

通過info all檢視fpu的寄存器。

FSAVE示例

.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 

    movq $60,%rax ;//此處設定斷點進行寄存器觀察恢複後
   syscall
           

as -g -o fpusave.o fpusave.s

ld -o fpusave fpusave.o

在fsave之前如下:

st0            56.78900146484375   (raw 0x4004e327f00000000000)

st1            12.340000152587890625   (raw 0x4002c570a40000000000)

st2            0    (raw 0x00000000000000000000)

st3            0    (raw 0x00000000000000000000)

st4            0    (raw 0x00000000000000000000)

st5            0    (raw 0x00000000000000000000)

st6            0    (raw 0x00000000000000000000)

st7            0    (raw 0x00000000000000000000)

fctrl          0xb7f   2943

fstat          0x3000  12288

ftag           0xfff   4095

在fsave之後如下,堆棧頂部值移動了:

st0            0    (raw 0x00000000000000000000)

st1            0    (raw 0x00000000000000000000)

st2            0    (raw 0x00000000000000000000)

st3            0    (raw 0x00000000000000000000)

st4            0    (raw 0x00000000000000000000)

st5            0    (raw 0x00000000000000000000)

st6            56.78900146484375   (raw 0x4004e327f00000000000)

st7            12.340000152587890625   (raw 0x4002c570a40000000000)

fctrl          0x37f   895

繼續閱讀