Как установить префикс REX при использовании RDRAND под GCC?
Я пытаюсь использовать Intel RDRAND
инструкция. В соответствии с Руководством разработчика программного обеспечения Intel® 64 и IA-32, том 2 (стр. 4-298), RDRAND
по умолчанию выдает 32-битные случайные значения, даже на 64-битных машинах:
В 64-битном режиме размер операции по умолчанию для инструкции составляет 32 бита. Использование префикса REX в форме REX.B разрешает доступ к дополнительным регистрам (R8-R15).
Я пытаюсь заставить 64-битное поколение с помощью rdrandq
, но выдает ошибку (/tmp/ccLxwW6S.s
связано с использованием встроенной сборки):
$ g++ -Wall rdrand.cxx -o rdrand.exe
/tmp/ccLxwW6S.s: Assembler messages:
/tmp/ccLxwW6S.s:5141: Error: invalid instruction suffix for `rdrand'
Как заставить 64-битную версию инструкции RDRAND под GCC? Как установить префикс REX при использовании RDRAND в GCC?
Заранее спасибо.
В приведенном ниже коде output
это byte[]
с длиной size
, safety
является отказоустойчивым. Два разных размера слова относятся к платформам X86, X32 и X64.
#if BOOL_X86
word32 val;
#else // X32 and X64
word64 val;
#endif
while (size && safety)
{
char rc;
__asm__ volatile(
#if BOOL_X86
"rdrandl %0 ; setc %1"
#else
"rdrandq %0 ; setc %1"
#endif
: "=rm" (val), "=qm" (rc)
:
: "cc"
);
if (rc)
{
size_t count = (size < sizeof(val) ? size : sizeof(val));
memcpy(output, &val, count);
size =- count;
}
else
{
safety--;
}
}
Если я удалю явный размер операнда из RDRAND (т. Е. Используйте rdrand
скорее, чем rdrandl
или же rdrandq
), то я получаю сообщение об ошибке при попытке использовать word64
:
/tmp/ccbeXOvM.s: Assembler messages:
/tmp/ccbeXOvM.s:5167: Error: operand size mismatch for `rdrand'
0 ответов
Вам не нужен суффикс размера операнда, просто используйте его с регистром соответствующего размера (который gcc выберет в зависимости от типа используемой вами переменной C).
gcc main.c -o main
(или же)
gcc -m32 main.c -o main
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char **argv) {
unsigned int rnd32;
#ifdef __x86_64
long long unsigned int rnd64;
/*
The next instruction generates this asm:
48 0f c7 f0 rdrand %rax
*/
asm volatile("rdrand %0\n":"=r"(rnd64):);
printf("\nRND64=0x%llx\n",rnd64);
#endif
/*
The next instruction generates this asm:
0f c7 f1 rdrand %ecx
*/
asm volatile("rdrand %0\n":"=r"(rnd32):);
printf("RND32=0x%x\n",rnd32);
printf("\nAssembler code:\n\n");
system("objdump -d main|grep rdrand");
return 0;
}
Выход (64 бит):
RND64=0x2f9f0e7d7f209575
RND32=0xbec8ff00
Assembler code:
40054f: 48 0f c7 f0 rdrand %rax
400557: 0f c7 f1 rdrand %ecx
Выход (32 бита):
RND32=0xa3d33766
Assembler code:
59a: 0f c7 f0 rdrand %eax