我在看 H.J. Lu 的PATCH:更新 x86 rdrand intrinsics。我不知道我是否应该使用
_rdrand_u64
,_rdrand64_step
,或者是否还有其他功能。似乎没有为他们编写的测试用例。
似乎还缺少手册页(来自 Ubuntu 14、GCC 4.8.4):
$ man -k rdrand
rdrand: nothing appropriate.
如何使用
RDRAND
内在函数生成一个 32 字节的块?
一个相关的问题是 RDRAND 和 RDSEED 内在函数 GCC 和英特尔 C++。但它没有告诉我如何使用它们,或者如何生成一个块。
如果你看
<immintrin.h>
(我的在`/usr/lib/gcc/x86_64-linux-gnu/4.9/include/',Ubuntu 15.04 64bit),有兼容(与MSVC,Intel CC)定义的函数将数据传回 GCC 内置函数
extern __inline int __attribute__((__gnu_inline__, __always_inline__, __artificial__))
_rdrand64_step (unsigned long long *__P)
{
return __builtin_ia32_rdrand64_step (__P);
}
用于 64 位参数,另外两个用于 16 位和 32 位参数
_rdrand16_step (unsigned short *__P)
_rdrand32_step (unsigned int *__P)
你应该使用它们,这样你的代码才能与 MSVC、Intel CC 和其他编译器兼容。
_rdrand64_step
将填充由指针传递的 64 位参数,随机位并返回错误代码。 32 位和 16 位版本同上
更新
“这些内在函数生成 16/32/64 位宽随机整数的随机数。生成的随机值被写入给定的内存位置并返回成功状态:如果硬件返回有效的随机值,则为“1”,并且“ 0'否则。”
https://software.intel.com/en-us/node/523864
更新
根据@vy32 的要求,这对我有用。好吧,我的系统自原始答案以来已更新,所以现在是 Ubuntu 20.04.1、x64、GCC v9.3、编译标志
gcc -m64 -mrdrnd -O3 a.c
代码
#include <stdio.h>
#include <immintrin.h>
int main() {
unsigned long long result = 0ULL;
int rc = _rdrand64_step (&result);
printf("%i %llu", rc, result);
return (rc != 1);
}
关于 CF 标志和“忽略这是一个常见的实现错误,它不会在测试中出现,但会在负载下运行 DRNG 时出现”,我相信这是内置的。如果您注释掉 printf 并使用 -S 标志编译为汇编程序,代码将如下所示,
xorl %eax, %eax
rdrand %rax
movl $1, %edx
...
cmovc %edx, %eax
这意味着
%eax
归零,%edx
设置为 1,然后通过 cmovc
如果 CF 升高,%edx
可能设置为 0。这个值是从函数返回的。
所以我相信内置已经以正确的方式处理进位标志,用户应该按照手册中的描述检查
_rdrandXX_step(ull*)
的输出。
注意文件
immintrin.h
是定义处理器内在函数的各种头文件的集合。包含 RDRAND 内在函数的 current 标头是您不应该包含的
x86gprintrin.h
。