我有一个单行 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/... 检查。
是什么赋予了?