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
的输出作为变量,但当前值if
i
不会在开始时复制到寄存器

为同一寄存器指定
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的答案时,您将看到它在循环之前添加了一条指令,将寄存器归零。