我想学习一些内联汇编编程,但我的第一个代码片段不起作用。我有一个字符串,我想把字符串的值分配给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然而,正如下面所评论的,这可能并不完全准确。