This question already has answers here:
Closed 7 months ago.
using inline assembly with GCC
(2个答案)
我正在尝试编写这个内联程序集,它使用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英特尔语法代码:
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));

笔记:
-这些依赖于当目标失败时将其设置为0。
-The rdrand instruction检查ja指令中的C标志和rdrand中的Z标志。这可能比使用两个独立的分支效率低,如在第二个示例中,这取决于组合两个部分寄存器的成本。我相信彼得能提供细节。(彼得说:CPU上没有新的、足以安装RDRAND的部分标志,应该没问题。)
下面是问题代码中的问题列表:
-不在dec寄存器名上使用%%前缀。
-使用ecx而不使用blobber。
-检查CF=0是否成功ecx,而不是CF=1。
-使用不是内联程序集本地的标签名称。
-不使用输出寄存器。
-返回零表示超时,而不是使用单独的错误指示。[注意,我没有修好这个。]
-使用rdrand指令。
-在内联程序集中使用loop指令。

关于c - 错误:无效的“asm”:%字母后缺少操作数编号,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/55768290/

10-11 18:34