我有以下代码:
#include <stdio.h>
void main(){
int x=0, y=0,i=100;
for (;i<1000; i++,x+=32){
if (x == 25*32) {
y+=32;
asm volatile("pushl %%eax\n\t"
"movl $0, %%eax\n\t"
"popl %%eax\n\t"
:"=a"(x)
:"a"(0)
);
}
printf("%d %d\n", x, y);
}
}
Run Code Online (Sandbox Code Playgroud)
基本上,我想要做的是,将变量x设置为0,但我不太明白汇编代码的作用,它实际上将x设置为0,但我不确定最新情况.谁能解释一下发生了什么?(只是为了学习汇编和C).
这是你的asm结构所说的:
"=a"(x),您告诉编译器程序集将write(=)到%eax(a)寄存器,并且您希望编译器将该结果分配给x((x))."a"(0),您告诉编译器您希望它(0)在%eax(a)中放置一个0 (),并且程序集将读取它.push %%eax在堆栈上保存%eax,movl $0, %%eax在%eax中输入0,并将popl %%eax保存的值恢复为%eax.那么,会发生什么:
所以,这有效,但效率低下.你可以用这个得到同样的效果:
asm volatile("movl $0, %[MyName]"
: [MyName] "=r" (x)
);
Run Code Online (Sandbox Code Playgroud)
这说的是:
=告诉编译器这些指令会写一个结果.r说的结果将被写入寄存器,但是编译器到达挑选寄存器.[MyName]告诉编译器来改变%[MyName],它出现在汇编代码,在登记编译精选的名称.(x)汇编代码之后使用寄存器中的值作为x的新值.movl $0, %[MyName]说将0移动到%[MyName]命名的寄存器.因为编译器可以选择寄存器,所以您不必使用汇编语言保存和恢复它.编译器负责确保它不需要其他任何寄存器.
能够像我一样命名操作数[MyName]是GCC的一个新功能.如果您的版本没有它,您可以这样做:
asm volatile("movl $0, %0"
: "=r" (x)
);
Run Code Online (Sandbox Code Playgroud)
如果没有名称,每个操作数都会得到一个数字,从0开始,并按操作数出现在输入/输出说明符中的顺序递增.由于我们只有一个操作数,因此它是%0.