现在的位置: 首页 > 综合 > 正文

VC6.0下debug和release版本的浮点运算结果不一致实例分析

2014年06月14日 ⁄ 综合 ⁄ 共 2142字 ⁄ 字号 评论关闭

VC6.0debugrelease版本的浮点运算结果不一致实例分析

 

  帖子报告以下程序在VC6.0debugrelease版本的运算结果不同:

#define PI 3.1415926

int main(void)

{

    float num1;

    float num2;

    float val;

    int i;

 

    val = 0;

    for(i = 1; i < 100; i ++)

    {

     num1 = 6548.5f*i/PI;

     num2 = 22234.44/i*PI;

     val += num2*num1;

    }

 

    printf("%x/n", *((unsigned long*)&val));

return 0;

}

 

  上面代码在debug下输出5056cb73,在release下输出5056cb6a

  中间关于计算val的代码可简化为:

    for(i = 1; i < 100; i ++)

    {

     val += 145602230.34f;

    }

 

  简化后仍然是在debug下输出5056cb73,在release下输出5056cb6a

  我们知道debug版本是不优化的,而release版本采用速度优化

  debug版本中的汇编程序是:

:00410A08 C745F400000000          mov [ebp-0C], 00000000

:00410A0F C745F001000000          mov [ebp-10], 00000001

:00410A16 EB09                    jmp 00410A21

:00410A18 8B45F0                  mov eax, dword ptr [ebp-10]

:00410A1B 83C001                  add eax, 00000001

:00410A1E 8945F0                  mov dword ptr [ebp-10], eax

:00410A21 837DF064                cmp dword ptr [ebp-10], 00000064

:00410A25 7D0E                    jge 00410A35

:00410A27 D945F4                  fld dword ptr [ebp-0C]

:00410A2A D80524604200            fadd dword ptr [00426024]

:00410A30 D95DF4                  fstp dword ptr [ebp-0C]

:00410A33 EBE3                    jmp 00410A18

:00410A35 …(以下略)

  上述代码中把val的值存放在[ebp-0C]中。每做一次加法时,先把val[ebp-0C] 压入协处理器的堆栈中,然后加上常数145602230.34。做完加法后把协处理器堆栈栈顶的数据传送到[ebp-0C]中。

  release版本的汇编程序是:

:00401001 D905B4804000            fld dword ptr [004080B4]

:00401007 B863000000              mov eax, 00000063

:0040100C D805B0804000            fadd dword ptr [004080B0]

:00401012 48                      dec eax

:00401013 75F7                    jne 0040100C

:00401015 D9542400                fst dword ptr [esp]

 

  上述代码首先把常数0压入协处理器的堆栈中,然后做99次加法,最后再把结果传送到[esp]中。

  由此可见,两种版本的差异是因fldfstp产生的。debug版本中频繁的fldfstp操作损失了数据精度。这样看来,release版本的精度要比debug版本的高。

  以下是关于fldfstfstp指令的资料:

1、FLD

  指令格式:FLD STReg(*)/MemReal 

  指令功能:将浮点数据压入协处理器的堆栈中。当进行内存单元内容压栈时,系统会自动决定传送数据的精度。比如:用DDREAL4定义的内存单元数值是单精度数等。

2、FST

  指令格式:FST STReg/MemReal 

  指令功能:将协处理器堆栈栈顶的数据传送到目标操作数中。在进行数据传送时,系统自动根据控制寄存器中舍入控制位的设置把栈顶浮点数舍入成相应精度的数据。 

3、FSTP 

  指令格式:FSTP STReg/MemReal 

  指令功能:与FST相类似,所不同的是:指令FST执行完后,不进行堆栈的弹出操作,即:堆栈不发生变化,而指令FSTP执行完后,则需要进行堆栈的弹出操作,堆栈将发生变化。 

  上述资料来源于:

http://topic.csdn.net/u/20071026/18/69b89fec-2dd4-40ce-a0cc-545b7721daca.html

 

 

 

 

抱歉!评论已关闭.