C 外接程序asm的奇怪行为
此代码的输出:C 外接程序asm的奇怪行为,c,gcc,x86,inline-assembly,C,Gcc,X86,Inline Assembly,此代码的输出: int i=0; while(i<5) { asm volatile ( "addl $1,%0" :"=r"(i) : :"memory" ); printf("%d\n",i); } 但应该是这样的: 2 3 3 3 . . . 1 2 3 4 5 为什么会这样?我似乎不明白问题出在哪里。您正在将I指定为仅输出的操作数。也就是说,编译器使
int i=0;
while(i<5)
{
asm volatile
(
"addl $1,%0"
:"=r"(i)
:
:"memory"
);
printf("%d\n",i);
}
但应该是这样的:
2
3
3
3
.
.
.
1
2
3
4
5
为什么会这样?我似乎不明白问题出在哪里。您正在将
I
指定为仅输出的操作数。也就是说,编译器使用寄存器%0
的输出作为变量,但当前值ifi
不会在开始时复制到寄存器
为同一寄存器指定i
作为输入:
asm volatile
(
"addl $1,%0"
:"=r"(i)
:"0"(i)
:"memory"
);
谢谢,但这是你代码第5行的打字错误吗?声明读写操作数不应该是:“r”(i)还是更简单的,
“+r”(i)
。通常只对单独的变量使用单独的匹配约束,即当语义与该语法匹配时。等等,ADD在此代码中不接受任何寄存器操作数。这是一个内存操作数。你在说什么?如果涉及到任何寄存器,它不应该被删除吗?@Tuhnri:不,你只会在你修改的不是输出的东西上声明删除。(顺便说一句,这个asm语句不应该声明为volatile
,也不应该有“内存”
缓冲区。如果不需要i
的值,让编译器对它进行优化是可以的。)顺便说一句,没有:“r”(i)
作为输入会让编译器选择一个不同于目标的寄存器,因此,您必须将其写入lea1(%1),%0
才能使用这两个操作数<代码>“0”是一个匹配约束:选择任何寄存器%0
@Tuhnri:还有,你说的是使用内存操作数的WTF吗<代码>r表示寄存器。在最近的问题中,您还没有看到编译器的asm输出来自您试图编写的内联asm吗?请检查反汇编。尽管编译器可以/将有所不同,但它并没有初始化寄存器,而是在循环中每次递增寄存器。当您使用jlahd的答案时,您将看到它在循环之前添加了一条指令,将寄存器归零。