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 16-bits Assembleur Discussion :

Inversion d'une chaîne de caractères


Sujet :

x86 16-bits Assembleur

  1. #1
    Futur Membre du Club
    Profil pro
    Inscrit en
    Décembre 2006
    Messages
    6
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Décembre 2006
    Messages : 6
    Points : 6
    Points
    6
    Par défaut Inversion d'une chaîne de caractères
    Bonjour tout le monde,

    j'ai un autre problème avec un autre programme. J'explique :

    On met une chaîne de caractères (ex: "bonjour") et on doit faire en sorte qu'en sortie on ait "ruojnob", c'est-à-dire qu'on doit inverser la chaîne de caractères.
    J'ai fait ce programme mais je n'obtiens pas du tout ça. Quelqu'un pourrait me dire ce qui ne va 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
     
    .386
    ASSUME  ss:pile,    cs:code,  DS:donnees
     
    pile  segment stack use16
     
          DB   1024   Dup(0)
     
    Pile  ends
     
    donnees segment use16
     
            acMess1 DB "Bonjour$"
     
    donnees ends
     
    code segment use16
     
    main:
        MOV AX,donnees
        MOV DS,AX
        MOV Cx,0
        mov Bx,6
     
     
    while_debut:
     
             cmp cx,bx
             jnb  while_fin
     
    	 mov bh,acMess1[Bx]
    	 mov dx,bx
    	 mov bx,cx
    	 mov ch,acMess1[Bx]
    	 mov bx,dx
    	 mov acMess1[Bx],ch
    	 mov bx,cx
    	 mov acMess1[Bx],bh
    	 mov bx,dx
     
     
             inc Cx
             dec Bx
     
             jmp while_debut
     
     
    while_fin:
     
    	mov ah,9
    	lea dx,acMess1
    	int 21h
     
     
           MOV AH,4ch
           Int 21h
     
     
     code ends
     end main

  2. #2
    Responsable Pascal, Lazarus et Assembleur


    Avatar de Alcatîz
    Homme Profil pro
    Ressources humaines
    Inscrit en
    Mars 2003
    Messages
    7 930
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 57
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ressources humaines
    Secteur : Service public

    Informations forums :
    Inscription : Mars 2003
    Messages : 7 930
    Points : 59 398
    Points
    59 398
    Billets dans le blog
    2
    Par défaut
    Bonjour !

    En fait, tu te compliques la vie en voulant utiliser uniquement le registre bx comme index : tu peux très bien utiliser également un registre d'index comme si. Ca pourrait donner quelque chose comme ceci :
    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
    MOV Si,0
    mov Bx,6
     
     
    while_debut:
     
             cmp Si,Bx
             jnb  while_fin
     
    	 mov al,acMess1[Bx]
             mov ah,acMess1[Si]
    	 mov acMess1[Bx],ah
             mov acMess1[Si],al
     
             inc Si
             dec Bx
     
             jmp while_debut
     
     
    while_fin:
    Le principal problème dans ton code vient de l'instruction
    En changeant la valeur de bh, tu changes la valeur de bx pour la suite des opérations.
    Règles du forum
    Cours et tutoriels Pascal, Delphi, Lazarus et Assembleur
    Avant de poser une question, consultez les FAQ Pascal, Delphi, Lazarus et Assembleur
    Mes tutoriels et sources Pascal

    Le problème en ce bas monde est que les imbéciles sont sûrs d'eux et fiers comme des coqs de basse cour, alors que les gens intelligents sont emplis de doute. [Bertrand Russell]
    La tolérance atteindra un tel niveau que les personnes intelligentes seront interdites de toute réflexion afin de ne pas offenser les imbéciles. [Fiodor Mikhaïlovitch Dostoïevski]

  3. #3
    Nouveau Candidat au Club
    Inscrit en
    Octobre 2011
    Messages
    1
    Détails du profil
    Informations forums :
    Inscription : Octobre 2011
    Messages : 1
    Points : 1
    Points
    1
    Par défaut question
    et si la chaine etait de taille inconnue et qu on a un deja un macro qui nous donne la taille , comment faire ??

  4. #4
    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
    Si la taille de la taille est inconnue,on la mesure (lstrlen..... +++)
    Elle doit être >= 2
    Le principe est simple.
    Un pointeur debut chaine
    Un pointeur en fin de chaine
    on charge le byte de debut mov al,byte ptr [registre pointeur]
    on charge le byte de fin
    on stocke le byte de debut a la fin
    on stocke le byte de fin au debut
    le pointeur de debut est incremente de +1 (inc)
    le pointeur de fin se decremente de 1 (dec)
    on verifie que les pointeurs ne sont pas égaux
    on recommence

  5. #5
    Membre éclairé
    Avatar de edfed
    Profil pro
    être humain
    Inscrit en
    Décembre 2007
    Messages
    476
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : être humain

    Informations forums :
    Inscription : Décembre 2007
    Messages : 476
    Points : 701
    Points
    701
    Billets dans le blog
    1
    Par défaut
    on peut aussi tester en premier que les pointeurs de fin et de debut ne sont pas egaux, en testant la taille du fichier.

    le compteur est égal à la taille divisée par deux.
    si ce compteur est egal à 0, alors on termine la fonction.
    sinon, on continue

    l'index de fin est egal à (taille-1 + pointeur de chaine)
    l'index de debut est egal à (pointeur de chaine)

    loop_ici:
    lire AL dans fin, lire AH dans debut
    ecrire AL dans debut, ecrire AH dans fin
    incrementer debut
    decrementer fin
    loop_ici avec le compteur
    et c'est fini.

    et au final, on peut meme prendre les chaine de 0 ou 1 caractère. et le check d'erreur à lieu des le debut, ce qui economise des cycles.

    mais il faut penser qu'il serait judicieux de creer une fonction de copie de chaine, pour travailler sur une copie et non sur l'original. mais c'est un autre sujet.

  6. #6
    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
    Pas besoin de compteur
    Taille >= 2 ;au debut

    Pointeur debut >= pointeur fin = c'est fini

  7. #7
    Membre éclairé
    Avatar de edfed
    Profil pro
    être humain
    Inscrit en
    Décembre 2007
    Messages
    476
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : être humain

    Informations forums :
    Inscription : Décembre 2007
    Messages : 476
    Points : 701
    Points
    701
    Billets dans le blog
    1
    Par défaut
    oui, mais ça coute un cmp de plus par iteration.

    un loop iteration, ça va plus vite qu'un cmp debut,fin / jb iteration .
    jb car comme on travaille sur des pointeurs, il vaut mieux utiliser la logique non signée, ce qui est implicite avec loop.


    le fait de tester au debut l'egalité de pointeur (en divisant par deux la taille) permet de s'affranchir de bug en cas d'egalité dès le debut, et le fait d'utiliser ce meme nombre comme compteur de loop permet d'optimiser enormement le programme, en taille comme en rapidité.

    ça donnerait ça en 16 bits.
    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
     
    ;taille:dw @f-$-2                       ;taille en octets de la chaine
    ;chaine:db "chaine à inverser"   ;chaine de caractères dont la taille est donnée dans le word precedant
    ;@@:    db 0                     ;au cas où on veut afficher la chaine en asciiZ.
    ;...
    ;       mov si,chaine
    ;       call invstr
    ;...
    invstr:
            push ax cx si di
            mov cx,[si-2]
            mov di,cx
            shr cx,1
            je .end
            dec di
            add di,si
    .iteration:
            mov al,[si]
            mov ah,[di]
            mov [si],ah
            mov [di],al
            inc si
            dec di
            loop .iteration
    .end:
            pop di si cx ax
            ret
    d'ailleur, je vais de ce pas tester ce bout de code. et je viens de le tester, ça marche comme prevu. on peut surement faire plus rapide, mais je vois pas comment, sans coder une veritable usine à gaz.

    du genre, tester si l'on a que 1, 2, ou 3 octets, utiliser un dword si l'on a plus que 3 octets.
    utiliser un micro bout de code pour les cas 1, 2 et 3, utiliser le dword pour tout les autres cas. inverser les octets d'un dword avec les instructions bswap, bswap ou ror/rol. etc... pourquoi pas utiliser les registres SSE pour les cas au dessus de 16 octets. etc...
    des optimisations qui ne sont même pas rentabilisées par le gain de cycles tellement c'est long à mettre au point.

    celà dit faudrait comparer les deux methodes pour voir.
    avec test d'egalité de pointeurs en fin de loop, et avec test d'egalité au debut avec taille divisée par deux.

  8. #8
    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
    La désolé , mais le loop est beaucoup plus lent que le cmp et est répété autant de fois que le cmp.
    C'est un problème classique d'optimisation.

Discussions similaires

  1. [Débutant] Inverser une chaîne de caractères
    Par zbooon dans le forum x86 16-bits
    Réponses: 5
    Dernier message: 28/04/2017, 14h44
  2. Inversion d'une chaîne de caractères
    Par bounadalvidal dans le forum Débuter
    Réponses: 7
    Dernier message: 09/11/2010, 15h51
  3. Réponses: 3
    Dernier message: 27/05/2010, 00h39
  4. Réponses: 3
    Dernier message: 24/10/2007, 02h47
  5. Inverser une chaîne de caractères
    Par DBBB dans le forum Assembleur
    Réponses: 2
    Dernier message: 30/03/2003, 12h09

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