(C中的内联汇编)汇编程序消息:错误:未知的伪操作:

我为asm内联汇编编写了一个简短的C“包装器”函数,如下所示。 汇编代码由while循环组成,使用SSE2计算几个矢量点积。 我在x86上的Ubuntu 14.04上使用GCC 4.8.4。 以下代码可以“无问题”组装

gcc -fpic -O2 -msse2 -S foo.c

但是,当我这样做

gcc -c foo.s

触发错误:

foo.c:汇编程序消息:
foo.c:2:错误:未知的伪操作:`.while5′

我检查了汇编器输出“foo.s”并发现了一些奇怪的东西。

C文件“foo.c”:

#include  void foo (int kk, double *A, double *B, double *ALPHA, double *C, int ldc) { asm("movl %0, %%ecx\n\t" /* kk -> %ecx */ "movl %3, %%eax\n\t" /* A -> %eax */ "movl %4, %%edx\n\t" /* B -> %edx */ /* a while-loop */ ".while%=\n\t" "movsd (%%edx), %%xmm5\n\t" "unpcklpd %%xmm5, %%xmm5\n\t" "movapd %%xmm5, %%xmm6\n\t" "movapd (%%eax), %%xmm4\n\t" "mulpd %%xmm4, %%xmm6\n\t" "movapd 16(%%eax), %%xmm7\n\t" "addl $32, %%eax\n\t" "addpd %%xmm6, %%xmm0\n\t" "mulpd %%xmm7, %%xmm5\n\t" "addpd %%xmm5, %%xmm1\n\t" "movsd 8(%%edx), %%xmm6\n\t" "addl $16, %%edx\n\t" "unpcklpd %%xmm6, %%xmm6\n\t" "mulpd %%xmm6, %%xmm4\n\t" "addpd %%xmm4, %%xmm2\n\t" "mulpd %%xmm6, %%xmm7\n\t" "addpd %%xmm7, %%xmm3\n\t" "subl $1, %%ecx\n\t" /* kk-- */ "testl %%ecx, %%ecx\n\t" /* kk = 0 ? */ "jne .while%=\n\t" /* other input operands passing */ "movl %5, %%ecx\n\t" /* C -> %ecx */ "movl %1, %%eax\n\t" /* ALPHA -> %eax, then C0 -> %eax */ "movl %2, %%edx\n\t" /* ldc -> %edx */ /* write-back */ "movsd (%%eax), %%xmm7\n\t" "unpcklpd %%xmm7, %%xmm7\n\t" "leal (%%ecx,%%edx,8), %%eax\n\t" /* C0=C+ldc */ "mulpd %%xmm7, %%xmm0\n\t" "addpd (%%ecx), %%xmm0\n\t" "movapd %%xmm0, (%%ecx)\n\t" "mulpd %%xmm7, %%xmm2\n\t" "addpd (%%eax), %%xmm2\n\t" "movapd %%xmm2, (%%eax)\n\t" "mulpd %%xmm7, %%xmm1\n\t" "addpd 16(%%ecx), %%xmm1\n\t" "movapd %%xmm1, 16(%%ecx)\n\t" "mulpd %%xmm7, %%xmm3\n\t" "addpd 16(%%eax), %%xmm3\n\t" "movapd %%xmm3, 16(%%eax)\n\t" : /* no output operands */ : "m"(kk), "m"(ALPHA), "m"(ldc), "m"(A), "m"(B), "m"(C) /* input operands */ : "eax", "edx", "ecx", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7" /* clobbers */ ); } 

汇编器输出(while循环看起来很奇怪!)

 .LFB503: .cfi_startproc #APP # 4 "foo.c" 1 movl 4(%esp), %ecx movl 8(%esp), %eax movl 12(%esp), %edx .while5 movsd (%edx), %xmm5 unpcklpd %xmm5, %xmm5 movapd %xmm5, %xmm6 movapd (%eax), %xmm4 mulpd %xmm4, %xmm6 movapd 16(%eax), %xmm7 addl $32, %eax addpd %xmm6, %xmm0 mulpd %xmm7, %xmm5 addpd %xmm5, %xmm1 movsd 8(%edx), %xmm6 addl $16, %edx unpcklpd %xmm6, %xmm6 mulpd %xmm6, %xmm4 addpd %xmm4, %xmm2 mulpd %xmm6, %xmm7 addpd %xmm7, %xmm3 subl $1, %ecx testl %ecx, %ecx jne .while5 movl 20(%esp), %ecx movl 16(%esp), %eax movl 24(%esp), %edx movsd (%eax), %xmm7 unpcklpd %xmm7, %xmm7 leal (%ecx,%edx,8), %eax mulpd %xmm7, %xmm0 addpd (%ecx), %xmm0 movapd %xmm0, (%ecx) mulpd %xmm7, %xmm2 addpd (%eax), %xmm2 movapd %xmm2, (%eax) mulpd %xmm7, %xmm1 addpd 16(%ecx), %xmm1 movapd %xmm1, 16(%ecx) mulpd %xmm7, %xmm3 addpd 16(%eax), %xmm3 movapd %xmm3, 16(%eax) # 0 "" 2 #NO_APP ret .cfi_endproc 

任何人都可以问我发生了什么事吗? 我不认为这是我编译器的问题。 我的代码一定有问题。 谢谢!

因为.while未被定义为标签,所以它被视为[不存在的]伪操作。

更改:

 ".while%=\n\t" 

成:

 ".while%=:\n\t" 

更新:

按你的要求。

“伪操作”是[assember指令的术语],它与指令不对应。

一些例子:

.globl main指定main标签是全局变量。

.text指定.text内容应放在“text”段中(同样适用于.data )。

这个. 前缀[通常]为伪操作保留。 这就是你得到Error: unknown pseudo-op: message的原因。

如果你做了"while%=\n\t"而不是[仍然错误,因为没有:表示标签],你会得到一个不同的消息: Error: no such instruction: