Как установить префикс 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;
}

https://repl.it/@zibri/rdrand

Выход (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
Другие вопросы по тегам