我有一个单线程C函数,它只是return value * pow(1.+rate, -delay);
- 它将未来值折扣为现值。拆卸的有趣的部分是为什么FLD1加载NaN?
0x080555b9 : neg %eax 0x080555bb : push %eax 0x080555bc : fildl (%esp) 0x080555bf : lea 0x4(%esp),%esp 0x080555c3 : fldl 0xfffffff0(%ebp) 0x080555c6 : fld1 0x080555c8 : faddp %st,%st(1) 0x080555ca : fxch %st(1) 0x080555cc : fstpl 0x8(%esp) 0x080555d0 : fstpl (%esp) 0x080555d3 : call 0x8051ce0 0x080555d8 : fmull 0xfffffff8(%ebp)
通过此功能在单步,GDB说(率0.02,延迟为2,你可以看到他们在堆栈上):
(gdb) si 0x080555c6 30 return value * pow(1.+rate, -delay); (gdb) info float R7: Valid 0x4004a6c28f5c28f5c000 +41.68999999999999773 R6: Valid 0x4004e15c28f5c28f6000 +56.34000000000000341 R5: Valid 0x4004dceb851eb851e800 +55.22999999999999687 R4: Valid 0xc0008000000000000000 -2 =>R3: Valid 0x3ff9a3d70a3d70a3d800 +0.02000000000000000042 R2: Valid 0x4004ff147ae147ae1800 +63.77000000000000313 R1: Valid 0x4004e17ae147ae147800 +56.36999999999999744 R0: Valid 0x4004efb851eb851eb800 +59.92999999999999972 Status Word: 0x1861 IE PE SF TOP: 3 Control Word: 0x037f IM DM ZM OM UM PM PC: Extended Precision (64-bits) RC: Round to nearest Tag Word: 0x0000 Instruction Pointer: 0x73:0x080555c3 Operand Pointer: 0x7b:0xbff41d78 Opcode: 0xdd45
而且之后fld1
:
(gdb) si 0x080555c8 30 return value * pow(1.+rate, -delay); (gdb) info float R7: Valid 0x4004a6c28f5c28f5c000 +41.68999999999999773 R6: Valid 0x4004e15c28f5c28f6000 +56.34000000000000341 R5: Valid 0x4004dceb851eb851e800 +55.22999999999999687 R4: Valid 0xc0008000000000000000 -2 R3: Valid 0x3ff9a3d70a3d70a3d800 +0.02000000000000000042 =>R2: Special 0xffffc000000000000000 Real Indefinite (QNaN) R1: Valid 0x4004e17ae147ae147800 +56.36999999999999744 R0: Valid 0x4004efb851eb851eb800 +59.92999999999999972 Status Word: 0x1261 IE PE SF C1 TOP: 2 Control Word: 0x037f IM DM ZM OM UM PM PC: Extended Precision (64-bits) RC: Round to nearest Tag Word: 0x0020 Instruction Pointer: 0x73:0x080555c6 Operand Pointer: 0x7b:0xbff41d78 Opcode: 0xd9e8
在此之后,一切都变成了地狱。事情被严重超过或低估,所以即使我的freeciv AI尝试中没有其他错误,它也会选择所有错误的策略。就像把全军送到北极一样。 (叹息,如果只有我得到那么远。)
我必须失去一些明显的东西,或被某些东西蒙蔽,因为我不能相信fld1
应该可能会失败。更少的是,只有在通过这个函数的一些通过之后它才会失败。在较早的通道中,FPU正确加载1到ST(0)。 0x080555c6的字节编码为fld1
- 在运行过程中用x/...检查。
什么给?
啊,你们摇滚!谢谢!它把我推上了墙。至于为什么会发生这种情况:可能是因为我移动了一个调用另一个函数的函数,该函数从一个文件返回到另一个文件,而在新文件中,没有浮点函数的原型,所以我猜编译器从不弹出返回堆栈的值。尽管如此,我本来预计会尽快用完FP堆栈,但现在看来,现在我已经提供了一个原型,它的工作状况好多了。 现在我可以进入下一个段落了! – 2010-05-14 12:02:26
@Bernd:是的,这肯定会导致这类问题。 – 2010-05-14 17:27:14