从x86函数返回时发信号通知NaN已损坏(x87的flds / fstps)

osgx:

我在x86(32位)linux gcc上有奇怪的行为。我使用gcc的__builtin_nansf("")Builtin 生成信号NaN ,生成0x7fa00000。从函数以float形式返回此值后,将其修改为0x7fe00000。有一个简短的例子:

#include <stdio.h>
float f = __builtin_nansf("");
float y;

float func (void)
{
  return f;
}

int main (void)
{
  printf("%x\n", *((int*)&f));
  y = func();
  printf("%x\n", *((int*)&y));
}

用编译的程序gcc-4.6.2 program.c,其输出:

7fa00000
7fe00000

Gdb:

(gdb) p/x f   
$2 = 0x7fa00000
...
(gdb) si
0x08048412 in func ()
1: x/i $pc
0x8048412 <func+14>:    flds   -0x4(%ebp)
(gdb) x/x $ebp-4
0xbfffeb34: 0x7fa00000
(gdb) si
(gdb) info all-regis
st0            nan(0xe000000000000000)  (raw 0x7fffe000000000000000)
... //after return from func
(gdb) si
0x0804843d in main ()
1: x/i $pc
0x804843d <main+38>:    fstps  0x804a024
(gdb) si
(gdb) x/x 0x804a024
0x804a024 <y>:  0x7fe00000

为什么我的信号NaN被修改?如何防止这种修改?

布雷特·黑尔(Brett Hale):

我不确定您可以阻止这种情况。在x87上加载sNaN通常会引发INVALID异常,然后通过设置(23位)尾数的msb将该值转换为qNaN。也就是说,与0x00400000进行“或”运算。

英特尔 ®64 和IA-32体系结构软件开发人员手册》第1卷第4.8.3.4节介绍了sNan / qNan处理。第8章讨论X87 FPU编程。第3卷22.18还介绍了X87 FPU如何处理NaN。

我没有看到X87控制字中的任何位会产生您期望的sNaN传播行为。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章