在GCC下使用RDRAND时如何设置REX前缀?

在GCC下使用RDRAND时如何设置REX前缀?,c,gcc,x86,inline-assembly,rdrand,C,Gcc,X86,Inline Assembly,Rdrand,我正在尝试使用英特尔的RDRAND指令。根据(第4-298页),RDRAND默认生成32位随机值,即使在64位机器上: 在64位模式下,指令的默认操作大小为32位。使用REX.B形式的REX前缀可以访问其他寄存器(R8-R15) 我试图使用rdrandq强制生成64位,但它产生了一个错误(/tmp/cclxw6s.s是由于使用了内联汇编): $g++-Wall rdrand.cxx-o rdrand.exe /tmp/cclxw6s.s:汇编程序消息: /tmp/ccLxwW6S.s:5141:

我正在尝试使用英特尔的
RDRAND
指令。根据(第4-298页),
RDRAND
默认生成32位随机值,即使在64位机器上:

在64位模式下,指令的默认操作大小为32位。使用REX.B形式的REX前缀可以访问其他寄存器(R8-R15)

我试图使用
rdrandq
强制生成64位,但它产生了一个错误(
/tmp/cclxw6s.s
是由于使用了内联汇编):

$g++-Wall rdrand.cxx-o rdrand.exe
/tmp/cclxw6s.s:汇编程序消息:
/tmp/ccLxwW6S.s:5141:错误:“rdrand”的指令后缀无效
如何在GCC下强制使用64位版本的RDRAND指令?在GCC下使用RDRAND时,如何设置REX前缀

提前谢谢


在下面的代码中,
output
是长度为
size
字节[]
<代码>安全是一种故障保护。这两种不同的字号处理不同的问题

\if BOOL\u X86
32字val;
#else//X32和X64
字64 val;
#恩迪夫
while(尺寸和安全性)
{
char-rc;
__反复无常(
#if BOOL_X86
“rdrandl%0;setc%1”
#否则
“rdrandq%0;setc%1”
#恩迪夫
:“=rm”(val),“=qm”(rc)
:
:“抄送”
);
if(rc)
{
大小计数=(大小
如果我从RDRAND中删除显式操作数大小(即,使用
RDRAND
而不是
rdrandl
rdrandq
),则在尝试使用
word64
时会出错:

/tmp/ccbeXOvM.s:汇编程序消息:
/tmp/ccbeXOvM.s:5167:错误:“rdrand”的操作数大小不匹配

您不需要操作数大小后缀,只需将其与适当大小的寄存器一起使用(gcc将根据您使用的C变量类型选择该寄存器)


(或)


#包括
#包括
int main(int argc,字符**argv){
无符号整数rnd32;
#ifdef\uuux86\u64
长无符号整数rnd64;
/*
下一条指令生成此asm:
48 0f c7 f0 Rrand%rax
*/
asm volatile(“rdrand%0\n”:“=r”(rnd64):);
printf(“\nRND64=0x%llx\n”,rnd64);
#恩迪夫
/*
下一条指令生成此asm:
0f c7 f1随机数%ecx
*/
asm volatile(“rdrand%0\n”:“=r”(rnd32):);
printf(“RND32=0x%x\n”,RND32);
printf(“\n装配程序代码:\n\n”);
系统(“objdump-d main | grep rdrand”);
返回0;
}

输出(64位):

输出(32位):


您不需要操作数大小后缀,只需将其与适当大小的寄存器一起使用(gcc将根据您使用的C变量类型选择该寄存器)


(或)


#包括
#包括
int main(int argc,字符**argv){
无符号整数rnd32;
#ifdef\uuux86\u64
长无符号整数rnd64;
/*
下一条指令生成此asm:
48 0f c7 f0 Rrand%rax
*/
asm volatile(“rdrand%0\n”:“=r”(rnd64):);
printf(“\nRND64=0x%llx\n”,rnd64);
#恩迪夫
/*
下一条指令生成此asm:
0f c7 f1随机数%ecx
*/
asm volatile(“rdrand%0\n”:“=r”(rnd32):);
printf(“RND32=0x%x\n”,RND32);
printf(“\n装配程序代码:\n\n”);
系统(“objdump-d main | grep rdrand”);
返回0;
}

输出(64位):

输出(32位):


您是否出于任何原因反对使用
\u rdrand64\u步骤
内部程序集?@Michael-我更喜欢内联程序集。RDRAND很容易测试。否则,我必须添加额外的测试以包括标头,并且担心GCC版本不支持RDRAND intrinsic,即使底层处理器和汇编程序支持它。显然,
RDRAND
的操作数大小是隐式的,即使在AT&t语法中也是如此
rdrand%e[rr]
在使用低寄存器时没有REX前缀,
rdrand%r[rr]
有。您可以随时写出相应的字节序列:
48 0f c7 f1
。正如前面所指出的,rdrand不允许接受内存输出。此外,还有一个新的for gcc,它可能能够为您保存
setc
。如果您的编译器版本足够新(
#ifdef_uugcc_ASM_uflag_uu
),您可以执行类似于
do{ASM(“rdrand%1”):“=@ccc”(x),“=r”(l))}的操作,而(!x)
给您提供了
.L2:rdrand%eax jnc.L2
。您是否出于任何原因反对使用
\rdrand64\u步骤
固有程序?@Michael-我更喜欢内联程序集。RDRAND很容易测试。否则,我必须添加额外的测试以包括标头,并且担心GCC版本不支持RDRAND intrinsic,即使底层处理器和汇编程序支持它。显然,
RDRAND
的操作数大小是隐式的,即使在AT&t语法中也是如此
rdrand%e[rr]
在使用低寄存器时没有REX前缀,
rdrand%r[rr]
有。您可以随时写出相应的字节序列:
48 0f c7 f1
。正如前面所指出的,rdrand不允许接受内存输出。此外,还有一个新的for gcc,它可能能够为您保存
setc
。如果您的编译器版本足够新(
#ifdef_uugcc_ASM_uflag_uu
),您可以执行类似于
do{ASM(“rdrand%1”):“=@ccc”(x),“=r”(l))}的操作,而(!x)
为您提供了
.L2:rdrand%eax jnc.L2
。您的回滚删除了
“=rm”(val)
是一个错误的事实,因为rdrand仅适用于寄存器输出。这是操作数能够暗示操作数大小的关键。我认为我其余的编辑也是在改进(否则我就不会做这个了)
gcc main.c -o main
gcc -m32 main.c -o main
RND64=0x2f9f0e7d7f209575
RND32=0xbec8ff00

Assembler code:

   40054f:   48 0f c7 f0             rdrand %rax   
   400557:   0f c7 f1                rdrand %ecx
RND32=0xa3d33766

Assembler code:

  59a:  0f c7 f0                rdrand %eax