我多年来一直在编写x86 Assembly,但从未遇到过这个. 我希望有人能给我指明正确的方向,这样我就可以有一个"Doh!"时刻.
在伪代码中,当我写42 DIV 4
时,除了按预期工作. 当我写入RDRAND DIV 4
时,中央处理器会引发异常. 我正在进行无符号的16位算术,但我也用32位和64位复制了它.
我已经在英特尔酷睿处理器和AMD EPYT上复制了这一点..所以我认为这是故意的,而不是孤立的事情.
这是源代码. 我这样编制:clang -masm=intel -o div_bug div_bug.c
#include <stdio.h>
#include <stdint.h>
int main() {
printf( "div_bug\n" );
uint8_t rval;
// rdrand sets CF on success... I've tried this with and without this
// check and the program still throws an exception
// This works as expected
asm volatile (
// "try_again_1:"
"rdrand ax;" // If CF==0, then the rdrand failed... try again
// "jnc try_again_1;"
"mov ax, 42;" // This works... as expected
"mov cl, 4;"
"div cl;"
"mov %0, ah;"
:"=r" ( rval ) // Output
: // Input
:"ax", "cl", "cc" ); // Clobbers
printf( "The first return value is %u\n", rval );
// This throws a `Floating point exception (core dumped)`
asm volatile (
// "try_again_2:"
"rdrand ax;" // If CF==0, then the rdrand failed... try again
// "jnc try_again_2;"
// "mov ax, 42;" // <---- Remove this and it breaks
"mov cl, 4;"
"div cl;"
"mov %0, ah;"
:"=r" ( rval ) // Output
: // Input
:"ax", "cl", "cc" ); // Clobbers
printf( "The second return value is %u\n", rval );
}
我这里还有一个代码的存储:https://github.com/marknelsonengineer/div_bug.git
我研究了英特尔的STM中的DIV
和RDRAND
指令,没有看到任何明显的东西.
我希望RDRAND
会返回一个号码.我可以除以4.
我的问题是:当分子来自RDRAND
时,为什么DIV
会抛出异常?
谢谢, 马克