x86机浮点数采用IEEE754编码标准。
浮点运算器(FPU)是专用于浮点运算的处理器,以前的FPU是一种单独芯片,在486之后,英特尔把FPU集成在CPU之内。
浮点寄存器是通过栈结构来实现的,由ST(0)~ST(7)共8个栈空间组成。ST(0)是栈顶,每个浮点寄存器占8个字节。
需要注意的是:float虽然为4个字节,但在计算机内部,和double一样都是以8个字节方式进行处理。当浮点数作为参数时,并不能直接压栈传递参数,这是因为PUSH指令只能传入4字节数据到栈中,这样会丢失4个字节数据。
下面仔细分析,
首先,熟悉一下常用8086浮点数指令:
FLD x | 将浮点数x压入浮点寄存器组中ST(0)~ST(7) |
FILD x | 将整数x压入浮点寄存器组中 |
FST adr | 将浮点寄存器组栈顶数据以浮点形式存入adr地址中 |
FSTP adr | 和FST指令一样,但会执行一次出栈操作 |
FIST adr | 将浮点寄存器组栈顶数据以整数形式存入adr地址中 |
FISTP adr | 和FIST指令一样,但会执行一次出栈操作 |
C语言代码:
float a = 1;
printf("%f\n", a);
用VC++6.0编译链接成8086指令后反汇编:
输出 1.000000
而将printf("%f\n",a)改成printf("%d\n,a)时,输出的却是0而不是16256(0x3F80)。
从上例可以看出,这就是为什么使用printf函数以整数方式输出浮点数时会产生错误。
因为内存中,
ebp-> 0x3F
0x80
0x00
0x00
0x00
0x00
0x00
0x00
printf以整数方式输出时,将对应参数ebp-8h开始的四个字节00000000,所以最终结果输出0。
另外,使用VS2015编译链接成SSE指令后反汇编: