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

Assembleur Discussion :

Compréhension du code


Sujet :

Assembleur

  1. #1
    Nouveau Candidat au Club
    Profil pro
    Inscrit en
    Mai 2006
    Messages
    2
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Mai 2006
    Messages : 2
    Points : 1
    Points
    1
    Par défaut Compréhension du code
    Dans le cadre d'un cours d'informatique, il nous est demandé de "comprendre" du code assembleur "ligne par ligne". Ce code est généré par gcc -S -mpreferred-stack-boundary=2 prog.c. Nous possédons donc le code de base, et l'assembleur est celui généré automatiquement par la commande "gcc -s".

    Le code de base est par exemple:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    int sayhello(){
      return printf("Hello World\n");
    }
    int main() {
      int i = 0;
      i = sayhello();
      printf("result %i\n", i);
    }
    Ce code que l'on compile comme je l'ai expliqué plus tot donne le résultat suivant en assembleur... Seulement notre cours ne nous permet absolument pas de comprendre ce code, et c'est là que j'ai besoin de votre aide! Comment analyseriez vous ce code??

    Voici le code assembleur:
    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
     
    	.file	"programme1.c"
    	.section	.rodata
    .LC0:
    	.string	"Hello World\n"
    	.text
    .globl sayhello
    	.type	sayhello, @function
    sayhello:
    	pushl	%ebp
    	movl	%esp, %ebp
    	subl	$4, %esp
    	movl	$.LC0, (%esp)
    	call	printf
    	leave
    	ret
    	.size	sayhello, .-sayhello
    	.section	.rodata
    .LC1:
    	.string	"result %i\n"
    	.text
    .globl main
    	.type	main, @function
    main:
    	pushl	%ebp
    	movl	%esp, %ebp
    	subl	$12, %esp
    	movl	$0, -4(%ebp)
    	call	sayhello
    	movl	%eax, -4(%ebp)
    	movl	-4(%ebp), %eax
    	movl	%eax, 4(%esp)
    	movl	$.LC1, (%esp)
    	call	printf
    	leave
    	ret
    	.size	main, .-main
    	.ident	"GCC: (GNU) 4.0.3 (Ubuntu 4.0.3-1ubuntu5)"
    	.section	.note.GNU-stack,"",@progbits
    ----------
    Merci d'avance



    Modération par Eric Sigoillot
    Merci d'utiliser les balises [code]

  2. #2
    Membre éclairé

    Inscrit en
    Juin 2004
    Messages
    1 397
    Détails du profil
    Informations forums :
    Inscription : Juin 2004
    Messages : 1 397
    Points : 763
    Points
    763
    Par défaut
    C'est pourtant pas sorcier...
    Il n'y a pas grand chose. Regarde la fonction main(), dans ton C.
    Elle initialise i à 0, puis appelle la fonction sayhello() et imprime i.

    Dans ton code asm, la même fonction place 0 sur la pile :
    appelle la fonction sayhello via le call puis écrase la valeur de i stockée sur la pile, avant de la prendre et de la passer à printf.

    Avec ça, et en voyant que .L0 c'est ton "Hello World", tu dois retrouver tes petits. Après, c'est le mécanisme de la pile qui peut être déroutant.
    Aucune réponse à une question technique par MP.
    Ce qui vous pose problème peut poser problème à un(e) autre

    http://thebrutace.labrute.fr

  3. #3
    Nouveau Candidat au Club
    Profil pro
    Inscrit en
    Mai 2006
    Messages
    2
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Mai 2006
    Messages : 2
    Points : 1
    Points
    1
    Par défaut
    Citation Envoyé par progfou
    Après, c'est le mécanisme de la pile qui peut être déroutant.
    Je sais que je suis terriblement chiant, mais j'ai examen mercredi, tu sais pas développer un tout petit peu plus ce mécanisme qui, pour moi, est effectivement assez déroutant!

    Merci d'avance et deja merci merci pour le début d'explication...

  4. #4
    Membre éprouvé
    Avatar de Celelibi
    Profil pro
    Inscrit en
    Janvier 2004
    Messages
    1 087
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2004
    Messages : 1 087
    Points : 1 122
    Points
    1 122
    Par défaut
    Pour commencer il faut savoir à quoi servent les registres esp et ebp.
    ebp indique la base de la pile, et esp indique le sommet de la pile.

    Maintenant reprenons le code asm.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    	pushl	%ebp
    	movl	%esp, %ebp
    On trouve presque toujours ces deux lignes au début des procédures/fonctions.
    Elles permettent de créer une nouvelles pile au dessus de l'ancienne. On pousse sur la pile (l'ancienne) la valeur de ebp, puis le sommet de l'ancienne pile devient la base de la nouvelle.
    On soustrait 12 à esp. esp va donc pointer 12 octets plus haut que ebp. Donc en fait on laisse 8 octets libres sur la pile. C'est comme ça que gcc (et sûrement d'autres compilateurs) réserve la mémoire pour les variables locales.
    À l'adresse ebp-4 tu as ta variable i. Sachant qu'un int fait 4 octets, on peut dire que les 4 octets les plus bas sur la pile de main sont réservés à la variable i.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    	call	sayhello
    	movl	%eax, -4(%ebp)
    Là bon le call est assez parlant, mais il faut quand même savoir que la valeur de retour est placée dans eax. C'est donc pour ça qu'on place la valeur de eax dans la mémoire à l'adresse ebp-4 (ce qui corresspond à la variable i).
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    	movl	-4(%ebp), %eax
    	movl	%eax, 4(%esp)
    	movl	$.LC1, (%esp)
    La première ligne sert juste à recharger dans eax la valeur de i (si on compile sans optimiser, gcc ne se rend pas compte que forcément il y a déjà dans eax la valeur de ebp-4).
    La deuxième ligne sert à mettre la valeur de eax (donc i) au dessus de la pile courante, ce qui corresspondra sûrement à la prochaine pile créée.
    Et la troisième ligne met l'adresse de la chaine "result %i\n" juste au sommet de la pile.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    	call	printf
    	leave
    	ret
    On appel printf, qui va bien évidemment se servir des deux valeurs qui ont été mises au dessus de la pile actuelle.


    Maintenant la procédure sayhello.
    Les deux premières lignes fonctionnent comme tout à l'heure.
    On laisse 0 octets libres sur la pile.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    	movl	$.LC0, (%esp)
    	call	printf
    C'est le même méchanisme que tout à l'heure. On met au dessus de la pile (qui sera la base de la pile de printf) l'adresse de la chaine "Hello World\n", puis on appel printf. Et la valeur de retour de printf sera mises dans eax.

    Si c'est toujours pas trop clair, il faut dessiner l'organisation mémoire.


    Mais bon, je suis pas trop sûr qu'il laisse 8 et 0 octets (au lieu de 12 et 4) sur les piles de main et sayhello.


    En espérant t'avoir un peu éclairé.
    Les vaches ne peuvent PAS voler, quoi qu'elles aient pu vous raconter.

Discussions similaires

  1. problème de compréhension de code
    Par condor_01 dans le forum C
    Réponses: 5
    Dernier message: 26/09/2007, 12h17
  2. compréhension de code en asp
    Par bidule123456 dans le forum ASP
    Réponses: 1
    Dernier message: 21/08/2007, 11h12
  3. compréhension de code (passage à une autre page)
    Par kokokaine dans le forum Général JavaScript
    Réponses: 4
    Dernier message: 04/05/2007, 11h02
  4. Réponses: 3
    Dernier message: 12/01/2007, 09h42
  5. [VB-Access]recset! Pb de compréhension de code
    Par sk8bcn dans le forum VBA Access
    Réponses: 5
    Dernier message: 15/12/2006, 15h26

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