gpt4 book ai didi

assembly - 为什么 FLD1 改为加载 NaN?

转载 作者:行者123 更新时间:2023-12-04 22:52:20 28 4
gpt4 key购买 nike

我有一个单行 C 函数,它只是 return value * pow(1.+rate, -delay); - 将 future 值折现为现值。拆解的有趣部分是

0x080555b9:否定%eax
0x080555bb : 推 %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 : 调用 0x8051ce0
0x080555d8 : fmull 0xfffffff8(%ebp)

在单步执行此函数时,gdb 说(速率为 0.02,延迟为 2;您可以在堆栈中看到它们):

(gdb) si
0x080555c6 30 返回值 * pow(1.+rate, -delay);
(gdb) 信息 float
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) si
0x080555c8 30 返回值 * pow(1.+rate, -delay);
(gdb) 信息 float
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

在此之后,一切都将陷入 hell 。事情被严重高估或低估,所以即使在我的 freeciv AI 尝试中没有其他错误,它也会选择所有错误的策略。就像把整个军队送到北极一样。 (唉,要是我能走那么远就好了。)

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

是什么赋予了?

最佳答案

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

具体来说,您(或可能是您的编译器)已溢出 x87 堆栈。它只能容纳 8 个值,而当时的 fld1发出,已经满了(用 0000 的标签字表示)。因此,fld1溢出堆栈(由 IE, SF, C1 指示)导致您看到的结果。

至于为什么会发生这种情况,您可能使用了 MMX 指令而不使用 EMMS在使用 x87 指令之前,或者您的编译器有错误,或者您在某处有违反平台 ABI 的汇编代码(或者您正在使用的库违反了 ABI)。

关于assembly - 为什么 FLD1 改为加载 NaN?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2830693/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com