我在 Mac OSX 上加载 Vorbis Ogg 文件时遇到了神秘的错误。第一个文件正确加载,第二个文件在一些代码中崩溃,表明文件已损坏,即使我两次加载相同的文件也会发生同样的情况。
在 Vorbis 内部进行长时间的深度调试后,我发现这个错误是由系统函数“pow”(双重幂)返回一个完全有效的输入的 (nan) 引起的,并且这只发生在第二次调用 (ov_read ),在第一次调用时,传递给“pow”的完全相同的值返回有效结果。
8 小时后,阅读大量 Intel x87 文档后,我发现了问题。长话短说,在 vorbis "vorbis_ftoi" 内部有一个函数使用这个汇编代码:
__asm__("fistl %0": "=m"(i) : "t"(f));
哪个应该在英特尔 FPU 堆栈上推送和弹出。但是在 LLVM 上,它会生成以下代码:
fld QWORD PTR [ebp-0x20]
fist DWORD PTR [ebp-0x14]
它压入堆栈但从不弹出导致 FPU 堆栈溢出。这显然是 LLVM 中的一个错误
GCC 生成的正确代码如下所示:
fld QWORD PTR [ebp-0x20]
fist DWORD PTR [ebp-0xc]
fstp st(0) // pops off the stack
我浪费了一天半的时间和我的布莱恩的一些字节学习一些垃圾(x87指令集和寄存器),所以我想分享它。
奥代