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 :

Boucle for en assembleur


Sujet :

x86 32-bits / 64-bits Assembleur

  1. #1
    Membre régulier

    Profil pro
    Inscrit en
    juin 2009
    Messages
    99
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : juin 2009
    Messages : 99
    Points : 122
    Points
    122
    Par défaut Boucle for en assembleur
    Bonjour,

    je me suis fixé comme objectif de coder les différentes boucles, a savoir for, while, do...while

    Pour le moment j'en suis a la boucle for et j'avoue ne pas comprendre pourquoi mon code me sort une boucle infinie.On peut voir qu'au début de l'execution du programme ma variable var est bien incrémentée correctement : on voit 1 puis 2 mais après je pars dans une boucle infinie et l'incrémentation s'arrête et je ne comprend pas pourquoi.

    Le code :
    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
    segment			 .data
     
    var		dw	0
     
    segment			.bss
     
    segment			.text
     
    global _start
     
    _start :
     
    	xor eax, eax
    	mov eax, [var]
     
    	mov ecx, 10
     
    debut :
     
    	inc eax
     
    	mov bl, 1
    	div bl
     
    	add al, 0x30
    	mov [var], al
     
    	mov eax, 4
    	mov ebx, 1
    	mov ecx, var
    	mov edx, 1
    	int 0x80
     
    	loop debut
     
    	jmp fin
     
    fin :
     
    	mov eax, 1
    	mov ebx, 0
    	int 0x80
    et voici se que j'ai en sortie :
    122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222
    Merci.

  2. #2
    Expert éminent
    Avatar de Kannagi
    Homme Profil pro
    cyber-paléontologue
    Inscrit en
    mai 2010
    Messages
    2 710
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 31
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : cyber-paléontologue

    Informations forums :
    Inscription : mai 2010
    Messages : 2 710
    Points : 8 312
    Points
    8 312
    Par défaut
    Parce que tu as écris ceci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    mov ecx, var
    loop debut
    loop décrémente le regitre ecx ,mais toi tu l'initialise à chaque fois , il faut que tu fasse un push/pop.

    Sinon :
    Ne sert absolument à rien

  3. #3
    Membre régulier

    Profil pro
    Inscrit en
    juin 2009
    Messages
    99
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : juin 2009
    Messages : 99
    Points : 122
    Points
    122
    Par défaut
    Pour push et pop j'ai ce message d'erreur :
    instruction not supported in 64-bit mode
    Comment je fait du coup ?

  4. #4
    Expert éminent
    Avatar de Kannagi
    Homme Profil pro
    cyber-paléontologue
    Inscrit en
    mai 2010
    Messages
    2 710
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 31
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : cyber-paléontologue

    Informations forums :
    Inscription : mai 2010
    Messages : 2 710
    Points : 8 312
    Points
    8 312
    Par défaut
    Ne marche pas ?

  5. #5
    Invité
    Invité(e)
    Par défaut
    Quel assembleur utilises-tu ? Vu le message d’erreur, on dirait que tu es en 64 bits. Ou alors, c’est ton linker qui déconne. En assembleur, il y a souvent des erreurs surprenantes pendant l’assemblage...

  6. #6
    Membre régulier

    Profil pro
    Inscrit en
    juin 2009
    Messages
    99
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : juin 2009
    Messages : 99
    Points : 122
    Points
    122
    Par défaut
    L'instruction :
    me renvoit l'erreur ci dessus.

    En fait voici ce que j'ai trouvé a propos de push et pop en 64 bits :
    You cannot push a 32 bit register in 64 bit mode; instead, you can push and pop the whole 64 bit register that contains a 32-bit value you want, so that's push rax instead of push eax
    donc un push ecx est faux par contre push rcx est correct.

    Sinon je suis sous Linux Mint 19 (OS 64 bits) , et je code via NASM syntax intel 8086.

    Je compile et link mon code avec ces deux commandes :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    nasm -f elf64 nomDuFichierAsm.asm
    ld nomDuFichierAsm.o -o nomExecutable
    En utilisant cette commande :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    nasm -f elf boucle_for.asm
    tout vas bien, mais au moment du linkage cette erreur survient :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    ld*: architecture i386 du fichier d'entrée «*boucle_for.o*» est incompatible avec la sortie i386:x86-64
    Je link via cette commande :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    ld boucle_for.o -o boucle_for

  7. #7
    Responsable Systèmes


    Homme Profil pro
    Technicien maintenance
    Inscrit en
    août 2011
    Messages
    11 856
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Technicien maintenance
    Secteur : High Tech - Matériel informatique

    Informations forums :
    Inscription : août 2011
    Messages : 11 856
    Points : 26 591
    Points
    26 591
    Par défaut
    Dans ton source, tu ne précise pas si ton code est 32 ou 64 bits.

    Tu peux le faire avec :

    push ecx fonctionne en 64 bits, il ne sauvegarde tout simplement pas les bits de poids fort du registre rcx. Et comme tu n'utilise pas de registres 64 bits, pas de problèmes.

    Le code est de toute façon du code 32 bits et il faut le compiler en 32bits, car les appels systèmes ne se font pas de la même façon en 64 bits, on utilise pas int 0x80 mais sysenter et les registres pour les paramètres ne sont pas les mêmes.
    Ma page sur developpez.com : http://chrtophe.developpez.com/ (avec mes articles)
    Mon article sur la création d'un système : http://chrtophe.developpez.com/tutoriels/minisysteme/
    Mon article sur le P2V : http://chrtophe.developpez.com/tutoriels/p2v/
    Consultez nos FAQ : Windows, Linux, Virtualisation

  8. #8
    Invité
    Invité(e)
    Par défaut
    L'opcode de push ecx et push rcx est le même. Idem pour les autres registres et l'instruction pop.
    C'est ce qui fait qu'il est nécessaire de préciser que l'assemblage doit être fait en 32 bits. A l'inverse, des instructions telles que mov r32,r/m32 et mov r64,r/m64 ont également les mêmes opcodes mais précédés d'un préfixe dans le cas du 64 bits.
    On voit donc bien que la transposition en 64 bits n'est pas homogène en ce qui concerne le codage.

    J’aimerais maintenant revenir sur le push ecx recommandé par Kannagi. C'est effectivement la bonne solution mais, pour les boucles mettant en oeuvre des fonctions (c'est notamment le cas avec les API Windows), il est plus judicieux de remplacer le classique compteur dans ecx par une variable globale ou locale. S'agissant de Windows, que je connais assez bien, la norme est de préserver systématiquement le contenu des registres ebx, esi et edi. Il résulte de ce principe que certaines API préservent ecx alors que d'autres le modifient, ce qui peut s'avérer fâcheux à l'usage.

    S'agissant enfin de ton programme, quelques remarques :
    • La déclaration de Var est incorrecte. Tu devrais avoir Var dd 0 pour être cohérent avec les manipulations sur les registres 32 bits qui seront faites ultérieurement.
    • Le mieux, d'ailleurs, est de mettre cette valeur à 30h (Ascii du zéro). Donc, Var dd 30h
    • Je ne comprends pas ta division par 1. A quoi sert-elle?
    • avec une boucle de 10 unités, on va avoir le problème avec le nombre 10 qui impose d'afficher 2 chiffres. Je suggère donc de n'incrémenter la valeur de la variable qu'après l'affichage, histoire de démarrer le comptage à partir de zéro.


    En définitive, on obtiendrait un programme de ce type dans lequel j'ai essayé d'intégrer les préconisations de Chrtophe, Kannagi et les miennes. Je ne me suis livré à aucun test :
    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
    [BITS 32]
    segment			 .data
    var		dd	 30h
    segment			.bss
    segment			.text
     
    global _start
     
    _start :
    	mov ecx, 10
     
    debut :
            push ecx
    	mov  eax, 4
    	mov  ebx, 1
    	mov  ecx, var
    	mov  edx, 1
    	int  0x80
            pop  ecx
     
    	inc  [var]
     
    	loop  debut
     
    	mov eax, 1
    	mov ebx, 0
    	int 0x80
    Attention : je ne travaille qu'avec les assembleurs MASM et GOASM avec Windows. L'univers de NASM et Linux me sont totalement étrangers. Je ne suis donc pas à l'abri d'erreurs.

  9. #9
    Responsable Systèmes


    Homme Profil pro
    Technicien maintenance
    Inscrit en
    août 2011
    Messages
    11 856
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Technicien maintenance
    Secteur : High Tech - Matériel informatique

    Informations forums :
    Inscription : août 2011
    Messages : 11 856
    Points : 26 591
    Points
    26 591
    Par défaut
    ecx est en général utilisé pour les boucles car cablé avec loop, ou jcxz (plus recommandé). Il reste possible d'utiliser un autre registre en le décrémentant et le comparant à 0, mais autant sauvegarder ecx sur la pile pour bénéficier des fonctions pré-cités
    Ma page sur developpez.com : http://chrtophe.developpez.com/ (avec mes articles)
    Mon article sur la création d'un système : http://chrtophe.developpez.com/tutoriels/minisysteme/
    Mon article sur le P2V : http://chrtophe.developpez.com/tutoriels/p2v/
    Consultez nos FAQ : Windows, Linux, Virtualisation

  10. #10
    Membre régulier

    Profil pro
    Inscrit en
    juin 2009
    Messages
    99
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : juin 2009
    Messages : 99
    Points : 122
    Points
    122
    Par défaut
    Merci pour tout vos commentaires ça m'aide beaucoup, c'est cool.

    Alors il a fallu modifier très légérement le code de Asmou, a savoir que si j'essaye de compiler le code tel qu'il est ci dessus j'obtiens ceci via nasm :

    boucle_for.asm:28: error: operation size not specified
    j'ai modifié ainsi ( ligne 28 : inc byte [var] ) :

    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
    [BITS 32]
    segment			 .data
     
    var		dd	 30h
     
    segment			.bss
     
    segment			.text
     
    global _start
     
    _start :
     
    	mov ecx, 10
     
    debut :
     
        push ecx
     
    	mov eax, 4
    	mov ebx, 1
    	mov ecx, var
    	mov edx, 1
    	int 0x80
     
        pop ecx
     
    	inc byte [var]
     
    	loop  debut
     
    	mov eax, 1
    	mov ebx, 0
    	int 0x80
    Alors ça compile et tout très bien, mais j'obtiens en sortie une erreur de segmentation après la premiére incrémentation :

    0Erreur de segmentation (core dumped)
    J'avoues ne pas totalement comprendre cette erreur.

  11. #11
    Responsable Systèmes


    Homme Profil pro
    Technicien maintenance
    Inscrit en
    août 2011
    Messages
    11 856
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Technicien maintenance
    Secteur : High Tech - Matériel informatique

    Informations forums :
    Inscription : août 2011
    Messages : 11 856
    Points : 26 591
    Points
    26 591
    Par défaut
    Chez moi ça fonctionne avec :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    nasm -f elf test.asm -o test.o
    ld test.o -o test
    Par contre, pense à ajouter un caractère de retour chariot après la boucle.
    Ma page sur developpez.com : http://chrtophe.developpez.com/ (avec mes articles)
    Mon article sur la création d'un système : http://chrtophe.developpez.com/tutoriels/minisysteme/
    Mon article sur le P2V : http://chrtophe.developpez.com/tutoriels/p2v/
    Consultez nos FAQ : Windows, Linux, Virtualisation

  12. #12
    Membre régulier

    Profil pro
    Inscrit en
    juin 2009
    Messages
    99
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : juin 2009
    Messages : 99
    Points : 122
    Points
    122
    Par défaut
    j'obtiens cette erreur lors de la compilation:

    ld*: architecture i386 du fichier d'entrée «*boucle.o*» est incompatible avec la sortie i386: x86-64
    Je n'ai malheureusement plus de temps je m'y remet ce soir.

  13. #13
    Invité
    Invité(e)
    Par défaut
    Citation Envoyé par chrtophe Voir le message
    ecx est en général utilisé pour les boucles car cablé avec loop, ou jcxz (plus recommandé). Il reste possible d'utiliser un autre registre en le décrémentant et le comparant à 0, mais autant sauvegarder ecx sur la pile pour bénéficier des fonctions pré-cités
    Je connais tout ça depuis des lustres. Pour ma part, j'utilise un compteur sous forme de variable lorsque le programme prend du volume et, notamment lorsqu'il y a des boucles imbriquées. C'est, du reste, une technique largement utilisée dans les compilateurs.
    Il faut remarquer enfin que RCX fait partie des 4 premiers registres permettant de passer des paramètres dans la convention FASTCALL utilisée pour le x64. C'est donc un registre à éviter dans ce cas.
    Un exemple de base pour fixer les idées...
    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
    .data
        Count   dd  0
     
    .code
        .
        .
        mov Count,10
     
    Bcle:
        .
        .
        dec  Count
        jnz   Bcle
        .
        .

  14. #14
    Responsable Systèmes


    Homme Profil pro
    Technicien maintenance
    Inscrit en
    août 2011
    Messages
    11 856
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Technicien maintenance
    Secteur : High Tech - Matériel informatique

    Informations forums :
    Inscription : août 2011
    Messages : 11 856
    Points : 26 591
    Points
    26 591
    Par défaut
    Les appels systèmes en 64 bits via sysenter attendent leurs paramètres dans les registres rdi, rsi, rdx, rcx, r8, r9, rax contenant le numéro de l'appel, qui n'est pas le même qu'en 32 bits.
    Ma page sur developpez.com : http://chrtophe.developpez.com/ (avec mes articles)
    Mon article sur la création d'un système : http://chrtophe.developpez.com/tutoriels/minisysteme/
    Mon article sur le P2V : http://chrtophe.developpez.com/tutoriels/p2v/
    Consultez nos FAQ : Windows, Linux, Virtualisation

  15. #15
    Membre régulier

    Profil pro
    Inscrit en
    juin 2009
    Messages
    99
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : juin 2009
    Messages : 99
    Points : 122
    Points
    122
    Par défaut
    Dites je me permet d'insister un peu car mon code n'est toujours pas fonctionnel :

    ce code semble correct :

    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
    [BITS 32]
    segment			 .data
     
    var		dd	 30h
     
    segment			.bss
     
    segment			.text
     
    global _start
     
    _start :
     
    	mov ecx, 10
     
    debut :
     
        push ecx
     
    	mov eax, 4
    	mov ebx, 1
    	mov ecx, var
    	mov edx, 1
    	int 0x80
     
        pop ecx
     
    	inc byte [var]
     
    	loop  debut
     
    	mov eax, 1
    	mov ebx, 0
    	int 0x80
    Mais tout de même une erreur a la compilation :
    ld*: architecture i386 du fichier d'entrée «*boucle.o*» est incompatible avec la sortie i386: x86-64
    Or si je compile avec :
    nasm -f elf64 boucle_for.asm
    Je n'ai pas le message ci dessus mais j'obtiens un segment fault.

    Donc comment je peux faire svp ?

  16. #16
    Responsable Systèmes


    Homme Profil pro
    Technicien maintenance
    Inscrit en
    août 2011
    Messages
    11 856
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Technicien maintenance
    Secteur : High Tech - Matériel informatique

    Informations forums :
    Inscription : août 2011
    Messages : 11 856
    Points : 26 591
    Points
    26 591
    Par défaut
    Il faut que tu compiles en 32 bits, pas en 64.

    Essayes d'installer le paquet ia32-libs.
    Ma page sur developpez.com : http://chrtophe.developpez.com/ (avec mes articles)
    Mon article sur la création d'un système : http://chrtophe.developpez.com/tutoriels/minisysteme/
    Mon article sur le P2V : http://chrtophe.developpez.com/tutoriels/p2v/
    Consultez nos FAQ : Windows, Linux, Virtualisation

  17. #17
    Membre régulier

    Profil pro
    Inscrit en
    juin 2009
    Messages
    99
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : juin 2009
    Messages : 99
    Points : 122
    Points
    122
    Par défaut
    Erf toujours cette même erreur lors du linkage , malgrès le fait que j'ai install ia32-libs :

    ld*: architecture i386 du fichier d'entrée «*boucle.o*» est incompatible avec la sortie i386: x86-64
    EDIT :

    C'est bon j'ai trouvé voici les commandes que j'ai utilisés :

    nasm -f elf test.asm -o test.o
    ld -m elf_i386 test.o -o test

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Boucle for dans un script cmd
    Par nicolas.ganache dans le forum Développement
    Réponses: 4
    Dernier message: 19/07/2004, 17h07
  2. Réponses: 3
    Dernier message: 06/07/2004, 11h21
  3. [Debutant] Batch et Boucle for
    Par ludovic.fernandez dans le forum Scripts/Batch
    Réponses: 8
    Dernier message: 06/05/2004, 20h21
  4. [Swing][boucles] for, do, if .....comment faire simple?
    Par chastel dans le forum AWT/Swing
    Réponses: 7
    Dernier message: 02/05/2004, 23h49
  5. [langage] boucle "for" modification du pas
    Par K-ZimiR dans le forum Langage
    Réponses: 4
    Dernier message: 29/04/2004, 12h54

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