当前位置:  开发笔记 > 人工智能 > 正文

为什么FLD1加载NaN而不是?

如何解决《为什么FLD1加载NaN而不是?》经验,为你挑选了1个好方法。

我有一个单行C函数return value * pow(1.+rate, -delay);- 它将未来值折现为现值.反汇编的有趣部分是

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

在此之后,一切都变得地狱.事情变得严重过高或被低估,所以即使我的自由人工智能尝试中没有其他错误,它也会选择所有错误的策略.就像把整个军队送到北极一样.(叹气,如果我走的那么远.)

我必须错过一些明显的东西,或被某些东西蒙蔽,因为我无法相信它fld1应该永远失败.更不用说它只有在通过这个函数的少数几个之后才会失败.在较早的传递中,FPU正确地将1加载到ST(0)中.0x080555c6处的字节肯定是编码的fld1- 在正在运行的进程中使用x/... 进行检查.

是什么赋予了?



1> Stephen Cano..:

非常合适.你在这里有一个堆栈溢出.

具体来说,您(或可能是您的编译器)已经溢出x87堆栈.它只能保存8个值,并且在fld1发出时,它已经满(由标记词表示0000).因此,fld1堆栈溢出(表示为IE, SF, C1)会导致您看到的结果.

至于为什么会发生这种情况,你可能已经使用过MMX指令而没有使用EMMS之前使用x87指令,或者你的编译器有错误,或者你的程序集代码违反你的平台的ABI(或者你正在使用的库违反了ABI).

推荐阅读
手机用户2402851155
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有