2009-05-18 55 views
2

我们最近将代码从gcc4.2.4升级到gcc4.3.3汇编编译错误(gcc4.2.4 = win,gcc4.3.3 = fail)

void testAndSet( volatile int* s, int* val) 
{ 
    __asm__ __volatile__ ("btsl $0, %0\n " 
      "jc bitSet\n " 
      "movl $0, %1\n " 
      "jmp returnVector\n" 
      "bitSet:\n " 
      "movl $1, %1\n" 
      "returnVector: " : "=m"(*s), "=m"(*val)); 
} 

我们的代码现在失败,出现以下错误,

lock.cxx: Assembler messages: 
lock.cxx:59: Error: symbol `bitSet' is already defined 
lock.cxx:61: Error: symbol `returnVector' is already defined 
lock.cxx:59: Error: symbol `bitSet' is already defined 
lock.cxx:61: Error: symbol `returnVector' is already defined 

这些符号,未发现其他地方。 (重命名它们会导致与新名称相同的错误)。

这是怎么回事?为什么我会错误两次?

回答

9

可能是优化程序发生了变化,现在将testAndSet()函数内联到2个位置。因为您正在为标签使用全局名称,所以这不起作用。您应该使用本地名称。例如:

__asm__ __volatile__ ("btsl $0, %0\n " 
      "jc 0f\n " 
      "movl $0, %1\n " 
      "jmp 1f\n" 
      "0:\n " 
      "movl $1, %1\n" 
      "1: " : "=m"(*s), "=m"(*val)); 

本地标签只是数字;要消除多个名为“0”的标签的情况,您需要使用“jmp 0f”作为前向跳转,而“jmp 0b”作为向后跳转。

+0

很好。就是这样。有趣的是,使用gcc选项-02失败,但使用-O – user48956 2009-05-18 17:40:12

5

这无关你的错误,但你可以提高你的代码,避免分支机构只需使用setCC instruction

__asm__ __volatile__ ("btsl $0, %0\n " 
     "mov $0, %1\n" 
     "setc %1\n" : "=m"(*s), "=m"(*val)); 

setCC指令(其中CC是条件码标志之一,类似于jCC指令)根据给定条件是否满足将字节设置为0或1。由于目的地是一个4字节的值,就需要或者与0预加载它,或使用MOVZX instruction使上3个字节0

1

您也可以通过后的各局部加入%=使用本地标签名称标签:

“loop%=”“\ n \ t”