IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

 C Discussion :

Échange de code


Sujet :

C

  1. #1
    Membre averti
    Avatar de exe2bin
    Profil pro
    Passionné de programmation
    Inscrit en
    Mars 2009
    Messages
    537
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Passionné de programmation

    Informations forums :
    Inscription : Mars 2009
    Messages : 537
    Points : 387
    Points
    387
    Billets dans le blog
    3
    Par défaut Échange de code
    Bonjour à tous ;
    je souhaite remplacer ce code :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    Pile[entree_libre++] = i;
    Pile[entree_libre++] = niveau++;
    Pile[entree_libre++] = nbElement--;
    par cela :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    __asm__
    (
       "pushl %0;pushl %1;pushl %2\n\t"
       "decl %1;incl %2\n\t"
       "addl $3, _entree_libre"
       : "=m" (i), "=m" (nbElement), "=m" (niveau)
       :
       : "memory"
    );
    Puis, plus loin, celui-ci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    nbElement = Pile[--entree_libre];
    niveau = Pile[--entree_libre];
    i = Pile[--entree_libre];
    par celui-là :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    __asm__
    (
       "popl %2;popl %1;popl %0\n\t"
       "subl $3, _entree_libre"
       : "=m" (i), "=m" (nbElement), "=m" (niveau)
       :
       : "memory"
    );
    Mais le programme plante . Quelqu'un voit-il pourquoi ?

  2. #2
    Expert confirmé

    Inscrit en
    Août 2006
    Messages
    3 941
    Détails du profil
    Informations forums :
    Inscription : Août 2006
    Messages : 3 941
    Points : 5 652
    Points
    5 652
    Par défaut
    Bonjour,

    La vraie question est : pourquoi vouloir mettre de l'asm ?

    Le compilateur C, avec ses optimisations fait probablement presque aussi bien, et à moins d'appeler ces fractions de code des millions de fois en un temps très bref, tu ne gagneras rien, sinon des ennuis, qui ont donc déjà commencés.
    Si les cons volaient, il ferait nuit à midi.

  3. #3
    Membre averti
    Avatar de exe2bin
    Profil pro
    Passionné de programmation
    Inscrit en
    Mars 2009
    Messages
    537
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Passionné de programmation

    Informations forums :
    Inscription : Mars 2009
    Messages : 537
    Points : 387
    Points
    387
    Billets dans le blog
    3
    Par défaut
    c'est exactement ça ! appeler ce code des milliard de fois ! C'est pour cela que je désire gagner
    des micro-secondes !

  4. #4
    Expert confirmé

    Inscrit en
    Août 2006
    Messages
    3 941
    Détails du profil
    Informations forums :
    Inscription : Août 2006
    Messages : 3 941
    Points : 5 652
    Points
    5 652
    Par défaut
    Bonjour,

    As-tu vérifié le code généré par le compilateur C ?

    J'ai souvent eu des surprises sur la qualité du code généré par les compilateurs modernes (Visual Studio et GCC), en activant les optimisations.

    J'avais l'habitude de faire de l'assembleur, sérieusement optimisé (en creusant les tables d'instructions, nombre de cycles, etc.), et j'ai peu à peu abandonné, car gagner sur le code généré n'est plus du tout évident, on a plutôt tendance à ralentir le programme (sans que ce soit général, évidemment).

    D'où ma question sur le code généré.
    Si les cons volaient, il ferait nuit à midi.

  5. #5
    Membre averti
    Avatar de exe2bin
    Profil pro
    Passionné de programmation
    Inscrit en
    Mars 2009
    Messages
    537
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Passionné de programmation

    Informations forums :
    Inscription : Mars 2009
    Messages : 537
    Points : 387
    Points
    387
    Billets dans le blog
    3
    Par défaut
    non je n'ai pas examiné le code généré par le compilateur mais je suis certain que tu as raison :
    de nos jours on ne peut faire mieux , sauf pour ce qui concerne les graphiques ;
    néanmoins j'aimerais réaliser ce petit bout de code assembleur.
    Apparement ce sont les pushl et popl qui posent problème ; pour en être sûr j'ai isolé le code
    dans un autre projet en appelant la fonction printf() entre les 2 codes assembleur et ....
    les popfl renvoient des valeurs innatendues !?

    Tu n'as qu'a essayer ce bout de code pour t'en persuader :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
     
    #include <stdio.h>
    #include <stdlib.h>
     
    int     glob = 10;
     
    int main()
    {
        int     a,b,c;
     
        a = b = c = 50;
        printf("a=%d\tb=%d\tc=%d\tglob=%d\n",a,b,c,glob);
        __asm__
        (
            "pushl %0;pushl %1;pushl %2\n\t"
            "decl %1;incl %2\n\t"
            "addl $3, _glob"
            : "=m" (a), "=m" (b), "=m" (c)
            :
            : "memory"
        );
        printf("a=%d\tb=%d\tc=%d\tglob=%d\n",a,b,c,glob);
        __asm__
        (
            "popl %2;popl %1;popl %0\n\t"
            "subl $3, _glob"
            : "=m" (a), "=m" (b), "=m" (c)
            :
            : "memory"
        );
        printf("a=%d\tb=%d\tc=%d\tglob=%d\n",a,b,c,glob);
     
        return 0;
    }

  6. #6
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Septembre 2007
    Messages
    7 360
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 360
    Points : 23 600
    Points
    23 600
    Par défaut
    Bonjour,

    Il y a plusieurs choses qui me déroutent dans ton code mais la première est qu'en principe, l'assembleur ne doit contenir qu'une seule instruction par ligne, et ce parce que les différentes « colonnes » (en fait les champs séparés par des espaces ou une tabulation) ont une sémantique : le premier est l'étiquette (même si parfois, en assembleur Intel, on la fait suivre de « : »), le second est l'instruction proprement dite, le troisième est l'opérande, qui obéit normalement à une grammaire spécifique incluant notamment les modes d'adressage, et les quatrième et suivants étant les commentaires.

    L'assembleur Intel comme certains autres tentent de limiter ces ambiguïtés en introduisant des délimiteurs spécifiques comme « ; » pour les commentaires. Autrement dit, tout ce qui suit la première instruction de chaque ligne est considéré comme en dehors du code. C'est flagrant avec gcc -S :

    Code asm : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    # 12 "code.c" 1
            pushl -12(%ebp);pushl -16(%ebp);pushl -20(%ebp)
            decl -16(%ebp);incl -20(%ebp)
            addl $3, glob
    # 0 "" 2

  7. #7
    Membre averti
    Avatar de exe2bin
    Profil pro
    Passionné de programmation
    Inscrit en
    Mars 2009
    Messages
    537
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Passionné de programmation

    Informations forums :
    Inscription : Mars 2009
    Messages : 537
    Points : 387
    Points
    387
    Billets dans le blog
    3
    Par défaut
    certes ,c'est assez déroutant la première fois ; contrairement à la syntaxe Intel ,
    la syntaxe AT&T est plutôt barbare mais c'est ainsi .....
    Si tu veux en savoir davantage : http://asm.developpez.com/cours/asminline/

  8. #8
    Membre émérite
    Homme Profil pro
    sans emploi
    Inscrit en
    Janvier 2014
    Messages
    539
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 51
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : sans emploi
    Secteur : Conseil

    Informations forums :
    Inscription : Janvier 2014
    Messages : 539
    Points : 2 601
    Points
    2 601
    Par défaut
    Citation Envoyé par exe2bin Voir le message
    Tu n'as qu'a essayer ce bout de code pour t'en persuader :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
     
    #include <stdio.h>
    #include <stdlib.h>
     
    int     glob = 10;
     
    int main()
    {
        int     a,b,c;
     
        a = b = c = 50;
        printf("a=%d\tb=%d\tc=%d\tglob=%d\n",a,b,c,glob);
        __asm__
        (
            "pushl %0;pushl %1;pushl %2\n\t"
            "decl %1;incl %2\n\t"
            "addl $3, _glob"
            : "=m" (a), "=m" (b), "=m" (c)
            :
            : "memory"
        );
        printf("a=%d\tb=%d\tc=%d\tglob=%d\n",a,b,c,glob);
        __asm__
        (
            "popl %2;popl %1;popl %0\n\t"
            "subl $3, _glob"
            : "=m" (a), "=m" (b), "=m" (c)
            :
            : "memory"
        );
        printf("a=%d\tb=%d\tc=%d\tglob=%d\n",a,b,c,glob);
     
        return 0;
    }
    Bonjour,
    tu utilises la pile système, mais tu ne modifies pas le pointeur de pile. Ton printf n'est pas au courant de ce que tu as empilé … et «y fout le bordel».
    Enfin je suppose, l'assembleur n'est pas ma tasse de thé. C'est rigolo car je pense que tu passes par une gestion propre de la pile pour t'éviter des appels récursifs et donc l'utilisation de la pile système, puis tu y reviens pour gagner quelques cycles … en terme d'optimisation par compilo cela s'appelle le stack unrolling, je crois (à vérifier).

    J'imagine également que tu travailles sur ce code :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
     
    void    iter(int n,int nbElement,struct noeud *ptr)
    {
        struct  noeud   *p = ptr;
        int     i,niveau = n;
        long    count = 0;
     
    A:  i = nbElement;
        while(i>0)
        {
            if(niveau != nombre_d_items)
            {
                Pile[entree_libre++] = i;
                Pile[entree_libre++] = niveau++;
                Pile[entree_libre++] = nbElement--;
                p = p->suivant;
                goto A;
            B:  p = p->precedant;
                nbElement = Pile[--entree_libre];
                niveau = Pile[--entree_libre];
                i = Pile[--entree_libre];
                /*if(niveau == nombre_d_items-1) {printListe();printf("\t");}*/
                if(++count == 53971002) {printListe();}
                insererApres(supprimerAvantZ(),p);
            }
            i--;
        }
        if(!pileVide()) goto B;
    }
    Plus tu feras du code spaghetti avec des goto vers et hors une boucle, plus tu vas compliquer le boulot d'optimisation du compilo. Il est souvent beaucoup plus profitable d'écrire un code simple que le compilo va optimiser qu'un code supposément optimisé que le compilo ne va que traduire.

    Une dernière remarque, ton code est limité à win32 avec tes morceaux asm, il ne compileras pas en 64bit ou sous linux par exemple. Il est peut-être préférable de faire un code que tu pourras paralléliser ou implémenter (enfin le compilo) avec des instructions avancées SIMD/MMX et autre SSE …

    Edit: à propos ton premier code fonctionne sous linux64 avec quelques aménagement, car l'ABI linux64 passe les paramètres int dans des registres sans les empiler …

  9. #9
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Septembre 2007
    Messages
    7 360
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 360
    Points : 23 600
    Points
    23 600
    Par défaut
    Citation Envoyé par exe2bin Voir le message
    certes ,c'est assez déroutant la première fois ; contrairement à la syntaxe Intel ,
    la syntaxe AT&T est plutôt barbare mais c'est ainsi .....
    Si tu veux en savoir davantage : http://asm.developpez.com/cours/asminline/
    Ce n'est pas ce que j'ai dit. La syntaxe AT&T est une chose mais le fait de séparer tes instructions assembleur avec des points-virgules « ; » est incorrect. Ta ligne est insérée telle quelle au sein du code produit par le compilateur et deux de tes trois instructions se retrouvent commentées, chose que l'on peut vérifier au moins avec GCC, en lui demandant de produire le code assembleur engendré plutôt que l'exécutable, à l'aide de l'option « -S ».

  10. #10
    Membre averti
    Avatar de exe2bin
    Profil pro
    Passionné de programmation
    Inscrit en
    Mars 2009
    Messages
    537
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Passionné de programmation

    Informations forums :
    Inscription : Mars 2009
    Messages : 537
    Points : 387
    Points
    387
    Billets dans le blog
    3
    Par défaut
    Ok ,Obsidian , voilà pour toi le code obtenu lors du débogage :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
     
    ................
     
    0x0040133C	pushl  -0x4(%ebp)
    	// premier code __asm__ ()
    0x0040133F	pushl  -0x8(%ebp)
     
    0x00401342	pushl  -0xc(%ebp)
     
    0x00401345	decl   -0x8(%ebp)
     
    0x00401348	incl   -0xc(%ebp)
     
    0x0040134F	addl   $0x3,0x407000
    ........................
    ..........................
    0x0040137C	popl   -0xc(%ebp)
     
    0x0040137F	popl   -0x8(%ebp)
     
    0x00401382	popl   -0x4(%ebp)
     
    0x00401389	subl   $0x3,0x407000

  11. #11
    Expert confirmé
    Inscrit en
    Mars 2005
    Messages
    1 431
    Détails du profil
    Informations forums :
    Inscription : Mars 2005
    Messages : 1 431
    Points : 4 182
    Points
    4 182
    Par défaut
    Résultat obtenu avec quelles options de compilation ?

    Comme les autres intervenants te l'ont dit, coder de cette manière si ce n'est pas pour l'exercice c'est de la pure perte de temps.

  12. #12
    Membre averti
    Avatar de exe2bin
    Profil pro
    Passionné de programmation
    Inscrit en
    Mars 2009
    Messages
    537
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Passionné de programmation

    Informations forums :
    Inscription : Mars 2009
    Messages : 537
    Points : 387
    Points
    387
    Billets dans le blog
    3
    Par défaut
    Je ne vois pas quel soucis peut-il y avoir avec Push et Pop puisque
    par définition ESP est mis à jour ; à moins de reconnaître que printf() est mal
    programmé (je n'irai pas juque là) ...

    Push/Poper des valeur dans la pile d'un programme ne coûte quand même
    pas autant qu'un appel de procédure (récursif ou pas d'ailleurs) ;
    c'est sans commune mesure avec la création d'un bloc d'activation avec
    sauvegarde de l'adresse de retour etc ...

    Aussi ,les gotos sont présent car il m'a fallu dé-récursifier la
    routine et sans passer par des gotos je vois pas comment faire !?
    Enfin si je souhaite utiliser la pile du programme c'est parce que
    justement il y en a une à ma disposition et je ne vois pas pourquoi
    alourdir le code en en créant une autre.

    Finalement je vois beaucoup de commentaires annexes mais pas celui qui
    propose une réponse au sujet du premier post.

  13. #13
    Membre émérite
    Homme Profil pro
    sans emploi
    Inscrit en
    Janvier 2014
    Messages
    539
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 51
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : sans emploi
    Secteur : Conseil

    Informations forums :
    Inscription : Janvier 2014
    Messages : 539
    Points : 2 601
    Points
    2 601
    Par défaut
    Citation Envoyé par exe2bin Voir le message
    Je ne vois pas quel soucis peut-il y avoir avec Push et Pop puisque
    par définition ESP est mis à jour ; à moins de reconnaître que printf() est mal
    programmé (je n'irai pas juque là) ...

    Push/Poper des valeur dans la pile d'un programme ne coûte quand même
    pas autant qu'un appel de procédure (récursif ou pas d'ailleurs) ;
    c'est sans commune mesure avec la création d'un bloc d'activation avec
    sauvegarde de l'adresse de retour etc ...
    Comme tu le dis il est fort à parier que printf n'est pas «mal programmé» mais si ton code assembleur ne fonctionne pas c'est tu l'utilises mal et que tu crois, à tort, bien l'utiliser.
    L'erreur que tu fais est simple : tu crois que le compilateur fait ce que tu crois qu'il fait alors que ce n'est absolument pas le cas. Un compilateur ne fait pas simplement traduire mot à mot du code c en assembleur, surtout quand tu lui demandes d'optimiser. Et je peux parier sans trop me tromper qu'il est bien plus simple d'aider le compilateur à optimiser que de faire des conjectures et d'essayer d'optimiser toi même le code assembleur produit en insérant de l'assembleur ou des goto mal utilisés.

    L'exemple simple et un peu bidon je te l'accorde est la version tail recursive de fibonacci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    int fibo_r(int n, int a, int b)
    {
    	if (n==0) return a;
    	if (n==1) return b;
    	return fibo_r(n-1, b, a+b);
    }
    Si tu ne lui demandes pas d'optimiser tu obtiens, il est vrai, une traduction mot à mot du code :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    int fibo_r(int n, int a, int b)
    {
       0:	55                   	push   %rbp
       1:	48 89 e5             	mov    %rsp,%rbp
       4:	48 83 ec 10          	sub    $0x10,%rsp
       8:	89 7d fc             	mov    %edi,-0x4(%rbp)
       b:	89 75 f8             	mov    %esi,-0x8(%rbp)
       e:	89 55 f4             	mov    %edx,-0xc(%rbp)
    	if (n==0) return a;
      11:	83 7d fc 00          	cmpl   $0x0,-0x4(%rbp)
      15:	75 05                	jne    1c <fibo_r+0x1c>
      17:	8b 45 f8             	mov    -0x8(%rbp),%eax
      1a:	eb 25                	jmp    41 <fibo_r+0x41>
    	if (n==1) return b;
      1c:	83 7d fc 01          	cmpl   $0x1,-0x4(%rbp)
      20:	75 05                	jne    27 <fibo_r+0x27>
      22:	8b 45 f4             	mov    -0xc(%rbp),%eax
      25:	eb 1a                	jmp    41 <fibo_r+0x41>
    	return fibo_r(n-1, b, a+b);
      27:	8b 55 f8             	mov    -0x8(%rbp),%edx
      2a:	8b 45 f4             	mov    -0xc(%rbp),%eax
      2d:	01 c2                	add    %eax,%edx
      2f:	8b 45 fc             	mov    -0x4(%rbp),%eax
      32:	8d 48 ff             	lea    -0x1(%rax),%ecx
      35:	8b 45 f4             	mov    -0xc(%rbp),%eax
      38:	89 c6                	mov    %eax,%esi
      3a:	89 cf                	mov    %ecx,%edi
      3c:	e8 00 00 00 00       	callq  41 <fibo_r+0x41>
      41:	c9                   	leaveq 
      42:	c3                   	retq
    J'y ai laissé les information de debug pour plus de clarté.

    En revanche, si tu lui demande d'optimiser le code produit :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    0000000000000000 <fibo_r>:
       0:	85 ff                	test   %edi,%edi
       2:	75 18                	jne    1c <fibo_r+0x1c>
       4:	eb 1e                	jmp    24 <fibo_r+0x24>
       6:	66 2e 0f 1f 84 00 00 	nopw   %cs:0x0(%rax,%rax,1)
       d:	00 00 00 
      10:	83 ef 01             	sub    $0x1,%edi
      13:	8d 04 16             	lea    (%rsi,%rdx,1),%eax
      16:	74 09                	je     21 <fibo_r+0x21>
      18:	89 d6                	mov    %edx,%esi
      1a:	89 c2                	mov    %eax,%edx
      1c:	83 ff 01             	cmp    $0x1,%edi
      1f:	75 ef                	jne    10 <fibo_r+0x10>
      21:	89 d0                	mov    %edx,%eax
      23:	c3                   	retq   
      24:	89 f0                	mov    %esi,%eax
      26:	c3                   	retq
    Mazette ! Plus d'appel récursif ! Il l'a dérécursivé lui-même d'une manière bien plus optimale que ce des instructions en assembleur aurait pu faire pour le dérécursiver !

    Pire comparons la sortie d'un fibonacci itératif classique
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    int fibo_i(int n)
    {
    	if (n<2) return 1;
    	int a=1;
    	int b=1;
    	for(int i=2; i<=n; ++i) {
    		int temp=a+b;
    		a=b;
    		b=temp;
    	}
    	return b;
    }
    donne avec optimisation due au compilateur :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    0000000000000000 <fibo_i>:
       0:	83 ff 01             	cmp    $0x1,%edi
       3:	7e 2b                	jle    30 <fibo_i+0x30>
       5:	83 c7 01             	add    $0x1,%edi
       8:	ba 02 00 00 00       	mov    $0x2,%edx
       d:	b8 01 00 00 00       	mov    $0x1,%eax
      12:	b9 01 00 00 00       	mov    $0x1,%ecx
      17:	66 0f 1f 84 00 00 00 	nopw   0x0(%rax,%rax,1)
      1e:	00 00 
      20:	8d 34 01             	lea    (%rcx,%rax,1),%esi
      23:	83 c2 01             	add    $0x1,%edx
      26:	89 c1                	mov    %eax,%ecx
      28:	39 d7                	cmp    %edx,%edi
      2a:	89 f0                	mov    %esi,%eax
      2c:	75 f2                	jne    20 <fibo_i+0x20>
      2e:	f3 c3                	repz retq 
      30:	b8 01 00 00 00       	mov    $0x1,%eax
      35:	c3                   	retq
    Évidemment tu peux arguer qu'un code assembleur plus court, plus rapide, en un mot plus «homme qui valait 3 milliards» existe comme :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    _fibonacci:
    	xor    eax, eax           ; 31 c0
    	jecxz  _fibonacci_end     ; e3 0a
    	dec    ecx                ; 49
    	inc    eax                ; 40
    	jecxz  _fibonacci_end     ; e3 06
    	cdq                       ; 99
    _fibonacci_loop:
    	xchg   eax, edx           ; 92
    	add    eax, edx           ; 01 d0
    	loop   _fibonacci_loop    ; e2 fb
    _fibonacci_end:
    	ret                       ; c3
    Mais bon … faut faire un choix. Soit on écrit en C un code qui optimisé sera presque le plus rapide ou programmer en assembleur pour faire le plus rapide du rapide, Mélanger les deux ne crée que des soucis.

    Citation Envoyé par exe2bin Voir le message
    Aussi ,les gotos sont présent car il m'a fallu dé-récursifier la
    routine et sans passer par des gotos je vois pas comment faire !?
    Tu as dérécursifier ta fonction en créant une pile pour imiter la pile système lors des appels récursifs et maintenant tu veux utiliser la pile système car tu crois qu'elle sera plus rapide.
    Pour dérecursifier efficacement tu peux prendre d'autrea approches comme trouver une version tail recursive que le compilo sera capable d'optimiser ou trouver une version itérative «pure» (je n'aime pas trop cette expression mais nous nous comprenons) comme l'algorithme L que tu peux trouver dans le fascicule 2b du TAOCP de Knuth.
    En un mot comme en cent, optimise ton algorithme en oubliant (un peu) ce que tu crois qu'il se passe derrière et laisse le compilo mettre les mains dans le cambouis en le guidant. gcc (comme clang) possède une tonne d'options d'optimisation (unroll loops, sse4, gomp/openacc pour paralléliser, attribut de fonction hot, inlining, …).
    Pour optimiser efficacement un programme il y a des outils comme le profiler gprof qui t'indique là où les optimisations seront les plus sensibles.

    Citation Envoyé par exe2bin Voir le message
    Enfin si je souhaite utiliser la pile du programme c'est parce que
    justement il y en a une à ma disposition et je ne vois pas pourquoi
    alourdir le code en en créant une autre.
    En C on n'utilise pas la pile. C'est le compilo qui décide s'il est adéquat ou non de l'utiliser. Lui imposer une manipulation en assembleur c'est lui mettre des bâtons dans les roues.

    Citation Envoyé par exe2bin Voir le message
    Finalement je vois beaucoup de commentaires annexes mais pas celui qui
    propose une réponse au sujet du premier post.
    Ce qu'on te dit, enfin du moins ce que je te dis, c'est que ton approche n'est pas la meilleure. Une autre approche te créera sans doute plus de boulot maintenant mais moins de soucis par la suite.

  14. #14
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 518
    Points
    41 518
    Par défaut
    ↑Dommage que je ne puisse te donner qu'un seul pouce haut, car tu formules ma pensée mieux que moi-même.
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  15. #15
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Septembre 2007
    Messages
    7 360
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 360
    Points : 23 600
    Points
    23 600
    Par défaut
    Citation Envoyé par exe2bin Voir le message
    Finalement je vois beaucoup de commentaires annexes mais pas celui qui
    propose une réponse au sujet du premier post.
    Est-ce que tu pourrais commencer par nous dire quel compilateur tu utilises, sur quelle plateforme et avec quel système d'exploitation ? Et accessoirement, si tu compiles en 32 bits, en 64 bits, ou si tu laisses le compilateur choisir ?

    On en est au quinzième commentaire et on ne le sait toujours pas, alors que ce que tu fais est intimement lié à l'ABI en vigueur et aux optimisations que le compilateur choisit ou non d'appliquer comme expliqué ci-dessus.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. De la rapidité du code
    Par jfloviou dans le forum Contribuez
    Réponses: 233
    Dernier message: 29/05/2009, 03h17
  2. code pour interbase 6.0 et 6.5 de generateur
    Par tripper.dim dans le forum InterBase
    Réponses: 4
    Dernier message: 01/07/2002, 12h29
  3. [MFC](encapsulation ADO) ou placer le code
    Par philippe V dans le forum MFC
    Réponses: 2
    Dernier message: 13/06/2002, 15h58
  4. Explorateur de code C
    Par Zero dans le forum C
    Réponses: 14
    Dernier message: 06/06/2002, 10h41
  5. OmniORB : code sous Windows et Linux
    Par debug dans le forum CORBA
    Réponses: 2
    Dernier message: 30/04/2002, 18h45

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo