Why does FLD1 load NaN?

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?

+4
source share
2 answers

It fits well. What you have here is stack overflow .

In particular, you (or perhaps your compiler) have overflowed the x87 stack. It can contain only 8 values, and while fld1 is issued, it is already full (indicated by the tag word 0000 ). Thus, fld1 overflows the stack (indicated by the symbol IE, SF, C1 ), which causes the result you see.

As for this, you could use MMX instructions without using EMMS before using x87 instructions, or your compiler has an error, or you have build code somewhere that violates your ABI platform (or the library that you use violates ABI).

+6
source

It looks like you have an FPU stack overflow. The FPU tag word is 0, which means all registers are used. You can also see all registers marked as “valid” when I expect some to be empty.

I do not know why this will happen. Maybe you have an MMX code that does not issue an EMMS command? Or maybe some inline assembly that does not clear the stack properly?

+4
source

Source: https://habr.com/ru/post/1309713/


All Articles