Move上的浮点运算无效?

时间:2012-07-06 14:25:38

标签: delphi assembly

我遇到了一个我以前从未见过的奇怪问题,在Delphi 2010中有时使用例程CopyMemory(内部调用Move)我得到一个Invalid Float Point Operation异常,当使用Move时会发生这种情况? ?

我在汇编程序中有一个调试信息,我检查了Move的源代码,问题发生在FILD指令中,我发现FILD将一个整数值从内存转换为寄存器中的浮点,它可能会触发无效操作,但为什么会这样呢?我现在坚持了2天

Assembler Information:
; System.Move (Line=0 - Offset=1)
;
00404E0C cmp eax, edx
00404E0E jz System.Move
00404E10 cmp ecx, +$20
00404E13 jnbe System.Move
00404E15 sub ecx, +$08
00404E18 jnle System.Move
00404E1A jmp dword ptr [System.Move+ecx*4]
00404E21 fild qword ptr [ecx+eax]
00404E24 fild qword ptr [eax] ; <-- EXCEPTION
00404E26 cmp ecx, +$08
00404E29 jle System.Move
00404E2B fild qword ptr [eax+$08]
00404E2E cmp ecx, +$10
00404E31 jle System.Move
00404E33 fild qword ptr [eax+$10]
00404E36 fistp qword ptr [edx+$10]
00404E39 fistp qword ptr [edx+$08]
00404E3C fistp qword ptr [edx]
00404E3E fistp qword ptr [ecx+edx]

Registers:
EAX: 0E3A4694 EDI: 0000000D
EBX: 00001B5C ESI: 0ECF7928
ECX: 00000005 ESP: 0612FC1C
EDX: 0E3A2B38 EIP: 00404E24

什么可能导致错误?

2 个答案:

答案 0 :(得分:6)

我以前见过这个问题。问题是在进入Move方法之前,x87寄存器的堆栈包含一些无效的浮点值而不是空的。这是由于之前发生的异常并且像这样离开了x87堆栈。

Move命令使用x87寄存器,因为它们允许快速移动数据而不依赖于SSE指令,但它假定堆栈为空。

寻找解决方案:

  • 在Move命令的开头设置断点,并使用FPU调试窗口验证FPU堆栈是否确实已被删除。
  • 从这里开始:回溯你的应用程序中使用相同窗口导致这个被破坏的FPU堆栈的原因。这是导致问题的原因。

答案 1 :(得分:1)

似乎与之前的问题类似: Memory corruption in System.Move due to changed 8087CW mode (png + stretchblt)

我的修复是禁用FastMove.pas中的SSE / MMX内容,因此它不再(错误)使用FPU(并且不容易受到FPU损坏)