令牌内联程序集错误之前的预期")"



我想学习一些内联汇编编程,但我的第一个代码片段不起作用。我有一个字符串,我想把字符串的值分配给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"是输入部分,而不是clobber。

但作为输入,它缺少"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
);

请注意,并没有告诉编译器您读取或写入指向的内存,因此只有这样的东西才是安全的,它复制地址,但不希望读取或写入指针指向的数据。

也相关:

  • 如何指示可以使用内联ASM参数指向的内存*?

  • 我可以修改gcc内联汇编中的输入操作数吗

  • 如何在扩展GCC内联汇编中将输入操作数(C寄存器变量(标记为阻塞?

通常,在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__,在我的情况下,这很有帮助。

这种修改的灵感来自于";当编写可以使用-ansi和各种-std选项编译的代码时,请使用__asm_而不是asm"从…起https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html然而,正如下面所评论的,这可能并不完全准确。

最新更新