Précédent   Forum du club des développeurs et IT Pro > Autres langages > Assembleur > x86 16-bits
x86 16-bits Architecture x86 16 bits et ses outils (assembleurs, debuggers, émulateurs...)
Partagez cette discussion sur d'autres réseaux sociaux : Viadeo Twitter Google Facebook Digg Delicious MySpace Yahoo
Réponse
 
Outils de la discussion
Publicité
'
Vieux 10/12/2006, 17h48   #1
camoa
Invité de passage
 
Inscription : décembre 2006
Messages : 6
Détails du profil
Informations forums :
Inscription : décembre 2006
Messages : 6
Points : 2
Points : 2
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 :
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
camoa est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 10/12/2006, 21h17   #2
Alcatîz
Responsable Pascal

 
Avatar de Alcatîz
 
Homme Jean-Luc Gofflot
Ressources humaines
Inscription : mars 2003
Messages : 5 508
Détails du profil
Informations personnelles :
Nom : Homme Jean-Luc Gofflot
Âge : 46
Localisation : Belgique

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

Informations forums :
Inscription : mars 2003
Messages : 5 508
Points : 39 355
Points : 39 355
Envoyer un message via ICQ à Alcatîz Envoyer un message via MSN à Alcatîz Envoyer un message via Yahoo à Alcatîz Envoyer un message via Skype™ à Alcatîz
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 :
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
Tutoriels, exercices, FAQ, sources, compilateurs, outils, livres Pascal
Mes tutoriels et sources Pascal
FAQ Assembleur

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]
Alcatîz est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 29/10/2011, 00h00   #3
mimitw5
Invité de passage
 
Inscription : 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 ??
mimitw5 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 29/10/2011, 14h33   #4
ToutEnMasm
Membre confirmé
 
Inscription : octobre 2005
Messages : 173
Détails du profil
Informations forums :
Inscription : octobre 2005
Messages : 173
Points : 208
Points : 208
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
ToutEnMasm est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 30/10/2011, 16h30   #5
edfed
Membre chevronné
 
Avatar de edfed
 
être humain
Inscription : décembre 2007
Messages : 471
Détails du profil
Informations professionnelles :
Activité : être humain

Informations forums :
Inscription : décembre 2007
Messages : 471
Points : 619
Points : 619
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.
__________________
http://www.pending.me.uk/nmc/bla_1356091200.png
Vivement 21/12/2012
edfed est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 30/10/2011, 18h15   #6
ToutEnMasm
Membre confirmé
 
Inscription : octobre 2005
Messages : 173
Détails du profil
Informations forums :
Inscription : octobre 2005
Messages : 173
Points : 208
Points : 208
Pas besoin de compteur
Taille >= 2 ;au debut

Pointeur debut >= pointeur fin = c'est fini
ToutEnMasm est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 31/10/2011, 12h06   #7
edfed
Membre chevronné
 
Avatar de edfed
 
être humain
Inscription : décembre 2007
Messages : 471
Détails du profil
Informations professionnelles :
Activité : être humain

Informations forums :
Inscription : décembre 2007
Messages : 471
Points : 619
Points : 619
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 :
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.
__________________
http://www.pending.me.uk/nmc/bla_1356091200.png
Vivement 21/12/2012
edfed est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 31/10/2011, 13h56   #8
ToutEnMasm
Membre confirmé
 
Inscription : octobre 2005
Messages : 173
Détails du profil
Informations forums :
Inscription : octobre 2005
Messages : 173
Points : 208
Points : 208
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.
ToutEnMasm est déconnecté   Envoyer un message privé Réponse avec citation 00
Réponse
Outils de la discussion

Navigation rapide


Fuseau horaire GMT +2. Il est actuellement 06h57.


 
 
 
 
Partenaires

Hébergement Web