error: invalid 'asm': operand number missing after %-letter

error: invalid 'asm': operand number missing after %-letter

我正在尝试编写这个内联汇编,其中 returns 使用 rdrand 指令的随机数。该数字存储在 eax 寄存器中,然后移至 rng_num 变量。但是我得到了标题中的错误。

    uint32_t rng_num;
    asm volatile("movl 0, %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 [=10=], %%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

正如 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 标志。这可能比使用两个单独的分支效率低,如第二个示例中所示,具体取决于组合两个部分寄存器的成本。我相信 Peter 可以提供详细信息。 (Peter 说:在足够新的 CPU 上没有部分标志停顿以具有 RDRAND,应该没问题。)

问题中代码问题列表如下:
- 不在 ecx 注册名称上使用 %% 前缀。
- 使用 ecx 没有破坏。
- 检查 CF=0 是否成功 rdrand 而不是 CF=1.
- 使用非内联程序集本地的标签名称。
- 不使用输出寄存器。
- Returns 零表示超时,而不是使用单独的错误指示。 [注意,我没有修复这个。]
- 使用 loop 指令。
- 在内联汇编中使用 ret 指令。