我多年来一直在编写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中的DIVRDRAND指令,没有看到任何明显的东西.

我希望RDRAND会返回一个号码.我可以除以4.

我的问题是:当分子来自RDRAND时,为什么DIV会抛出异常?

谢谢, 马克

推荐答案

大多数时候,您的随机数将为= 1024,这意味着除以4的结果将无法容纳8位,并且您将获得#DE exection. 来自描述DIV的英特尔手册:

IF OperandSize = 8 (* Word/Byte Operation *)
    THEN
        temp ← AX / SRC;
        IF temp > FFH
            THEN #DE; (* Divide error *)
        ELSE
            AL ← temp;
            AH ← AX MOD SRC;
        FI;
FI;

C++相关问答推荐

-O and -wrap的行为

如何将一个enum类型类型转换为另一个类型?

从STdin读写超过4096个字节

如何启用ss(另一个调查套接字的实用程序)来查看Linux主机上加入的多播组IP地址?

sizeof结果是否依赖于字符串的声明?

在C中使用JMP_buf数组进行线程化(在xv6中测试)

如何调试LD_PRELOAD库中的构造函数?

Can函数指针指向C++中具有不同参数连续性的函数

如何在C中通过套接字自定义数据类型读取原始变量?

函数内的局部字符指针

在循环中复制与删除相同条件代码的性能

Fprintf正在写入多个 struct 成员,并且数据过剩

C++中PUTS函数的返回值

将非连续物理内存映射到用户空间

基于蝶数恰好有8个除数的事实的代码

OMP并行嵌套循环

如何在MSVC中使用intSafe.h函数?

C循环条件内的函数

添加/删除链表中的第一个元素

仅使用其内存地址取消引用 C 中的 struct