我有一个单行 C 函数,它只是return value * pow(1.+rate, -delay);
- 它将未来值折扣为现值。拆解的有趣部分是
0x080555b9 : 否定 %eax 0x080555bb : 推 %eax 0x080555bc : 字段 (%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 : 调用 0x8051ce0 0x080555d8 : fmull 0xfffffff8(%ebp)
在单步执行此函数时,gdb 说(速率为 0.02,延迟为 2;您可以在堆栈上看到它们):
(gdb) 硅 0x080555c6 30 返回值 * pow(1.+rate, -delay); (gdb) 信息浮动 R7:有效 0x4004a6c28f5c28f5c000 +41.68999999999999773 R6:有效 0x4004e15c28f5c28f6000 +56.34000000000000341 R5:有效 0x4004dceb851eb851e800 +55.22999999999999687 R4:有效 0xc0008000000000000000 -2 =>R3:有效 0x3ff9a3d70a3d70a3d800 +0.02000000000000000042 R2:有效 0x4004ff147ae147ae1800 +63.77000000000000313 R1:有效 0x4004e17ae147ae147800 +56.36999999999999744 R0:有效 0x4004efb851eb851eb800 +59.92999999999999972 状态字:0x1861 IE PE SF 顶部:3 控制字:0x037f IM DM ZM OM UM PM PC:扩展精度(64 位) RC:四舍五入到最近 标签字:0x0000 指令指针:0x73:0x080555c3 操作数指针:0x7b:0xbff41d78 操作码:0xdd45
之后fld1
:
(gdb) 硅 0x080555c8 30 返回值 * pow(1.+rate, -delay); (gdb) 信息浮动 R7:有效 0x4004a6c28f5c28f5c000 +41.68999999999999773 R6:有效 0x4004e15c28f5c28f6000 +56.34000000000000341 R5:有效 0x4004dceb851eb851e800 +55.22999999999999687 R4:有效 0xc0008000000000000000 -2 R3:有效 0x3ff9a3d70a3d70a3d800 +0.02000000000000000042 =>R2: 特殊 0xffffc000000000000000 实数不定 (QNaN) R1:有效 0x4004e17ae147ae147800 +56.36999999999999744 R0:有效 0x4004efb851eb851eb800 +59.92999999999999972 状态字:0x1261 IE PE SF C1 顶部:2 控制字:0x037f IM DM ZM OM UM PM PC:扩展精度(64 位) RC:四舍五入到最近 标签字:0x0020 指令指针:0x73:0x080555c6 操作数指针:0x7b:0xbff41d78 操作码:0xd9e8
在这之后,一切都下地狱了。事情被严重高估或低估了,所以即使我的 freeciv AI 尝试中没有其他错误,它也会选择所有错误的策略。就像派全军去北极一样。(叹气,要是我能走那么远就好了。)
我一定是遗漏了一些明显的东西,或者被某些东西蒙蔽了双眼,因为我无法相信这fld1
会失败。更不用说它只在少数通过此功能后才会失败。在较早的传递中,FPU 正确地将 1 加载到 ST(0) 中。0x080555c6 处的字节肯定会编码fld1
- 在正在运行的进程中使用 x/... 检查。
是什么赋予了?