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 :

Question sur le prologue du main et ce qu'il se passe après l'épilogue du main


Sujet :

x86 32-bits / 64-bits Assembleur

  1. #1
    Membre régulier
    Profil pro
    Inscrit en
    Janvier 2006
    Messages
    150
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2006
    Messages : 150
    Points : 111
    Points
    111
    Par défaut Question sur le prologue du main et ce qu'il se passe après l'épilogue du main
    Bonjour,

    Première question, je me demandais où pointait $eip lorsqu'on arrive à la fin de la fonction main (ret).


    Il y a quelque chose qui me chagrine avec gcc, je ne comprend pas pourquoi lorsque je compile une simple source ( int main(){} ) avec gcc sous une debiane j'obtiens :

    version gcc 4.0.4 20060507 (Debian 4.0.3-3)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    ;prologue
    push   %ebp
    mov    %esp,%ebp
     
    ;épilogue
    pop    %ebp
    ret
    alors que sous fedora core, j'obtiens pour le même code un truc plus compliqué avec des instructions vraiment inutiles mais qui au final revient à exactement à la même chose :

    gcc 4.1.1 20060525 (Red Hat 4.1.1-1)
    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
    35
    36
    37
    38
    39
    40
    41
    42
    43
    ;prologue
    
    0x08048354 <main+0>:    lea    0x4(%esp),%ecx 
    ;on sauvegarder l'addresse de la pile + 4 (correspond à l'adresse de retour theoriquement)
    
    0x08048358 <main+4>:    and    $0xfffffff0,%esp 
    
    ;on reserve un espace (entre 0 et 16 octets) dans la pile
    ;alignement de la pile ?
    
    0x0804835b <main+7>:    pushl  0xfffffffc(%ecx) 
    ; on empile ecx - 4 soit l'adresse la pile a la base
    ; cette valeur n'est même pas dépilé dans l'epilogue
    
    0x0804835e <main+10>:   push   %ebp             
     ;sauvegarde du pointeur de frame
    
    0x0804835f <main+11>:   mov    %esp,%ebp      
    ;nouveau pointeur de pile
    
    0x08048361 <main+13>:   push   %ecx              
    ;on empile ecx (contient donc ancien adresse esp + 4)
    
    
    [le corp de la fonction]
    
    ;épilogue
    
    0x08048362 <main+14>:   pop    %ecx               
    ; (qui contient ancienne adresse esp + 4)              
    
    0x08048363 <main+15>:   pop    %ebp
    ; on réstaure le pointeur de frame
    
    0x08048364 <main+16>:   lea    0xfffffffc(%ecx),%esp
    ; esp <- ecx-4 soit la l'ancienne valeur de esp
    ; 
    ; là je me demande alors l'utilité de l'instruction du prologue : 0x0804835b <main+7>:    pushl  0xfffffffc(%ecx) 
    ; => équivalent de leave
    
    0x08048367 <main+19>:   ret
    ; eip restauré
    Pourquoi faire :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    0x08048354 <main+0>:    lea    0x4(%esp),%ecx
    0x08048358 <main+4>:    and    $0xfffffff0,%esp
    0x0804835b <main+7>:    pushl  0xfffffffc(%ecx)
    alors qu'on peut aussi simplement faire(ou alors peut etre que je ne comprend pas du tout la syntaxe AT&T, mais je crois bien que c'est équivalent) :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    0x08048354 <main+0>:    mov    %esp,%ecx
    0x08048358 <main+4>:    and    $0xfffffff0,%esp
    0x0804835b <main+7>:    pushl  %ecx

  2. #2
    Membre actif

    Profil pro
    Inscrit en
    Octobre 2005
    Messages
    193
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2005
    Messages : 193
    Points : 277
    Points
    277
    Par défaut
    Salut,
    pour la premiere question,après le ret,eip ( le pointeur d'instructions) pointe juste après le call.Le call stocke l'adresse de retour en pile,et le ret réaffecte cette valeur a eip.
    Pour le reste,c'est ce qu'on appelle le "stack frame" en anglais.Faire une recherche avec google sur ces mots.
    En français ,on peut appeler ça le "cadre de la pile" ou la structure d'un appel de programme.
    Ces structures d'appels sont normalisés et optimisées.
    Standard call,c call,interface call ..... ont toutes de petites différences dans la manière de revenir au point d'appel et/ou des différences dans le passage de paramètres.
    Pour en faire une critique,mieux vaut savoir ce que l'on attend comme résultat et comment on utilise les librairies.
    ToutEnMasm

Discussions similaires

  1. Question sur le main
    Par Invité dans le forum SDL
    Réponses: 3
    Dernier message: 18/07/2007, 23h26
  2. question sur le main
    Par scolopendra dans le forum Langage
    Réponses: 3
    Dernier message: 10/05/2007, 12h49
  3. Question sur les handles et les couleurs...
    Par MrDuChnok dans le forum C++Builder
    Réponses: 7
    Dernier message: 29/10/2002, 09h45
  4. Réponses: 2
    Dernier message: 11/08/2002, 22h27
  5. question sur les message box !
    Par krown dans le forum Langage
    Réponses: 7
    Dernier message: 02/08/2002, 17h11

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