我正在尝试编写此内联程序集,该内联程序集使用rdrand
指令返回一个随机数。该数字存储在eax
寄存器中,然后移动到rng_num
变量中。但是我得到标题中的错误。
uint32_t rng_num;
asm volatile("movl $100, %ecx\n\t"
"__trng_cpu_ret:\n\t"
"rdrand %%eax\n\t"
"jnc .__trng_cpu_end\n\t"
"loop __trng_cpu_ret\n\t"
".__trng_cpu_fail:\n\t"
"movl $0, %%eax\n\t"
".__trng_cpu_end:\n\t"
"ret\n\t"
: "=r" (rng_num)
:
:"%eax");
这是原始的x86 Intel语法代码:
mov ecx, 100 ;number of retries
retry:
rdrand eax
jnc .done ;carry flag is clear on success
loop retry
.fail:
;no random number available
.done:
;random number is is EAX
答案 0 :(得分:2)
如fuz和Peter在评论中提到的,正确的答案是不要使用内联汇编。
但是这里有几种以内联汇编形式编写代码的方法。
uint32_t rng_num;
int iterations = 100;
asm volatile("1: rdrand %0\n\t"
"dec %1\n\t"
"ja 1b\n\t" // jump if CF=0 (from rdrand) and ZF=0 (from dec)
: "=r" (rng_num), "+r"(iterations));
// alternative that doesn't need partial-flag merging
asm volatile("1: rdrand %0\n\t"
"jc 2f\n\t"
"dec %1\n\t"
"jnz 1b\n\t"
"2:\n\t"
: "=r" (rng_num), "+r"(iterations));
注意:
-它们依靠rdrand
在失败时将目标设置为0。
-The ja
instruction既检查来自rdrand
指令的C标志,又检查来自dec
的Z标志。与第二个示例一样,这可能不如使用两个单独的分支有效,具体取决于合并两个部分寄存器的成本。我确定彼得可以提供详细信息。 (彼得说:在新的足以拥有RDRAND的CPU上,没有部分标志停滞应该没事。)
以下是问题代码中的问题列表:
-不要在%%
寄存器名称上使用ecx
前缀。
-使用ecx
,不加掩饰。
-检查CF = 0是否是rdrand
而不是CF = 1的结果。
-使用不在嵌入式程序集中的标签名称。
-不使用输出寄存器。
-返回零以指示超时,而不使用单独的错误指示。 [注意,我没有解决这个问题。]
-使用loop
指令。
-在内联汇编中使用ret
指令。