AT&T erreur de compilation etc...

Résolu
maminovadu75 Messages postés 37 Date d'inscription lundi 14 novembre 2005 Statut Membre Dernière intervention 16 novembre 2006 - 15 oct. 2006 à 16:51
_dune2_ Messages postés 141 Date d'inscription mercredi 19 juillet 2006 Statut Membre Dernière intervention 20 avril 2011 - 28 oct. 2006 à 13:12
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

cs_patatalo Messages postés 1466 Date d'inscription vendredi 2 janvier 2004 Statut Modérateur Dernière intervention 14 février 2014 2
15 oct. 2006 à 18:22
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
@++
3
maminovadu75 Messages postés 37 Date d'inscription lundi 14 novembre 2005 Statut Membre Dernière intervention 16 novembre 2006
15 oct. 2006 à 18:50
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
3
cs_patatalo Messages postés 1466 Date d'inscription vendredi 2 janvier 2004 Statut Modérateur Dernière intervention 14 février 2014 2
15 oct. 2006 à 20:06
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.

@++
3
BruNews Messages postés 21040 Date d'inscription jeudi 23 janvier 2003 Statut Modérateur Dernière intervention 21 août 2019
16 oct. 2006 à 09:37
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++
3

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
_dune2_ Messages postés 141 Date d'inscription mercredi 19 juillet 2006 Statut Membre Dernière intervention 20 avril 2011
16 oct. 2006 à 10:50
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 ...
3
maminovadu75 Messages postés 37 Date d'inscription lundi 14 novembre 2005 Statut Membre Dernière intervention 16 novembre 2006
16 oct. 2006 à 18:53
savez vous ou je peux trouver une documentation très complète pour apprendre a programmer ' correctement en asm ' ?

merci de votre aide
0
_dune2_ Messages postés 141 Date d'inscription mercredi 19 juillet 2006 Statut Membre Dernière intervention 20 avril 2011
28 oct. 2006 à 13:12
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 ...
0
Rejoignez-nous