我用下面的代码遇到了一个有趣的情况:
static void DivideByZero() {
// volatile to prevent compiler optimizations.
volatile float zero = 0.0f;
volatile float result __attribute__((unused)) = 123.0f / zero;
}
DivideByZero();
int raised = fetestexcept(FE_DIVBYZERO | FE_OVERFLOW);
ASSERT_TRUE((raised & FE_DIVBYZERO) != 0);
当我运行支持 KVM
的 qemu 设备时,我得到以下结果:
FE_DIVBYZERO !=0; //and it's ok
但是当我在没有 KVM
支持的情况下运行相同的源代码时:
FE_DIVBYZERO ==0; //and it's not ok
据我了解,这种情况确实发生了,因为在 mxcsr
中未设置寄存器位(除以零)。但是我不明白为什么没有设置这个位。
有任何想法吗?
更新:
同样的情况也发生在基于 qemu 的 android
模拟器上。
emulator -avd test -qemu
返回:FE_DIVBYZERO !=0;
emulator -avd test -qemu -disable-kvm
返回:FE_DIVBYZERO ==0;
最佳答案
MXCSR
寄存器在
Intel® 64 and IA-32 Architectures Software Developer’s Manual
在现代 x86 处理器上,编译器将浮点运算映射为 scalar
SIMD,使用与vector (SSE)
指令相同的资源。
MXCSR
寄存器控制着scalar
和vector (SSE)
浮点指令的操作。我在下面包含了描述 MXCSR 的相关部分。 MXCSR[9]
是除以零掩码,如果清除 (0) 那么当检测到除以零时 CPU 将引发异常。当您在虚拟机中运行时,异常被“虚拟化”,它们由“管理程序”处理,KVM在你的情况下。然后管理程序决定是否将异常反射(reflect)回客户虚拟机。我的理论是除以零掩码被清除,引发异常,KVM 和/或 QEMU 正在清除指示发生除以零异常的标志 MXCSR[2]
并恢复你的虚拟机。因此,这可能是 KVM/QEMU 中的错误。
你可以发出 fegetexcept()在 DivideByZero()
之前查明除以零异常是否被屏蔽 (1) 或不屏蔽 (0)。如果它没有被屏蔽,那么你可以使用 fedisableexcept()掩盖它。
关于android - Qemu,除以零,mxcsr 寄存器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15134189/