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

x86 32-bits / 64-bits Assembleur Discussion :

Adressage de base avec ESP


Sujet :

x86 32-bits / 64-bits Assembleur

  1. #1
    Membre confirmé
    Inscrit en
    Juillet 2005
    Messages
    512
    Détails du profil
    Informations forums :
    Inscription : Juillet 2005
    Messages : 512
    Points : 641
    Points
    641
    Par défaut Adressage de base avec ESP
    Est ce que de l'adressage de base avec ESP existe
    Exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    mov dword ptr [esp+4],20
    ou doit-on passer par les registres EBX, EBP ?

  2. #2
    Expert confirmé

    Inscrit en
    Août 2006
    Messages
    3 942
    Détails du profil
    Informations forums :
    Inscription : Août 2006
    Messages : 3 942
    Points : 5 654
    Points
    5 654
    Par défaut
    Noe,

    Oui, ça existe.

    Mais il faut être conscient que ça adresse la pile.
    Si les cons volaient, il ferait nuit à midi.

  3. #3
    Membre confirmé
    Inscrit en
    Juillet 2005
    Messages
    512
    Détails du profil
    Informations forums :
    Inscription : Juillet 2005
    Messages : 512
    Points : 641
    Points
    641
    Par défaut
    Merci,

    Je sais que ça adresse la pile, c'est bien pour cela que je pose la question.
    C'est au sujet des fonctions en langage C, elle utilise le registre EBP pour faire cela (pour lire les paramètres de la fonction par exemple), alors que ce n'est pas toujours necessaire. On pourait passer directement par ESP.

  4. #4
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Septembre 2007
    Messages
    7 372
    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 372
    Points : 23 628
    Points
    23 628
    Par défaut
    Non, parce que ESP varie. Tu peux stocker des choses toi-même dans la pile, et tu peux descendre dans des sous-fonctions sans définir de nouveaux cadres de pile.

    En outre, c'est très pratique en cas d'exception, quand tu dois quitter une procédure en plein traitement avant qu'elle ait pu vider la pile elle-même. Ça te permet de ramener ESP « au début ».

  5. #5
    Membre confirmé
    Inscrit en
    Juillet 2005
    Messages
    512
    Détails du profil
    Informations forums :
    Inscription : Juillet 2005
    Messages : 512
    Points : 641
    Points
    641
    Par défaut
    Citation Envoyé par Obsidian
    Non, parce que ESP varie.
    Quand je suis dans une fonction (simple), je sais bien si ESP va varier ou pas. Donc je ne vois pas ce qui pose problème ?

  6. #6
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Septembre 2007
    Messages
    7 372
    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 372
    Points : 23 628
    Points
    23 628
    Par défaut
    Citation Envoyé par Lucien63 Voir le message
    Je ne vois pas ce qui pose problème ?
    Je te l'ai dit. Tu peux tout gérer à partir du pointeur de pile (tous les microprocesseurs ne proposent pas un registre dédié comme EBP), mais c'est beaucoup plus compliqué :

    • D'abord, ton pointeur de pile évolue au cours de la fonction. Si ces évolutions ne sont pas « statiques » (comprendre par là « connues à la compilation »), par exemple si tu empiles récursivement des valeurs tant qu'un registre est différent de zéro, par exemple, tu es obligé d'impliquer ce registre dans ton calcul d'index et ça devient très compliqué de retrouver le début de ta pile. Autant directement utiliser un registre qui conserve sa valeur ;
    • Ensuite, les langages de haut niveau sont suceptibles de mettre fin prématurément à ta fonction, à n'importe quel moment. Ça peut arriver si le programmeur à mis un « return » en plein milieu.


    Dans ce dernier cas, il te faut remettre directement le pointeur de pile à l'état où il était en rentrant dans la fonction, pour retrouver celui des registres qui y ont été sauvegardés et rendre la main à la fonction du niveau du dessus.

    Pire encore, lorsque tu utilises un langage compilé qui gère les exceptions (C++, par exemple), si celle-ci n'est pas rattrapée en interne, tu peux « dévisser » de trois ou quatre fonctions avant de reprendre la main. Dans ce cas, le fait d'utiliser EBP pour pointer le cadre de pile te permet de remonter itérativement jusqu'à la fonction souhaitée. Tu restaures le pointeur de pile initial en remettant EBP dans ESP, tu fais un POPA (qui restaure EBP), et tu recommences n fois.

    C'est notamment ce que font automatiquement les instructions ENTER et LEAVE. C'est pourquoi il est intéressant de respecter le bon format.

    D'autre part, « BP » signifie « Base Pointer ». C'est donc un registre dédié à l'indexation par offset par rapport à un point de départ, même si on peut le faire avec d'autres registres, et heureusement. Tu n'es pas obligé de t'en servir uniquement pour référencer le cadre de pile. C'est utile pour exploiter des structures, par exemple.

  7. #7
    Membre confirmé
    Inscrit en
    Juillet 2005
    Messages
    512
    Détails du profil
    Informations forums :
    Inscription : Juillet 2005
    Messages : 512
    Points : 641
    Points
    641
    Par défaut
    Je me suis peut-être mal exprimé.
    Je parlais de fonction C et non C++.
    C'est au sujet des fonctions en langage C
    Je parlais dans le contexe ou c'est moi qui écrit la fonction en asm.
    Je sais donc bien si ESP va être modifié ou pas quand même. Il va pas bougé tout seul ?

  8. #8
    Membre actif

    Inscrit en
    Février 2009
    Messages
    200
    Détails du profil
    Informations forums :
    Inscription : Février 2009
    Messages : 200
    Points : 235
    Points
    235
    Par défaut
    (Désolé de défoncer les portes ouvertes

    Les instructions enter/leave, indiquées par Obsidian, sont typiques des concessions faites aux HLL de type C et sont prévues pour faciliter l'interfaçage entre HLL et assembleur.

    Pour ton cadre de pile, les règles sont simples:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
     
    PUSH EBP
    MOV EBP ESP
     
       Lp argument1 = EBP+04
       Lp argument2 = EBP+08 
    MOV ESP EBP
    POP EBP
     
    RET NombreArguments*4 (4 pour 4 bytes -> DWORD)
    Toutes les remarques faites par Obsidian sont valides et pertinentes: Elles t'éviteront bien des surprises et des incompréhensions liées à la constatation de phénomènes erratiques en tout genres.

  9. #9
    Membre confirmé
    Inscrit en
    Juillet 2005
    Messages
    512
    Détails du profil
    Informations forums :
    Inscription : Juillet 2005
    Messages : 512
    Points : 641
    Points
    641
    Par défaut
    Je sais comment on monte un cadre de pile, ce n'était pas le sujet de la question ?
    la sortie d'une fonction en appel C est RET tout court. C'est la fonction appelante qui retire les paramètres.

    Toutes les remarques faites par Obsidian sont valides et pertinentes
    Oui elle sont valide, mais ne reponde pas à ma question.

    D'abord, ton pointeur de pile évolue au cours de la fonction.
    ça j'ai répondu, C'est moi qui écrit la fonction. je sais si ESP change ou pas!

    Ensuite, les langages de haut niveau sont suceptibles de mettre fin prématurément à ta fonction, à n'importe quel moment. Ça peut arriver si le programmeur à mis un « return » en plein milieu.
    Là faut m'expliquer comment tu fait pour mettre un return au milieu de ma fonction.
    Je ne vois pas par quelle artifice un langage peut mettre fin à une fonction qu'il n'a pas compilé.

  10. #10
    Membre actif

    Inscrit en
    Février 2009
    Messages
    200
    Détails du profil
    Informations forums :
    Inscription : Février 2009
    Messages : 200
    Points : 235
    Points
    235
    Par défaut
    Est-ce que de l'adressage de base avec ESP existe (?)
    - Oui

    doit-on passer par les registres EBX, EBP ?
    - Non

    Puisque tu sais déjà tout-ça, pourquoi le demandes-tu ?

    Ou: Si tu pouvais indiquer la réponse que tu attends, à Obsidian (par exemple), cela permettrait à un plus grand nombre de te la fournir...

    Est-ce juste un prétexte pour te permettre d'être désagréable ? (je n'ai rien contre remarques bien, il faut que certaines frustrations soit évacuées d'une manière ou d'une autre selon les moyens de chacun et le côté bouffon m'amuse toujours )

  11. #11
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Septembre 2007
    Messages
    7 372
    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 372
    Points : 23 628
    Points
    23 628
    Par défaut
    Citation Envoyé par Lucien63 Voir le message
    Oui elle sont valide, mais ne reponde pas à ma question.
    Alors, pour mettre fin au suspens, oui, l'adressage basé sur le pointeur de pile, ça se fait (j'ai déssassemblé et commenté quelques programmes qui le faisaient) mais ça reste compliqué.

    J'ai répondu à ta question. Je t'ai cité le cas où l'usage de la pile interne à une fonction nécessite un registre pour en suivre la trace, ce qui fait qu'il devient plus simple d'utiliser ce même registre pour sauvegarder l'état initial de la pile.

    Ensuite, utiliser le mode indexé pour retrouver l'adresse de départ n'est pas plus efficace que d'utiliser un registre du processeur, qui reste de loin la ressource la plus rapide. Faire un accès bus à la fin de chaque fonction pour aller lire une constante sur trente-deux bits n'est pas meilleur que d'utiliser EBP. C'est plus long en temps et c'est quatre ou cinq octets plus grand. Si tu as des ressources, c'est idiot de ne pas les exploiter.

    Ça, c'est pour les langages de haut niveau. Si tu écris directement en assembleur, tu peux utiliser ESP mais à ce moment, il faut que tu suives toi-même et sur papier toute l'évolution de ta pile sans te tromper, et que tu fasses les adaptations à la volée. Bon courage.

    Autrement, ça ne t'apporte rien de plus de t'en tenir à ESP si tu disposes d'un autre registre. Ces arguments justifient déjà son utilisation, à mon avis, mais la raison la plus importante est encore à venir :

    Là faut m'expliquer comment tu fait pour mettre un return au milieu de ma fonction.
    Chaque fois que tu ouvres un bloc, tu descends d'un niveau dans la pile (ce qui te permet accessoirement d'y déclarer des variables locales). Ce n'est pas propre aux corps de fonction. Quand tu fais :

    Code C : 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
    int fonction (int x,int y)
    {
         if (x>1)
         {
             char v;
     
            if (y>1)
            {
                FILE * f;
     
                f = fopen ("fichier","r");
     
                if (f==NULL)
                {
                    fprintf (stderr,"Echec ouverture\n");
                    return -1;
                }
            }
         }
    }

    ... ton return quitte la fonction et remonte donc quatre niveaux d'imbrication. Cependant, à ce stade, le compilo sait encore s'y retrouver, et il n'ouvre pas forcément un cadre de pile pour chaque bloc.

    D'autre part, quoi que l'on en pense, le goto existe toujours en C, et permet d'atteindre directement le bas de la fonction si on le souhaite. C'est pratique, quand on sait s'en servir, pour mettre justement en place des mécanismes s'apparentant aux exceptions. Quand tu en es là, tu ne sais pas où en était ta pile.

    Mais la raison la plus importante pour moi est la suivante : la pile des appels, dont l'utilité principale se révèle avec le déboguage.

    Lorsque tu utilises ton débugger, celui-ci te donne la pile des appels de fonction, depuis celle où le programme se trouve ou a planté, en remontant jusqu'à main(). Ça, ce n'est possible que parce que les cadres de pile se font successivement référence et forment une liste chaînée qui peut être remontée. C'est peut-être là que se trouve le principal argument en défaveur d'un usage direct du pointeur de pile : il est dépendant de ce qui se passe au runtime et tu es obligé de laisser le programme se terminer pour retomber sur tes pattes.

    Tu peux demander à ton compilateur d'omettre volontairement les pointeurs de cadre de pile à l'aide d'options explicites. Pour gcc, c'est le fameux -fomit-frame-pointer.

    Essaie de compiler ton programme sans les symboles de déboguage et de provoquer volontairement une segfault dans une fonction au cinquième ou sixième niveau d'imbrication. Avec les cadres de pile, tu retrouves l'adresse de début de toutes les fonctions. Sans ces pointeurs, tu te retrouves au début de ton programme.

    C'est également très important pour les outils de profilage, car c'est avec eux qu'ils pourront tenir les statistiques des appels de fonctions.

    On a vu également que c'était important également pour les langages de haut niveau autres que le C, et pour tout outil d'exploration externe qui, lui, étudie le programme objet indépendament du langage source.

    Je ne vois pas par quelle artifice un langage peut mettre fin à une fonction qu'il n'a pas compilé.
    Un signal en provenance du système d'exploitation, tel que Abort, par exemple. Bon, sous Unix, c'est un signal comme un autre, et il est de ceux qui, en principe, provoquent la terminaison du processus. Mais dans d'autres cas, celui-ci peut être interprété à juste titre comme une exception, et nécessiter la remontée d'urgence de la pile des appels jusqu'à un point précis, plutôt que tout en haut du processus.

    À contrario, virer les cadres de pile est surtout intéressant en C, mais n'est pas toujours possible.

    Enfin, qu'est-ce que ça t'apporte ? Un peu de gain de place au niveau du cadre, (sensible quand il y a beaucoup d'appels de fonctions), rien du tout au niveau du référencement des variables locales et de la gestion de la pile, ni en temps ni en place.


    À noter comme décrit précédement que l'usage de EBP est indépendant de celui des cadres de pile. Il n'empêche que ce que l'on a dit demeure.

  12. #12
    Membre actif

    Inscrit en
    Février 2009
    Messages
    200
    Détails du profil
    Informations forums :
    Inscription : Février 2009
    Messages : 200
    Points : 235
    Points
    235
    Par défaut
    Bel effort de limpidité, bravo !

  13. #13
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Septembre 2007
    Messages
    7 372
    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 372
    Points : 23 628
    Points
    23 628
    Par défaut
    Citation Envoyé par Rémi Coquet Voir le message
    Bel effort de limpidité, bravo !
    Merci.

  14. #14
    Membre confirmé
    Inscrit en
    Juillet 2005
    Messages
    512
    Détails du profil
    Informations forums :
    Inscription : Juillet 2005
    Messages : 512
    Points : 641
    Points
    641
    Par défaut
    J'en deduis que ce n'est pas interdit mais pas conseillé.

    Merci pour ton exposé sur le sujet.

Discussions similaires

  1. [msde]Exportation de base avec msde..vers Hébergeur.
    Par didoboy dans le forum MS SQL Server
    Réponses: 5
    Dernier message: 30/03/2004, 17h11
  2. [SGBD] Pour moyenne base avec SQL ?
    Par PyRoFlo dans le forum Bases de données
    Réponses: 10
    Dernier message: 13/03/2004, 18h54
  3. Exportation de base avec ASP sous OUTLOOK
    Par M1000 dans le forum ASP
    Réponses: 6
    Dernier message: 04/03/2004, 09h52
  4. Création d'une base avec IbConsole
    Par Lucien dans le forum Outils
    Réponses: 3
    Dernier message: 02/03/2004, 18h34
  5. base avec nom des pays
    Par jack-daniel dans le forum Requêtes
    Réponses: 2
    Dernier message: 08/07/2003, 14h16

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