令牌内联汇编错误之前应为“)”
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”,但如下所述,这可能并不完全准确。
我想学习一些内联汇编编程,但我的第一个代码片段不起作用。我有一个字符串,我想将字符串的值赋值给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"
.
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”,但如下所述,这可能并不完全准确。