Если вы посмотрите на <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
%edx
может быть установлено в 0, если CF повышается. И это значение возвращается из функции.
Поэтому я считаю, что встроенная функция уже правильно обрабатывает флаг переноса, и пользователь должен просто проверить вывод _rdrandXX_step(ull*)
, как описано в руководстве.
person
Severin Pappadeux
schedule
04.07.2015