I have a single-layer C function that simply return value * pow(1.+rate, -delay); - It assigns the current value to the future value. The interesting part of the showdown is
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)
When this function is executed once, gdb says (speed is 0.02, the delay is 2, you can see them on the stack):
(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
And after 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
After that, everything goes to hell. Everything becomes too overpriced or underestimated, so even if there were no other errors in my attempt at AI Freeciv, he would choose all the wrong strategies. Like sending the whole army to the Arctic. (Sigh if I went this far.)
I need to skip something obvious or go blind with something because I can't believe fld1 will never work. Moreover, it should fail only after several passes pass through this function. In previous passes, the FPU correctly loads 1 into ST (0). Bytes in 0x080555c6 definitely encode fld1 - checked with x / ... in the current process.
What gives?
source share