我需要从处理器(Intel Core i3)的随机生成器中获取随机数。我不想使用任何库,而是希望使用内嵌汇编在C++中实现,但我不知道应该使用哪些寄存器和指令。
RDRAND %rax
成功时,进位标志将被设置。有关更多详细信息,请参阅英特尔的Bull Mountain软件实现指南。(“Bull Mountain”是英特尔硬件RNG的代号。)
...但我不知道应该使用哪些寄存器和指令。
下面是我在Linux机器上使用GCC的内联汇编。我相信我从英特尔手册中抄袭了很大一部分。它可能是由David Johnston编写的,他对rdand问题提供了令人惊叹的技术答案。他也是英特尔硬件设计的人。
int RDRAND_bytes(byte* buff, size_t bsize)
{
if (!HasRDRAND())
return -1;
size_t idx = 0, rem = bsize;
size_t safety = bsize / sizeof(unsigned int) + 4;
unsigned int val;
while (rem > 0 && safety > 0)
{
char rc;
__asm__ volatile(
"rdrand %0 ; setc %1"
: "=r" (val), "=qm" (rc)
);
// 1 = success, 0 = underflow
if (rc)
{
size_t cnt = (rem < sizeof(val) ? rem : sizeof(val));
memcpy(buff + idx, &val, cnt);
rem -= cnt;
idx += cnt;
}
else
{
safety--;
}
}
// Wipe temp on exit
*((volatile unsigned int*)&val) = 0;
// 0 = success; non-0 = failure (possibly partial failure).
return (int)(bsize - rem);
}
以下代码用于检测 HasRDRAND
。它可以检测 AMD 和 Intel CPU(我认为这是提供 RDRAND 的所有 CPU)。
struct CPUIDinfo {
unsigned int EAX;
unsigned int EBX;
unsigned int ECX;
unsigned int EDX;
};
// Be careful below. EBX/RBX needs to be preserved depending on the memory model and use of PIC.
void cpuid_info(CPUIDinfo *info, const unsigned int func, const unsigned int subfunc) {
__asm__ __volatile__ (
"cpuid"
: "=a"(info->EAX), "=b"(info->EBX), "=c"(info->ECX), "=d"(info->EDX)
: "a"(func), "c"(subfunc)
);
}
int HasAmdCpu() {
CPUIDinfo info;
cpuid_info(&info, 0, 0);
if (memcmp((char *) (&info.EBX), "htuA", 4) == 0
&& memcmp((char *) (&info.EDX), "itne", 4) == 0
&& memcmp((char *) (&info.ECX), "DMAc", 4) == 0) {
return 1;
}
int HasIntelCpu() {
CPUIDinfo info;
cpuid_info(&info, 0, 0);
if (memcmp((char *) (&info.EBX), "Genu", 4) == 0
&& memcmp((char *) (&info.EDX), "ineI", 4) == 0
&& memcmp((char *) (&info.ECX), "ntel", 4) == 0) {
return 1;
}
return 0;
}
int HasRDRAND() {
if (!HasAmdCpu() || !HasIntelCpu())
return 0;
CPUIDinfo info;
cpuid_info(&info, 1, 0);
static const unsigned int RDRAND_FLAG = (1 << 30);
if ((info.ECX & RDRAND_FLAG) == RDRAND_FLAG)
return 1;
return 0;
}
同时请参考如何使用RDRAND内嵌函数?。虽然它不能直接回答你的问题,但它可能是一个替代方案,并且可以帮助其他人。
int success = _rdrand64_step(&output)
或while( !_rdrand64_step(&output) ){}
。 (定义在<immintrin.h>
中。RDRAND和RDSEED内置函数GCC和Intel C ++) - Peter Cordes