AT&T erreur de compilation etc... [Résolu]

Signaler
Messages postés
37
Date d'inscription
lundi 14 novembre 2005
Statut
Membre
Dernière intervention
16 novembre 2006
-
Messages postés
141
Date d'inscription
mercredi 19 juillet 2006
Statut
Membre
Dernière intervention
20 avril 2011
-
Bonjour, j'aimerais me mettre a l'assembleur mais j'ai quelque problème.
voici mon code morceau de code pour trier un tableau de int : ( mélange de C/C++ et d'assembleur. )

    for(int j=0;j<SIZE;j++)

    {

        for(int k=j;k<SIZE;k++) {

            if( i[j] > i[k] ) {

                __asm("mov %0,%%eax" :: "m" (i[j]) ); // mov eax, i|j]

                __asm("mov %0,%1" : "=m" (i[j]) : "m" (i[k]) ); // mov i[j], i[k]

                __asm("mov %%eax,%0" : "=m" (i[k]) ); // mov i[k], eax

            }


        }

    }

malheureusement IDE ( Code::Blocks ) me retourne un message d'erreur :
too many memory reference for mov.
Comment faire pour résoudre cette erreur ?

merci,

7 réponses

Messages postés
1466
Date d'inscription
vendredi 2 janvier 2004
Statut
Modérateur
Dernière intervention
14 février 2014
1
salut,




ce genre d'instruction est impossible pour un processeur 386+,
__asm("mov %0,%1" : "=m" (i[j]) : "m" (i[k]) ); // mov i[j], i[k]
tu doit soit passer par un registre (edx ou ecx) soit par la pile avec un push/pop
@++
Messages postés
37
Date d'inscription
lundi 14 novembre 2005
Statut
Membre
Dernière intervention
16 novembre 2006

je doit faire comme ceci donc ?

__asm("mov %0,%%eax" :: "m" (a[j])); // mov eax, i|j]
__asm("mov %0,%%ebx" :: "m" (a[k])); // mov eax, i|j]
__asm("mov %%ebx,%0" : "=m" (a[j]) ); // mov i[k], eax
__asm("mov %%eax,%0" : "=m" (a[k]) ); // mov i[k], eax
mais bon ce code est-il simplifier au maximum ? parce que en C, si je fait
int c;
c = i[j];
i[j] = i[k] ;
i[k] = c ;

le c obtient de meilleur résultat niveau temps, 2 tableau d'entier ( 25000 case ) strictement identique, que je veux trier les tableaux
le c est plus rapide de 200 ms environ...

pourquoi :s
Messages postés
1466
Date d'inscription
vendredi 2 janvier 2004
Statut
Modérateur
Dernière intervention
14 février 2014
1
salut,



parce que le code c est optimisé, de plus, il utilise lui meme des registres, si les registres que tu utilise sont déjà utilisés pour les itérations, il faut les sauvegarder et les restaurer -> perte de temps.

@++
Messages postés
21041
Date d'inscription
jeudi 23 janvier 2003
Statut
Modérateur
Dernière intervention
21 août 2019
26
Ce qu'on peut résumer en:
Ne jamais mettre un peu d'ASM dans une fonction en C, on ne ferait qu'empêcher l'optimisation du compilo.
Soit on écrit la fonction entièrement en ASM soit on laisse en C.

ciao...
BruNews, MVP VC++
Messages postés
141
Date d'inscription
mercredi 19 juillet 2006
Statut
Membre
Dernière intervention
20 avril 2011

Salut,

Je suis d'accord avec BruNews, tant que l'on reste dans du code non vectorisable.
On peut par contre être amené (et je le fais assez souvent pour le traitement d'image ou de signal) à inserer de l'asm en ligne dans du C pour utiliser les instructions MMX et SSE, tant que le compilateur ne saura pas vectoriser à notre place (vectorisation prévu pour gcc 4.x, mais pour l'instant gcc-4.1 ne sait _que_ vectoriser et n'implémente pas encore la conversion vers MMX et SSE des boucles).

Exemple, sommation de 2 vecteurs de 16 bits signé avec gain dont la taille est multiple de 8 mots :

int audioMixer(short *mix1, int len1, short *mix2, int len2, int gain)
{
  int   len;

  //B1 GREATER THAN B2
  if (len1>len2)  {
    len=len1;
    for (int i=len2;i<len;i++)  mix2[i]=0;
  }
  else  {
    len=len2;
    for (int i=len1;i<len;i++)  mix1[i]=0;
  }

  // for SSE2 we need SSE2 cpu caps and len multiple of 8 shorts
  if((cpucaps & CPU_CAPS_SSE2) && !(len & 0x07)) {
      // go for SSE loop
      int len8 = (len+7)>>3 ;
      gain = gain & 0xFF; // ensure that gain is positive
      if(gain != 0) {
#ifdef __i386__ // to protect other archi compilation ...
    __asm(
         "   movd       %2,%%mm0      ;" // MM0 = [0 0 0 G]
         "   pshufw     $0,%%mm0,%%mm0;" // MM0 = [G G G G]
         "   movq2dq    %%mm0,%%xmm0  ;" // XMM0 = [0 0 0 0 G G G G]
         "   movdqa     %%xmm0,%%xmm1 ;" // XMM1 = [0 0 0 0 G G G G]
         "   pslldq     $8,%%xmm1     ;" // XMM1 = [G G G G 0 0 0 0]
         "   por        %%xmm1,%%xmm0 ;" // XMM0 = [G G G G G G G G]
         "0:                          ;"
         "   movdqu     (%0),%%xmm7   ;" // XMM7=Mix1
         "   movdqu     (%1),%%xmm1   ;" // XMM1=[S1 S2 S3 S4 S5 S6 S7 S8]
         "   movdqa     %%xmm1,%%xmm2 ;" // XMM2=[S1 S2 S3 S4 S5 S6 S7 S8]
         "   pmullw     %%xmm0,%%xmm1 ;" // XMM1= low words of G*S
         "   pmulhw     %%xmm0,%%xmm2 ;" // XMM2= high words of G*S
         "   movdqa     %%xmm1,%%xmm3 ;" // XMM3= low words of G*S
         "   punpcklwd  %%xmm2,%%xmm1 ;" // XMM1= [S1*G S2*G S3*G S4*G]
         "   punpckhwd  %%xmm2,%%xmm3 ;" // XMM3= [S5*G S6*G S7*G S8*G]
         "   psrad      $2,%%xmm1     ;" // XMM1= [S1*G S2*G S3*G S4*G] >> 2
         "   psrad      $2,%%xmm3     ;" // XMM3= [S5*G S6*G S7*G S8*G] >> 2
         "   packssdw   %%xmm3,%%xmm1 ;" // XMM1= [S1 S2 S3 S4 S5 S6 S7 S8]
         "   paddsw     %%xmm7,%%xmm1 ;" // Add Mix1 and Mix2*GAIN
         "   movdqu     %%xmm1,(%0)   ;" // Write result
         "   add        $16,%0        ;" // mix1 to next 8 values
         "   add        $16,%1        ;" // mix2 to next 8 values
         "   dec        %3            ;" // decrement counter
         "   jne        0b            ;" // roll if not zero
         :: "r" (mix1), "r" (mix2), "r" (gain), "r" (len8));
#endif
      }
  } else {
      // for MMX we need MMX cpu caps and len multiple of 4 shorts
      if((cpucaps & CPU_CAPS_MMX) && !(len & 0x03)) {
      int len4 = (len)>>2 ;
      gain = gain & 0xFF; // ensure that gain is positive
      // need to create mmx_gain, cause pshufw is SSE instr.
      unsigned short mmx_gain[4];
      mmx_gain[0] = gain;
      mmx_gain[1] = gain;
      mmx_gain[2] = gain;
      mmx_gain[3] = gain;
      // go for MMX loop
#ifdef __i386__ // to protect other archi compilation ...
      __asm(
            "   movq       %2,%%mm0      ;" // MM0 = [G G G G]
            "0:                          ;"
            "   movq       (%0),%%mm7    ;" // MM7=Mix1
            "   movq       (%1),%%mm1    ;" // MM1=[S1 S2 S3 S4]
            "   movq       %%mm1,%%mm2   ;" // MM2=[S1 S2 S3 S4]
            "   pmullw     %%mm0,%%mm1   ;" // MM1= low words of G*S
            "   pmulhw     %%mm0,%%mm2   ;" // MM2= high words of G*S
            "   movq       %%mm1,%%mm3   ;" // MM3= low words of G*S
            "   punpcklwd  %%mm2,%%mm1   ;" // MM1= [S1*G S2*G]
            "   punpckhwd  %%mm2,%%mm3   ;" // MM3= [S3*G S4*G]
            "   psrad      $2,%%mm1      ;" // MM1= [S1*G S2*G] >> 2
            "   psrad      $2,%%mm3      ;" // MM3= [S3*G S4*G] >> 2
            "   packssdw   %%mm3,%%mm1   ;" // MM1= [S1 S2 S3 S4]
            "   paddsw     %%mm7,%%mm1   ;" // Add Mix1 and Mix2*GAIN
            "   movq       %%mm1,(%0)    ;" // Write result
            "   add        $8,%0         ;" // mix1 to next 4 values
            "   add        $8,%1         ;" // mix2 to next 4 values
            "   dec        %3            ;" // decrement counter
            "   jne        0b            ;" // roll if not zero
            "   emms                     ;" // dont forget to cleanup FPU stack !
            :: "r" (mix1), "r" (mix2), "m" (mmx_gain[0]), "r" (len4));
#endif
      } else {
        // Fall back to standard mix
      // at first, division is VERY slow
      //for (int i=0;i<len;i++) mix1[i]=mix1[i]+((mix2[i]*gain)/GAIN_REF);
      // it is greatly better to do 2 right shifts as GAIN_REF=4
      for (int i=0;i<len;i++) {
        int result;
        result=mix1[i]+((mix2[i]*gain)>>2);
        if(result>32767) result=32767;
        if(result<-32768) result=-32768;
        mix1[i]=(short)result;
      }
      }
  }

  return len;
}

Mais pour le reste du code, standard, il est évident que le compilateur gcc est bien meilleur que nous en optimisation, et surtout dans sa capacité à réorganiser les instructions et à tirer parti des spécificités du processeur (en utilisant "-march=pentium4" par exemple).

Gentoo... que du bonheur ...
Messages postés
37
Date d'inscription
lundi 14 novembre 2005
Statut
Membre
Dernière intervention
16 novembre 2006

savez vous ou je peux trouver une documentation très complète pour apprendre a programmer ' correctement en asm ' ?

merci de votre aide
Messages postés
141
Date d'inscription
mercredi 19 juillet 2006
Statut
Membre
Dernière intervention
20 avril 2011

Salut,

Je ne sais pas si tu trouveras "[..] une documentation très complète pour apprendre a programmer ' correctement en asm ' [..]".

Si je peux te donner donner une méthode qui fonctionne bien, c'est l'analogie entre la programmation en asm et le langage :

1) Pour commencer, tu apprends la grammaire de base avec des bases en orthographe. De même en assembleur, pour commencer, tu vas apprendre à écrire des routines simples (grammaire de base) avec un jeu d'instruction de base (orthographe de base).

2) Tu vas ensuite améliorer ton vocabulaire pour réaliser des phrases ayant un sens plus pointu (utilisation de termes exacts). De même en assembleur, tu vas ensuite enrichir ton jeu d'instructions, non pas avec le dico de français ;) ,mais avec les datasheets d'intel(ou de tout autre constructeur de processeur).

3) tu vas prendre de l'aisance dans la langue, et construire des phrases riches en vocabulaire et utilisant des tournures de phrases trés pointues tout en jouant avec les mots (.. stade des écrivains et artistes). Ainsi, à ce stade en tant que programmeur en asm, tu vas prendre de l'aisance en manipulation des instructions et en optimisation de code ... et tu vas devenir un virtuose de la prose assembleur ;)

Tu peux donc conclure par toi même que la programmation en assembleur (mais aussi dans les autres langages) commence par l'apprentissage des rudiments (dont tu trouveras beaucoups d'exemples via google), mais se forge ensuite sur son expérience et sa motivation à aller chercher le plus loin possible les astuces de codes ... et celà, aucune documentation ne peut te l'apprendre ;)

La programmation est une passion ....

Gentoo... que du bonheur ...