第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