bre*_*ett 5 c assembly gcc inline-assembly
例:
int main(void)
{
int x = 10, y;
asm ("movl %1, %%eax;"
"movl %%eax, %0;"
:"=r"(y) /* y is output operand */
:"r"(x) /* x is input operand */
:"%eax"); /* %eax is clobbered register */
}
Run Code Online (Sandbox Code Playgroud)
r(y)?%%以前用过eax?一般单%用吗?好的,这是gcc内联汇编程序,它非常强大但很难理解.
首先,%char是一个特殊的char.它允许您定义寄存器和数字占位符(稍后将详细说明).不幸的是,%也被用作寄存器名称的一部分(例如%EAX),因此在gcc内联汇编程序中,如果要命名寄存器,则必须使用2%的字符.
%0,%1和%2(ect ..)是占位符输入和输出操作数.这些在列表中定义,后跟汇编程序字符串.在您的示例中,%0成为y的占位符,%1成为x的占位符.在执行asm-code之前,编译器将确保变量将在寄存器中用于输入操作数,并确保输出操作数将写入输出操作数列表中指定的变量.
现在你应该知道r(y)是什么:它是一个输入操作数,为变量y保留一个寄存器,并将它分配给占位符%1(因为它是内联汇编程序字符串后面列出的第二个操作数).还有很多其他占位符类型.m允许你指定一个内存位置,如果我没有弄错,我可以用于数字常量.你会发现它们都在gcc文档中列出.
然后是clobber列表.这个清单很重要!它列出了在汇编代码中修改的所有寄存器,标志,内存位置等(例如示例中的EAX).如果你弄错了,优化器将不知道修改了什么,很可能你最终得到的代码不起作用.
你的榜样几乎毫无意义.它只是将值X加载到寄存器中并将该寄存器分配给EAX.之后EAX被存储到另一个寄存器中,然后该寄存器将成为您的y变量.所以它只是一个简单的任务:
y = x;
最后一件事:如果您之前使用过Intel风格的汇编程序:您必须向后阅读这些参数.对于所有指令,源操作数是指令本身之后的操作数,目标操作数是逗号右侧的操作数.与英特尔语法相比,这恰恰相反.