令牌内联汇编错误之前应为“)”

Expected ')' before token inline assembly error

我想学习一些内联汇编编程,但我的第一个代码片段不起作用。我有一个字符串,我想将字符串的值赋值给rsi寄存器。

这是我的代码:

    string s = "Hello world";
    const char *ystr = s.c_str();
    asm("mov %1,%%rsi"
    :"S"(ystr)
    :"%rsi" //clobbered register
);

    return 0;

它给了我错误:令牌前应为“)”。感谢任何帮助。

您遗漏了 : 来分隔空的输出部分。所以 "S"(ystr) 是输出部分中的输入操作数,而 "%rsi" 在输入部分中,而不是 clobbers。

但作为输入,它缺少 "constraint"(var_name) 语法的 (var_name) 部分。所以这是一个语法错误,也是一个语义错误。这是错误 <source>:9:5: error: expected '(' before ')' token 的直接来源。 https://godbolt.org/z/97aTdjE8K


正如 Nate 指出的那样,您还有其他几个错误,例如试图强制输入使用 "S".

选择 RSI
   char *output;   // could be a dummy var if you don't actually need it.
   asm("mov %1, %0"
     : "=r" (output)     /// compiler picks a reg for you to write to.
    :"S"(ystr)           // force RSI input
    :   // no clobbers
   );

请注意,这 不会 告诉编译器您读取或写入指向的内存,因此它只对像这样的东西是安全的,它会复制地址但不会'期望读取或写入指向的数据。

还相关:

一般来说,当在 x86 上使用 gcc 内联 asm 时,您希望避免使用 mov 指令,并希望避免在 asm 代码中显式寄存器——只需使用寄存器约束来获取内容适当的寄存器。因此,对于您的示例,将字符串指针获取到 rsi 寄存器中,您只需要:

asm volatile("; ystr wil be in %rsi here"
            :  // no output contraints
            : "S"(ystr)  // input constraint
            :  // no clobber needed
            );

请注意,这里没有实际的 asm 代码输出——只是一条注释。输入约束足以使操作数在其出现之前进入所需的寄存器。是的,rsi 之后很可能会用于其他用途,但这是预期的——寄存器约束仅涵盖 asm 文本的输入和输出。

在我的案例中,C++ 代码是使用 -std=c++17 编译的,编译器还报告了 expected ')' before ':' 令牌

我将关键字 asm 更改为 __asm__,对我来说,这很有帮助。

此修改的灵感来自 https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html 中的“编写可以使用 -ansi 和各种 -std 选项编译的代码时,请使用 __asm__ 而不是 asm”,但如下所述,这可能并不完全准确。