第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)