您可以在扩展程序集中使用局部变量,但您需要将它们告知扩展程序集构造。考虑:
#include <stdio.h>
int main (void)
{
int data1 = 10;
int data2 = 20;
int result;
__asm__(
" movl %[mydata1], %[myresult]\n"
" imull %[mydata2], %[myresult]\n"
: [myresult] "=&r" (result)
: [mydata1] "r" (data1), [mydata2] "r" (data2));
printf("The result is %d\n",result);
return 0;
}
In this [myresult] "=&r" (result)
说选择一个寄存器(r
)将用作输出(=
) 左值的值result
,并且该寄存器将在程序集中被称为%[myresult]
并且必须与输入寄存器不同(&
)。 (您可以在两个地方使用相同的文本,result
代替myresult
;我只是为了说明而做了不同的处理。)
相似地[mydata1] "r" (data1)
表示输入表达式的值data1
到寄存器中,它将在程序集中被称为%[mydata1]
.
我修改了程序集中的代码,使其仅修改输出寄存器。你原来的代码修改了%ecx
但没有告诉编译器它正在这样做。你可以告诉编译器,通过把"ecx"
第三次之后:
,这就是“破坏”寄存器列表所在的位置。但是,由于我的代码让编译器分配一个寄存器,因此我不会在破坏的寄存器中列出特定的寄存器。可能有一种方法告诉编译器其中一个输入寄存器将被修改但输出不需要,但我不知道。 (文档是here https://gcc.gnu.org/onlinedocs/gcc-4.7.2/gcc/Extended-Asm.html.) 对于此任务,更好的解决方案是告诉编译器对输入之一使用与输出相同的寄存器:
__asm__(
" imull %[mydata1], %[myresult]\n"
: [myresult] "=r" (result)
: [mydata1] "r" (data1), [mydata2] "0" (data2));
在此,0
with data2
表示使其与操作数 0 相同。操作数按其出现的顺序编号,从第一个输出操作数 0 开始,一直到输入操作数。所以,当汇编代码开始时,%[myresult]
将引用一些寄存器的值data2
已被放置,编译器将期望新值result
组装完成后将出现在该寄存器中。
执行此操作时,您必须将约束与事物在装配中的使用方式相匹配。为了r
约束,编译器提供一些可以在接受通用处理器寄存器的汇编语言中使用的文本。其他包括m
作为内存参考,以及i
为立即数操作数。