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 :

[Débutant] Inversion d'une chaîne


Sujet :

x86 32-bits / 64-bits Assembleur

  1. #1
    Nouveau membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Août 2015
    Messages
    14
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 28
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Août 2015
    Messages : 14
    Points : 26
    Points
    26
    Par défaut [Débutant] Inversion d'une chaîne
    Salut !

    Je débute en assembleur x86, et je bute un peu sur un exercice : je veux inverser une chaîne de caractères mais j'obtiens une segfault que je n'arrive pas à résoudre. Je suppose que mon erreur est relative avec la gestion de la pile mais je ne la comprends pas. Voilà mon programme :

    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
    segment .code
    global _start
    _start:
     
    	call push_chaine		;met 0 suivi de mesg sur le haut de la pile
    	call pop_chaine			;récupère la chaine
    	mov ecx, mesg		
    	mov eax, 4				;syscall 4 = stdout(ecx)
        mov ebx, 1		
        mov edx, size
        int 80h					;stdout mesg
    	mov	eax,1				;Interruption linux
    	mov	ebx,0				;pour quitter
    	int	80h					;le proggrame
     
    push_chaine:
    	push word 0				;0 = fin de la chaine
    	lea eax, [mesg]
    	boucle:
    	mov eax, ecx			;on stocke eax dans ecx
    	push eax				
    	inc eax					;on passe au caractere suivant
    	or ecx, ecx				;on vérifie si c'était le dernier caractère
    	jnz boucle				
    	pop eax					
    	lea eax, [mesg]			;on stocke le ptr sur la chaine
    	ret
    pop_chaine:
    	pop ecx					
    	mov [eax], ecx			;stockage du caractère courant
    	inc eax
    	or ecx, ecx
    	jnz pop_chaine
    	ret
     
    section .data
    Merci d'avance de votre aide

  2. #2
    Invité
    Invité(e)
    Par défaut
    Bon je suppose que tu fait du nasm.

    Alors je te conseille de lire sa doc: http://www.nasm.us/docs.php

    Bon je ne suis clairement pas un fan de push et pop, alors si c'est en série en plus avec ton push sans pop dans une même boucle, ou non avec qu'un pop après la boucle, malgré que ta boucle à du faire X boucles * nbr_char.
    Enfin je vois que tu as une fonction pop_chaine qui fait l'inverse de push_chaine, mais bon apparemment tous ces push et pop ne sont pas super synchro vu que tu as un segfault, enfin essaye d'enlever tous ces push et pop pour voir si cela marché déjà.

    Bref je n'aime pas les push/pop, mais d'après ce que j'en ai conclu, ton esp (push) alloue beaucoup plus de mémoire que tu n'en libères (pop)

    Après tu as déjà essayer la technique du petit poucet ? (je sais drôle de nom que j'ai inventé )

    En gros elle est simple, tu parcours ton code en y mettant une pause (boucle infinie) après chaque ligne/bloc de codes pour isoler ton code qui pose problème.

    Normalement je ne lis pas ce genre de code, non formaté, après des milliers de lectures de codes asm, je peux te dire qu'à la fin tu as une forte envie de normaliser tout ça

    Mais bon ça peut aller, le code est petit.

    Et ne pas confondre le AT&T et l'intel:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    mov     eax, ecx        ;on stocke eax dans ecx
    C'est plutôt on stocke la valeur de ecx dans le registre eax.
    Dernière modification par Invité ; 16/09/2015 à 12h47.

  3. #3
    Nouveau membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Août 2015
    Messages
    14
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 28
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Août 2015
    Messages : 14
    Points : 26
    Points
    26
    Par défaut
    Pourquoi l'utilisation de pop et push n'est pas recommandée ? Il vaut mieux modifier la pile via esp puis modifier sa valeur ? J'en profite pour poser une question, j'ai du mal à saisir la nuance précise entre esp et ebp, j'ai trouvé quelques réponses mais elles ne m'ont pas vraiment éclairé.

    Pour le formatage du code, ce sont les deux lignes qui sont décalées qui posent problème c'est ça ? Si oui j'en suis désolé, c'est survenu après le c/c du code.

    Merci pour la doc de nasm, j'avoue que j'ai pas trop osé plonger dedans pour le moment, je me disais que le cours de Paul carter et un bouquin suffiraient pour l'instant, mais je vais me pencher dessus.

  4. #4
    Invité
    Invité(e)
    Par défaut
    Pourquoi déconseiller ? parce que c'est moche, voilà tout

    Je veux bien que l'on invente des macros/instructions pour automatiser certaines taches répétitives, mais bon, il y a toujours ce juste milieu à trouver ^^

    Et pour beaucoup apparemment, ils n'aiment pas beaucoup push et pop.


    Enfin la vraie raison du pourquoi c'est moche, c'est aussi parce qu'il ne faut pas rater son coup, push et pop sont comme des âmes soeurs, l'un ne peut pas vivre sans l'autre, ou du moins tu peux mélanger un compléter un push avec un sub et un pop avec un add, mais cela devient tordu comme logique de programmation.

    Sinon push/pop ne sont pas dispo en x64.


    ebp pour ma part est d'une inutilité, mais affligeante, cela évite de faire un add de esp à la fin de la déclaration de la pile ou autre chose mais osef, sert toi en avec autre chose plutôt que de pointer systématiquement ebp vers le haut de la pile.

    Citation Envoyé par Abdoulito Voir le message
    Merci pour la doc de nasm, j'avoue que j'ai pas trop osé plonger dedans pour le moment, je me disais que le cours de Paul carter et un bouquin suffiraient pour l'instant, mais je vais me pencher dessus.
    Np, moi aussi j'ai beaucoup hésiter, tellement hésiter qu'il m'a fallu 2 ans avant de me convaincre d'aller me jeter à l'eau dans ces docs (docs intel aussi), mais même maintenant j'ai la trouille d'aller les lire de A à Z pour bien comprendre des conceptes

  5. #5
    Nouveau membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Août 2015
    Messages
    14
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 28
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Août 2015
    Messages : 14
    Points : 26
    Points
    26
    Par défaut
    D'accord ! Je vais essayer de faire sans alors, de toute façon je suppose que c'est le meilleur moyen de savoir ce qu'il se passe en mémoire dans un premier temps. Mais bon je suis un peu déçu, ça m'explique pas le pourquoi du comment c'est nul

  6. #6
    Invité
    Invité(e)
    Par défaut
    Les impressions jouent beaucoup sur la façon de coder aussi et c'est ça qui fait aussi la magie de la programmation ^^
    Dernière modification par Invité ; 16/09/2015 à 19h55.

  7. #7
    Nouveau membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Août 2015
    Messages
    14
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 28
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Août 2015
    Messages : 14
    Points : 26
    Points
    26
    Par défaut
    C'est vrai. Merci en tout cas je vais essayer de mettre ça en application

  8. #8
    Responsable Systèmes


    Homme Profil pro
    Gestion de parcs informatique
    Inscrit en
    Août 2011
    Messages
    17 347
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Gestion de parcs informatique
    Secteur : High Tech - Matériel informatique

    Informations forums :
    Inscription : Août 2011
    Messages : 17 347
    Points : 42 814
    Points
    42 814
    Par défaut
    Sinon push/pop ne sont pas dispo en x64.
    Ah bon ? Je savais pas. Même pas push rax ?


    Abdoulito, push et pop sont souvent utilisés avant un call notamment sous Windows. Exemple : avant d'appeler une fonction, tu va empiler ses paramètres (les stocker dans la pile, un peu comme une pile d'assiettes). Le principe est qu'il faut autant empiler que dépiler ni plus ni moins sinon tu va écraser ta pile et le soft en cours va planter.Je n'ai pas lu le code, mais comme le signale shaynox, si tu as des boucles imbriqués qui ne font pas les empilements/dépilements correctement : crash ...

    push eax est équivalent à :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    mov [esp],eax
    sub esp,4
    En gros tu mets la valeur de eax à l'adresse contenu dans esp, tu diminue ensuite celle-ci de 4 octets eax=32 bits=4 octets. L'adresse de la pile diminue au fur et à mesure que tu empiles des choses.

    ebp est souvent utilisé pour sauvegardé provisoirement une pile, notamment par les prologues des fonctions C.

    Exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    push ebp
    mov ebp,esp
    sub esp,16  //reservation 16 octets
    mov esp,ebp
    pop ebp
    Cela s’appelle le stack frame :

    Les fonctions push pop modifient la valeur de esp tout comme call et ret. Le stack Frame permet de sauvegarder temporairement le registre esp


    Shaynox merci de vérifier, je fais plus d’assembleur depuis longtemps
    push_chaine pop_chaine servent à quoi ? à calculer la taille de la chaine ?
    Ma page sur developpez.com : http://chrtophe.developpez.com/ (avec mes articles)
    Mon article sur le P2V, mon article sur le cloud
    Consultez nos FAQ : Windows, Linux, Virtualisation

  9. #9
    Responsable Systèmes


    Homme Profil pro
    Gestion de parcs informatique
    Inscrit en
    Août 2011
    Messages
    17 347
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Gestion de parcs informatique
    Secteur : High Tech - Matériel informatique

    Informations forums :
    Inscription : Août 2011
    Messages : 17 347
    Points : 42 814
    Points
    42 814
    Par défaut
    Après lecture en diagonale, en dessous de boucle, tu fait des push eax, nombre variable. Après ton jnz, tu fais un seul pop eax, donc quand tu va faire un ret, il va sauter à une adresse équivalent à un eax pushé, et non pas à l'adresse de retour de push_chaine, d'ou le crash.
    Ma page sur developpez.com : http://chrtophe.developpez.com/ (avec mes articles)
    Mon article sur le P2V, mon article sur le cloud
    Consultez nos FAQ : Windows, Linux, Virtualisation

  10. #10
    Invité
    Invité(e)
    Par défaut
    Ah lol j'ai dit cela parce que j'ai confondu avec le fait qu'il n'y a pas du pushaq/popaq (push/pop all) en 64-bits.


    Sinon je bloque un peu sur le code, en intervertissant les registres à la l.18, ça va un peu mieux, sinon je pense qu'au lieu qu'il compare le caractère d'une chaine, il compare son adresse en l'incrémentant dans push_chaine, donc crochet autour des registres manquants.

    Sinon oui, le fait de faire de multiple push (esp--) mais avec qu'un pop (esp++) en retour puis un ret (esp++) après, c'est vrai que cela va casser les branchement lors du saut du ret étant donné que le ret x86 est égale à:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    add     esp, 4
    jmp     [esp - 4]
    Et attend plutôt l'adresse mise par le call push_chaine dans la pile:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
        sub     esp, 4
        mov     [esp], dword ret_push_chaine
    jmp     push_chaine
    ret_push_chaine:
     
    call    pop_chaine
    ; ...
    Dernière modification par Invité ; 17/09/2015 à 02h33.

  11. #11
    Nouveau membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Août 2015
    Messages
    14
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 28
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Août 2015
    Messages : 14
    Points : 26
    Points
    26
    Par défaut
    Ah tout s'explique, je n'avais pas vraiment cherché à comprendre comment call et ret fonctionnaient. Du coup si je veux utiliser la pile au sein de mes fonctions il faut sauvegarder esp au début de la fonction pour pouvoir le restaurer juste avant le ret, j'ai bon ?

  12. #12
    Invité
    Invité(e)
    Par défaut
    Ou sinon tu décomposes le ret et le call comme je l'ai fait ^^
    Parce que vu ce que tu veux faire, c'est assez tordu comme technique de programmation, ce n'est pas forcément négatif le mot tordu dans ce contexte ^^


    call push_chaine:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    jmp     push_chaine
    ret_push_chaine:
    ret du push_chaine:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    jmp     ret_push_chaine
    Trop facile me diras-tu ?
    Bah je vois que cette option pour ne pas à avoir faire du code supplémentaire tout en se basant que sur la pile.

    Et fait le aussi pour ton pop_chaine, enfin je te conseille aussi de réécrire ton code avec les connaissances que tu as acquis depuis (parce que je ne suis pas sûr que ça va marcher, enfin crash non mais marcher je sais pas ) depuis le début sans utiliser push et pop pour voir, tu peux te le permettre sachant que ce n'est pas un gros code complexe.
    Dernière modification par Invité ; 17/09/2015 à 16h43.

  13. #13
    Nouveau membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Août 2015
    Messages
    14
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 28
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Août 2015
    Messages : 14
    Points : 26
    Points
    26
    Par défaut
    Oui je compte le réécrire de toute façon, ça ira plus vite et ça me permettra de mieux comprendre ce que je fais. Pour les ret/call à la main c'est tout con mais c'est vrai que ça peut éviter pas mal de prises de tête. Merci à vous deux en tout cas !

  14. #14
    Membre expérimenté
    Avatar de sambia39
    Homme Profil pro
    No Comment
    Inscrit en
    Mai 2010
    Messages
    543
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loiret (Centre)

    Informations professionnelles :
    Activité : No Comment
    Secteur : High Tech - Matériel informatique

    Informations forums :
    Inscription : Mai 2010
    Messages : 543
    Points : 1 745
    Points
    1 745
    Par défaut
    Bonjour
    Citation Envoyé par Abdoulito Voir le message
    Salut !
    Je débute en assembleur x86, et je bute un peu sur un exercice : je veux inverser une chaîne de caractère mais j'obtiens une segfault que je n'arrive pas à résoudre. Je suppose que mon erreur est relative avec la gestion de la pile mais je ne la comprends pas. Voilà mon programme :

    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
    segment .code
    global _start
    _start:
    
    	(1)call push_chaine		;met 0 suivi de mesg sur le haut de la pile
    	(2)call pop_chaine			;récupère la chaine
    	mov ecx, mesg		
    	mov eax, 4				;syscall 4 = stdout(ecx)
        mov ebx, 1		
        mov edx, size
        int 80h					;stdout mesg
    	mov	eax,1				;Interruption linux
    	mov	ebx,0				;pour quitter
    	int	80h					;le proggrame
    
    push_chaine:
    	push word 0				;0 = fin de la chaine
    	lea eax, [mesg]
    	boucle:
    	mov eax, ecx			;on stocke eax dans ecx
    	push eax				
    	inc eax					;on passe au caractere suivant
    	or ecx, ecx				;on vérifie si c'était le dernier caractère
    	jnz boucle				
    	pop eax					
    	lea eax, [mesg]			;on stocke le ptr sur la chaine
    	ret
    pop_chaine:
    	pop ecx					
    	mov [eax], ecx			;stockage du caractère courant
    	inc eax
    	or ecx, ecx
    	jnz pop_chaine
    	ret
    	
    section .data
    Merci d'avance de votre aide
    Première remarque, lire le code tel qu'il est et le comprendre comme ce qui a été écrit et non pas comme ce que l'on veut qu'il fasse, car ça vous induit en erreur et ne vous permet pas de savoir vraiment ce qui est à l'origine de l'erreur.
    ( 1 & 2 sont à l'origine des erreurs segfault ce qui ce traduit par tentative d'accès mémoire autre que la vôtre )

    (1) Vous appelez la fonction qui doit manipuler une chaine de caractère sans charger préalablement cette chaine de caractère dans le registre adéquat, mais par contre vous charger la chaine de caractère dans l'étiquette "call push_chaine" qui a pour première instruction la sauvegarde de fin de chaine et de plus vous ne travailler pas avec votre chaine de caractère précédemment chargé (charger dans le registre accumulateur EAX ) .Ensuite dans votre boucle vous effectuer une sauvegarde suivie d'une incrémentation de celle-ci (normalement vous devez vous poser la question qui suit, " est-ce que je pointe sur un caractère courant où j'incrémente juste l'accumulateur ?" ).
    puis vient le test de fin de chaine et après un saut si ce n'est pas le cas (on boucle). à ce stade je pense qu'il y a segfault.

    Dans ce genre d'exercice il faut structurer votre code de façon à ce qu'il soit logique et correspondant si possible à votre algorithme. Donc, la première étape est de charger la chaine ensuite la sauvegarder et enfin faire appel à votre fonction pour pouvoir travailler avec la chaine de caractère ce qui donnerait les instructions suivantes
    Code NASM : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    _start:
        mov eax, msg_ori 		; charge la chaine de caractère
        push eax		 	; vous la sauvegarde 
       call f_inverser_str	        ; appel de votre func
    	.....
    section	.data
    msg_ori db 'http://www.developpez.net',0xa
    siz_msg equ $ - msg_ori

    Dans votre fonction vous devez manipuler la chaine en empilent chaque caractère puis tester si vous êtes en fin de chaine ou pas
    vous pouvez faire
    Code NASM : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    save_data_c_str:
            mov bl, byte [eax]        ; on pointe sur le caractère courant
    	test bl,bl                      ; on teste si on est pas en fin de ligne
    	jz end_data_c_str         ; si oui en va en fin de traitement
    	push bx                       ; sinon en sauvegarde le caractère dans bx
    	inc eax                        ; on increment eax donc passe au caractère suivant.
    	jmp save_data_c_str    ; on boucle l'operation tant que bl est différent de 0

    (2)Vous dépiler ECX mais dans votre code source on ne voit pas là où il y a un POP ECX . Ensuite vous essayer de mettre le contenu de ECX dans EAX et vous incrémentez EAX etc. Bref je m'arrête là.
    Dans votre seconde fonction normalement vous devez avant tout recharger le pointeur de façon à ce qu'il pointe sur le caractère courant et ensuite vous allez commencer à dépiler les caractères pointer à coup de pop ce n'est qu'a ce stade que vous êtes réellement entrain d'inverser votre chaine de caractère.
    Code NASM : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    ; reacharger le pointeur 
    depile_data_c_str:
            pop bx                         ; dépiler le caractère actuel dans bx
    	mov byte [eax],bl         ; le mettre dans EAX 
    	inc eax                         ; incrémenté donc case suivante
    	test bl,bl                       ; si pas de fin de chaine un peut comme ( bx != '\0' || bx != 0)
    	jnz depile_data_c_str     ; alors on recommence tant que l'on a pas tout dépiler.
    	leave
    	ret

    Citation Envoyé par shaynox Voir le message
    Bon je suppose que tu fait du nasm.
    Alors je te conseille de lire sa doc: http://www.nasm.us/docs.php
    Bon je ne suis clairement pas un fan de push et pop, alors si c'est en série en plus avec ton push sans pop dans une même boucle, ou non avec qu'un pop après la boucle, malgré que ta boucle à du faire X boucles * nbr_char.
    Enfin je vois que tu as une fonction pop_chaine qui fait l'inverse de push_chaine, mais bon apparemment tous ces push et pop ne sont pas super synchro vu que tu as un segfault, enfin essaye d'enlever tous ces push et pop pour voir si cela marché déjà.
    Non on ne joue pas aux devinettes et ce n'est pas en retirant les POP ou PUSH que l'on va savoir d'où vient le problème surtout avec un segfault qui dit clairement que l'on a tenté ou accédé à un emplacement mémoire qui n'est pas le nôtre.

    Citation Envoyé par shaynox Voir le message
    Bref je n'aime pas les push/pop, mais d'après ce que j'en ai conclu, ton esp (push) alloue beaucoup plus de mémoire que tu n'en libères (pop)
    Après tu as déjà essayer la technique du petit poucet ? (je sais drôle de nom que j'ai inventé )
    En gros elle est simple, tu parcours ton code en y mettant une pause (boucle infinie) après chaque ligne/bloc de codes pour isoler ton code qui pose problème.
    Petite pousse est à éviter pourquoi mettre des boucles infini quel est l'intérêt ? tester si les instructions précédentes fonctionnent correctement? si oui comment on sort de la boucle ?
    Bref, tu peux utiliser de manière provisoire un breakpointe int 0x3 pour tester si les instructions précédentes ont été exécuter ou pas dans le cas contraire ya un souci.

    Citation Envoyé par shaynox Voir le message
    Et ne pas confondre le AT&T et l'intel:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    mov     eax, ecx        ;on stocke eax dans ecx
    C'est plutôt on stocke la valeur de ecx dans le registre eax.
    Oui c'est vrai mais la syntaxe elle-même n'est pas du type AT &T c'est juste une erreur de commentaire.

    Citation Envoyé par shaynox Voir le message
    Pourquoi déconseiller ? parce que c'est moche, voilà tout
    Je veux bien que l'on invente des macros/instructions pour automatiser certaines taches répétitives, mais bon, il y a toujours ce juste milieu à trouver ^^
    Et pour beaucoup apparemment, ils n'aiment pas beaucoup push et pop.
    Enfin la vraie raison du pourquoi c'est moche, c'est aussi parce qu'il ne faut pas rater son coup, push et pop sont comme des âmes soeurs, l'un ne peut pas vivre sans l'autre, ou du moins tu peux mélanger un compléter un push avec un sub et un pop avec un add, mais cela devient tordu comme logique de programmation.
    Sinon push/pop ne sont pas dispo en x64...... etc.
    POP/PUSH ont leur utilité et on les utilises en fonction du traitement que l'on va faire.

    Citation Envoyé par chrtophe Voir le message
    Ah bon ? Je savais pas. Même pas push rax ?
    Abdoulito, push et pop sont souvent utilisés avant un call notamment sous Windows. Exemple : avant d'appeler une fonction, tu va empiler ses paramètres (les stocker dans la pile, un peu comme une pile d'assiettes). Le principe est qu'il faut autant empiler que dépiler ni plus ni moins sinon tu va écraser ta pile et le soft en cours va planter.Je n'ai pas lu le code, mais comme le signale shaynox, si tu as des boucles imbriqués qui ne font pas les empilements/dépilements correctement : crash ...
    à bientôt
    Celui qui peut, agit. Celui qui ne peut pas, enseigne.
    Il y a deux sortes de savants: les spécialistes, qui connaissent tout sur rien,
    et les philosophes, qui ne connaissent rien sur tout.
    George Bernard Shaw

  15. #15
    Invité
    Invité(e)
    Par défaut
    Citation Envoyé par sambia39 Voir le message
    Non on ne joue pas aux devinettes et ce n'est pas en retirant les POP ou PUSH que l'on va savoir d'où vient le problème surtout avec un segfault qui dit clairement que l'on a tenté ou accédé à un emplacement mémoire qui n'est pas le nôtre.
    C'est juste ma méthode, alors oui je lui conseille de jouer aux devinettes, en plus c'est marrant

    Citation Envoyé par sambia39 Voir le message
    Petite pousse est à éviter pourquoi mettre des boucles infinies quel est l'intérêt ? Tester si les instructions précédentes fonctionnent correctement? si oui comment on sort de la boucle ?
    Bref, tu peux utiliser de manière provisoire un breakpointe int 0x3 pour tester si les instructions précédentes ont été exécuter ou pas dans le cas contraire ya un souci.
    Ne pose pas des questions dont tu connais déjà les réponses stp

    Citation Envoyé par sambia39 Voir le message
    Oui c'est vrai, mais la syntaxe elle-même n'est pas du type AT &T c'est juste une erreur de commentaire.
    Pour moi c'est une erreur de code et non de commentaire, car si tu regardes bien mettre ecx dans eax avec ecx non affecter au préalable n'a pas de sens et sachant qu'il considere ecx comme le caractère à tester.

    Citation Envoyé par sambia39 Voir le message
    POP/PUSH ont leur utilité et on les utilise en fonction du traitement que l'on va faire.
    Je dis juste l'avis de beaucoup de programmeurs asm sur l'utilisation de ces instructions.
    Dernière modification par E.Bzz ; 18/09/2015 à 15h09. Motif: Les messages adressés à la modération doivent l'être par MP

  16. #16
    Nouveau membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Août 2015
    Messages
    14
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 28
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Août 2015
    Messages : 14
    Points : 26
    Points
    26
    Par défaut
    Re !

    J'ai refait mon programme, cette fois il compile bien et me parait plus clair (même si j'ai utilisé push & pop pour le moment). En revanche, la chaine affichée n'est pas inversée et j'ai du mal à saisir pourquoi.

    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
    segment .code
    global _start
    _start:
    	mov ecx, 0
    	push ecx
    	jmp push_chaine
    	fin_push_chaine:
    	jmp pop_chaine
    	fin_pop_chaine:
    	mov ecx, mesg
    	mov eax, 4				;syscall 4 = stdout(ecx)
            mov ebx, 1		
            mov edx, size
            int 80h					;stdout mesg
    	mov	eax,1				;Interruption linux
    	mov	ebx,0				;pour quitter
    	int	80h					;le proggrame
     
    	push_chaine:
    	mov eax, mesg
    	inc ecx
    	push eax
    	cmp eax, 0				;quand fin chaine on arrete de boucler
    	jne push_chaine
    	pop eax					;eax = 0
    	mov ecx, 0				;on réinitialise le compteur pour la suite
    	jmp fin_push_chaine
     
    	pop_chaine:
    	pop eax
    	mov [mesg+ecx], eax
    	inc ecx
    	cmp eax, 0				;quand début chaine on arrete de boucler
    	jne pop_chaine	
    	jmp fin_pop_chaine
    section .data
     
    	mesg db 'Salut les potes', 0

  17. #17
    Invité
    Invité(e)
    Par défaut
    Salut,

    Tu es sûr que ton programme ne fait pas de boucle infinite arriver à ce bout de code ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
        push_chaine:
            mov     eax, mesg
            inc     ecx
            push    eax
        cmp     eax, 0              ; Quand fin chaine on arrete de boucler
        jne     push_chaine
    Sinon j'ai refait ton code, voie s'il marche, je l'ai pas testé (j'avoue un peu la flemme d'expliquer ce qui ne va pas si jamais cela marche, par contre si tu as des questions, n'hésite pas):
    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
     
    global _start
     
    segment .code
    ;{
        _start:
       ;{
            jmp     push_chaine
            fin_push_chaine:
     
            jmp     pop_chaine
            fin_pop_chaine:
     
            mov     ecx, msg
            mov     eax, 4              ; syscall 4 = stdout(ecx)
            mov     ebx, 1
            mov     edx, size
            int     80h                 ; stdout msg
     
            mov     eax,1               ; Interruption linux
            mov     ebx,0               ; Pour quitter
            int     80h                 ; Le programme
       ;}
     
        push_chaine:
       ;{
            xor     ecx, ecx
            loop1:
           ;{
                dec     esp
                mov     al, [msg + ecx]
                mov     [esp], al
     
                inc     ecx
           ;}
            cmp     al, 0               ; Quand fin chaine on arrete de boucler
            jne     loop1
     
            dec     ecx                 ; Si le zéro n'est pas pris en compte, alors mettre sub     ecx, 2 pour voir
       ;}
        jmp     fin_push_chaine
     
        pop_chaine:
       ;{
            xor     ebx, ebx
            loop2:
           ;{
                mov     al, [esp]
                mov     [msg + ebx], al
                inc     esp
     
                inc     ebx
           ;}
            loop     loop2              ; While (ecx)
       ;}
        jmp     fin_pop_chaine
    ;}
     
    section .data
        msg:    db  "Salut les potes", 0
    Dernière modification par Invité ; 22/09/2015 à 12h46.

  18. #18
    Nouveau membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Août 2015
    Messages
    14
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 28
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Août 2015
    Messages : 14
    Points : 26
    Points
    26
    Par défaut
    Ah oui en effet, j'ai completement oublié de pointer sur mesg + ecx, du coup ça peut pas fonctionner. Merci. Je regarderais ton code quand le mien fonctionnera

    Edit : bon par contre maintenant j'ai quelque chose d'assez bizarre à l'execution http://i.imgur.com/o1GGzgU.png

  19. #19
    Invité
    Invité(e)
    Par défaut
    Ah oui faut faire gaffe à ne pas écraser le zéro de ta chaine aussi, sinon le print va continuer à afficher des bytes jusqu'à ce qu'Il voit un zéro.
    Dernière modification par Invité ; 21/09/2015 à 00h48.

  20. #20
    Nouveau membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Août 2015
    Messages
    14
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 28
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Août 2015
    Messages : 14
    Points : 26
    Points
    26
    Par défaut
    Ton code compile mais affiche une suite de caractères du style de ce que j'ai screen au dessus

    J'ai rajouté la taille de la chaine qui a disparu entre temps mais ça ne semble pas régler le problème.

+ Répondre à la discussion
Cette discussion est résolue.
Page 1 sur 3 123 DernièreDernière

Discussions similaires

  1. Inversion d'une chaîne de caractères
    Par camoa dans le forum x86 16-bits
    Réponses: 7
    Dernier message: 31/10/2011, 14h56
  2. Réponses: 3
    Dernier message: 27/05/2010, 00h39
  3. Inversion d'une chaîne
    Par Maxence45 dans le forum Pascal
    Réponses: 36
    Dernier message: 15/03/2007, 00h58
  4. [Débutant] Comment sauvegarder une chaîne ?
    Par nmqm dans le forum Assembleur
    Réponses: 1
    Dernier message: 01/03/2006, 00h49

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