2009-05-18 4 views
2

Nous avons récemment mis à jour le code à gcc4.3.3 de gcc4.2.4.Erreur de compilation d'assembly (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)); 
} 

Notre code échoue maintenant avec les erreurs suivantes,

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 

Ces symboles sont introuvables nulle part ailleurs. (Renommer les provoque la même erreur avec le nouveau nom).

Quoi de neuf? pourquoi ai-je deux fois les erreurs?

Répondre

9

L'optimiseur a probablement changé et intègre maintenant votre fonction testAndSet() en 2 endroits. Parce que vous utilisez des noms globaux pour vos étiquettes, cela ne fonctionne pas. Vous devriez utiliser des noms locaux à la place. E.g:

__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)); 

Les étiquettes locales sont simplement des nombres; pour désambiguïser les cas où il y a plusieurs étiquettes appelées "0", vous devez utiliser "jmp 0f" pour les sauts vers l'avant et "jmp 0b" pour les sauts vers l'arrière.

+0

Très bien. C'était ça. Fait intéressant, échoue avec l'option gcc -02 mais pas avec -O – user48956

+0

Plus la valeur du paramètre -O est élevée, plus il est probable que les choses soient en ligne; En gros, -O2 et -O3 vont utiliser des optimisations basées sur des incréments de plus en plus agressifs et des déroulements de boucles, etc. Il peut être intéressant d'essayer '-Os' (optimiser sans augmenter la taille du code) qui offre souvent une bonne optimisation intermédiaire. –

5

Ceci est sans rapport avec votre erreur, mais vous pouvez améliorer votre code et éviter les branches en utilisant simplement le setCC instruction:

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

L'instruction setCC (où CC est l'un des drapeaux de code de condition, analogue à la jCC instruction) définit un octet à 0 ou 1 selon que la condition donnée a été satisfaite ou non. Étant donné que la destination est une valeur de 4 octets, vous devez soit précharger avec 0 ou utiliser le MOVZX instruction pour faire 3 octets supérieur 0.

1

vous pouvez également utiliser des noms d'étiquettes locales en ajoutant % = après chaque locale étiquette:

"boucle% =:" "\ n \ t"