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 :

[NASM / Linux][Débutant] Segmentation fault affichage avec printf


Sujet :

x86 32-bits / 64-bits Assembleur

  1. #1
    Membre du Club Avatar de donkeyquote
    Profil pro
    Inscrit en
    Septembre 2007
    Messages
    195
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2007
    Messages : 195
    Points : 52
    Points
    52
    Par défaut [NASM / Linux][Débutant] Segmentation fault affichage avec printf
    Salut,

    J'essaie de faire afficher la somme de deux entiers de la facon suivante :

    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
     
    ;importing exter C symbol
    extern printf
     
    ;declaring variables
    segment .data
    ;variable1 takes 1 as a value
    value1: db 1h	; value1 is BYTE containing the hexa 1
    value2: db 2h	; value2 is BYTE containing the hexa 2	
     
    ;entry point for main function
    global main
    ;start assembly program
    section .text
     
    ;coding the _main symbol
    main:
     
    ;put the value of the value1 variable into the EAX registre
    mov EAX, value1
     
    ;add the value of value2 variable into the EAX restre
    add EAX, value2
     
    ;pushing the value1 variable on the stack
    push EAX
     
    ;calling the _printf C function
    call printf
     
    ;cleaning the stack by unstacking the hello variable on the EAX register
    pop EAX
     
    ;exiting from _main symbol
    ret
    Je travaille sous linux.

    Quand j'execute je me prends un segmentation fault

    Pourquoi ? Comment faire l'affichage des registres avec printf ?

  2. #2
    Membre confirmé Avatar de dapounet
    Profil pro
    Étudiant
    Inscrit en
    Juillet 2007
    Messages
    469
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juillet 2007
    Messages : 469
    Points : 567
    Points
    567
    Par défaut
    Tout d'abord tu ne stockes pas dans EAX ce que tu crois. Quand NASM rencontre le nom d'une variable, il la remplace par son adresse. Pour faire un accès mémoire, il faut mettre entre crochets l'adresse à laquelle tu veux accéder.
    Donc pour avoir la valeur de value1, il faut écrire [value1].

    Pour afficher un entier avec printf(), il faut faire quelque chose de ce genre :
    Il y a deux arguments, l'int à afficher et la chaîne de format. En assembleur il faut d'abord mettre sur la pile celui tout à droite, puis celui à sa gauche, etc.

    Voilà un exemple de code final. J'ai utilisé des variables de 32 bits pour que ce soit plus facile (avec des octets il faudrait utiliser MOVZX ou MOVSX pour les copier dans EAX).

    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
    extern printf
    global main
     
    segment .data
    value1 dd 1h
    value2 dd 2h
    format_d db '%d', 10, 0
     
    section .text
    main:
      mov EAX, [value1]
      add EAX, [value2]
      push EAX
      push format_d
      call printf
      pop EAX
      pop eax
     
      ret
    :wq

  3. #3
    Membre du Club Avatar de donkeyquote
    Profil pro
    Inscrit en
    Septembre 2007
    Messages
    195
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2007
    Messages : 195
    Points : 52
    Points
    52
    Par défaut
    Plus j'avance dans le sujet, plus je me pose des questions...

    1) A quoi ca sert l'instruction "pop"? c'est l'equivalent d'un "delete" ?

    2) Pourquoi faire deux "pop" sur EAX ?

    3) Pourquoi on ne fait pas mov [EAX], [value1] au lieu de EAX, [value1]. Est-ce que EAX ne represente pas une adresse et pas une valeur ?

  4. #4
    Membre confirmé Avatar de dapounet
    Profil pro
    Étudiant
    Inscrit en
    Juillet 2007
    Messages
    469
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juillet 2007
    Messages : 469
    Points : 567
    Points
    567
    Par défaut
    Je te conseille de lire le tutoriel de Paul Carter que j'ai linké dans l'autre topic, à mon avis c'est le meilleur.

    Citation Envoyé par donkeyquote Voir le message
    1) A quoi ca sert l'instruction "pop"? c'est l'equivalent d'un "delete" ?
    C'est l'inverse d'un PUSH. Avec un PUSH tu mets une valeur sur la pile, avec un POP tu récupères la dernière valeur que tu as mise.

    Citation Envoyé par donkeyquote Voir le message
    2) Pourquoi faire deux "pop" sur EAX ?
    printf() s'attend à trouver ses arguments sur la pile, dans un certain ordre. Une fois qu'elle a terminé son travail elle retourne à l'appelant en laissant la pile telle quelle. Puisque les arguments ne servent plus à rien, autant les enlever de la pile. Tu peux le faire en POPant chaque DWORD que tu as mis juste avant, ou avec une seule instruction add esp, nn est le nombre d'octets à déblayer de la pile.
    En fait toutes les fonctions ne laissent pas traîner leurs arguments sur la pile, mais celles du C le font.

    Citation Envoyé par donkeyquote Voir le message
    3) Pourquoi on ne fait pas mov [EAX], [value1] au lieu de EAX, [value1]. Est-ce que EAX ne represente pas une adresse et pas une valeur ?
    EAX est le nom d'un registre, une zone de stockage très rapide d'accès à l'intérieur du processeur. Les registres n'ont pas d'adresse. Étant donné qu'on ne fait pas d'accès mémoire quand on utilise un registre, ça paraît logique de ne pas utiliser [].
    :wq

  5. #5
    Membre du Club Avatar de donkeyquote
    Profil pro
    Inscrit en
    Septembre 2007
    Messages
    195
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2007
    Messages : 195
    Points : 52
    Points
    52
    Par défaut
    J'ai commence a lire ton manuel et j'ai commence a faire quelques examples.
    Et donc de plus en plus de doutes...

    Maintenant je ne comprend pas pourquoi le code suivant ne m'affiche pas la valeur 4 alors que la valeur de EAX apres la valeur de EAX devrait etre 3 apres le troisieme "pop":

    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
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
     
    ;importing exter C symbol
    extern printf
     
    ;declaring variables
    segment .data
    ;variable1 takes 1 as a value
    value1: dd 1h	; value1 is 32 Bits containing the hexa 1
    value2: dd 2h	; value2 is 32 Bits containing the hexa 2
    message_add: db 'Addition Result:', 10, 0
    message_inc: db 'Increase one unit:', 10, 0
    format_d: db '%d', 10, 0   ; "%d\n" to call printf("%d\n", eax);
     
     
    ;entry point for main function
    global main
    ;start assembly program
    section .text
     
    ;coding the _main symbol
    main:
     
    ;pushing the message_add on the stack
    push message_add
     
    ;calling the printf in order to display the add message
    call printf
     
    ;taking the EAX off
    pop EAX
     
    ;put the value of the value1 variable into the EAX registre
    mov EAX, [value1]
     
    ;add the value of value2 variable into the EAX restre
    add EAX, [value2]
     
    ;pushing the EAX value on the stack
    push EAX
     
    ;pushing the value1 variable on the stack
    push format_d
     
    ;calling the _printf C function
    call printf
     
    ;cleaning up the stack by unstacking the hello variable on the EAX register
    pop EAX ;gets the '%d', 10, 0 value out
    pop EAX ;gets the 3 value out
     
     
    ;****************
    mov EBX, message_inc
     
    ;push message_inc on the stack
    push EBX
     
    ;call the printf C function
    call printf
     
    ;cleaning up the stack
    pop EBX
    ;****************
     
    ;put the value of the value1 variable into the EAX registre
    mov EAX, [value1]
     
    ;add the value of value2 variable into the EAX restre
    add EAX, [value2]
     
    ;increase the EAX one unit: EAX++
    inc EAX
     
    ;push the incremented number on the stack
    push EAX
     
    ;push the format string on the stack
    push format_d
     
    ;call the printf C function
    call printf
     
    ;cleaning up the stack
    pop EAX
    pop EAX
     
    ;exiting from _main symbol
    ret

Discussions similaires

  1. Réponses: 5
    Dernier message: 23/12/2009, 11h31
  2. la précision d'affichage avec printf
    Par mony84 dans le forum Bibliothèque standard
    Réponses: 2
    Dernier message: 13/09/2008, 00h29
  3. [Débutant] pb affichage du "\" avec printf
    Par jocelyn54 dans le forum Bibliothèque standard
    Réponses: 5
    Dernier message: 24/01/2008, 11h02
  4. [Lex/Yacc][Débutant] Segmentation fault
    Par exhortae dans le forum Générateurs de compilateur
    Réponses: 0
    Dernier message: 20/12/2007, 23h00
  5. problème d'affichage avec printf
    Par sorari dans le forum C++
    Réponses: 12
    Dernier message: 08/03/2005, 18h30

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