由于不幸的原因,我不能进入,我不得不支持一个古老的汇编程序,它没有我需要的助记符的映射。
我知道硬件支持它,但是我似乎找不到任何关于如何使用操作码而不是助记符的在线文档。
有没有人可以参考一下在内联AT&T语法中如何在GCC上做到这一点。
发布于 2018-09-06 01:35:32
幸运的是,rdrand
只有一个参数,那就是寄存器。因此,如果您想让编译器自由选择,您只需要涵盖几种情况。注意,它仍然很难看:)
inline int rdrand()
{
int result;
__asm__ __volatile__ (
".byte 0x0f, 0xc7\n\t"
".ifc %0, %%eax\n\t"
".byte 0xf0\n\t"
".else\n\t"
".ifc %0, %%ebx\n\t"
".byte 0xf3\n\t"
".else\n\t"
".ifc %0, %%ecx\n\t"
".byte 0xf1\n\t"
".else\n\t"
".ifc %0, %%edx\n\t"
".byte 0xf2\n\t"
".else\n\t"
".ifc %0, %%esi\n\t"
".byte 0xf6\n\t"
".else\n\t"
".ifc %0, %%edi\n\t"
".byte 0xf7\n\t"
".else\n\t"
".ifc %0, %%ebp\n\t"
".byte 0xf5\n\t"
".else\n\t"
".error \"uknown register\"\n\t"
".endif\n\t"
".endif\n\t"
".endif\n\t"
".endif\n\t"
".endif\n\t"
".endif\n\t"
".endif\n\t"
: "=R" (result) : : "cc");
// "=R" excludes r8d..r15d in 64-bit mode
return result;
}
对于64位操作数大小,您将需要一个REX.W (0x48)前缀,但是the "=R"
constraint而不是"=r"
将避免需要在REX前缀中设置任何其他位。
请注意,rdrand
还使用进位标志,该标志的处理留给读者作为练习。gcc6可以使用标志输出操作数,这比setcc
更有效。
发布于 2018-09-06 02:02:47
试试这个:
long result;
char success = 0; /* make sure we don't get surprised by setc only writing 8 bits */
/* "rdrand %%rax ; setc %b1" */
asm volatile (".byte 0x48, 0x0f, 0xc7, 0xf0; setc %b1" : "=a"(result), "=qm"(success) :: "cc");
a
约束强制编译器对result
使用rax
寄存器。这就是它得到的最普遍的东西,而不是令人讨厌的。我建议您添加一个配置测试,以检查汇编程序是否理解rdrand
,并使用以下代码:
long result;
char success = 0;
#ifdef HAVE_RDRAND
asm volatile ("rdrand %0; setc %b1" : "=r"(result), "=qm"(success) :: "cc");
#else
asm volatile (".byte 0x48, 0x0f, 0xc7, 0xf0; setc %b1" : "=a"(result), "=qm"(success) :: "cc");
#endif
虽然如果汇编器不理解rax
,强制编译器使用rdrand
寄存器可能会带来很小的性能损失,但允许使用任何寄存器所需的复杂杂乱操作远远超过了这一点。
https://stackoverflow.com/questions/52190220
复制相似问题