Problème sur un devoir en assembleur [Help : c'est pas simple <:'o( ]

Problème sur un devoir en assembleur [Help : c'est pas simple <:'o( ] - ASM - Programmation

Marsh Posté le 14-12-2002 à 18:19:30    

Je dois faire un programme en assembleur qui teste si une chaine de caractères (qu'on entre au clavier) est un palindrome ou non (--> même chose qu'on la lise de gauche à droite ou de droite à gauche).
 
J'ai écrit le programme, mais il m'indique toujours que ce que j'ai entré n'est pas un palindrome (même les palindromes, d'où le problème ;o) et je ne vois pas du tout où se trouve l'erreur ! La logique du programme me semble bonne pourtant ! Le traducteur ne me signale aucune erreur (juste un warning, mais inévitable).
 

.model small
.stack
.data
    ac_intro DB "Veuillez entrer la chaine de caractères à tester : $"
    ac_pos DB 0ah, 0dh, "La chaine que vous avez entré est un palindrome !$"
    ac_neg DB 0ah, 0dh, "La chaine que vous avez entré n'est pas un palindrome !$"
    ac_work DB 250, ?, 251 dup ('$')
 
.code
 
main :
    mov ax, @data
    mov ds, ax
     
    mov ax, 0900h
    lea dx, ac_intro
    int 21h ;affichage du message d'intro
 
    mov ax, 0a00h
    lea dx, ac_work
    int 21h ;saisie de la string
 
    mov si, 2
    mov di, ac_work[1]
    inc di ;initialisation des variables d'indice : si pour le premier élément de la chaine à tester et di pour le dernier
 
 
until :
    cmp si, di
    jae fin1
    cmp ac_work[si], 20h
    je si_space
    cmp ac_work[di], 20h
    je di_space
    mov dl, ac_work[di]
    cmp ac_work[si], dl
    jne fin2
    dec di
    inc si
    jmp until
 
si_space :
    inc si
    jmp until
 
di_space :
    dec di
    jmp until
 
fin1 :
    mov ax, 0900h ; affichage du message de succès
    lea dx, ac_pos
    int 21h
    jmp quit
 
fin2 :
    mov ax, 0900h ; affichage du message d'échec
    lea dx, ac_neg
    int 21h
     
quit :
    mov ax, 4c00h
    int 21h
 
end main


 
 
Explication sur la partie "until" : tant que si <= que di, je regarde si l'élément repéré par si est un espace blanc (j'aurais pu mettre ' ';). Si c'est le cas, je passe à l'élément suivant (inc si). Idem pour di (avec dec di le cas échéant).
Si les éléments repérés par si et di sont tous les deux des caractères, alors je regarde s'ils sont les mêmes. Si oui, je continue, si non je coupe !
 
 
Voila, je ne vois pas où se trouve l'erreur :o/ Quelqu'un pourrait-il m'aider ? C'est sûrement une bétise, mais bon !
Merci d'avance !


Message édité par yannick_frere le 15-12-2002 à 14:06:58
Reply

Marsh Posté le 14-12-2002 à 18:19:30   

Reply

Marsh Posté le 14-12-2002 à 19:51:34    

S'il vous plait, il n'y a personne pour me donner un petit coup de main ?  :(

Reply

Marsh Posté le 14-12-2002 à 21:16:38    

bin pour ton histoire d'espace, tu doit "sauter" tout les espaces du début, et sauter tout les espaces de fin, et ensuite faire la comparaison "croisée", moi je vois l'algo comme ça:
 
deb: chaine saisie
fin: pointeur
 
 
;positionnement à la fin
 
fin<-deb
 
tant que fin != 0
     avancer fin
 
; on bouffe les espaces du début
 
tant que deb == espace
     avancer deb
 
; on bouffe les espaces de fin
 
   reculer fin
tant que fin == espace
 
; comparaison croisée
 
tant que deb==fin et adresse deb < adresse fin
   avancer deb
   reculer fin
 
si deb==fin
   c'est un palindrome
 
 
 
ça doit être ça l'algo à coder non ?

Reply

Marsh Posté le 14-12-2002 à 21:33:40    

Merci pour ton aide, Bjone !
 
Ce que tu m'as proposé ne suffira pas  :(
Parce que tu élimines les espaces du début et de la fin, mais il pourrait y en avoir au milieu !
Du style "  abba ab ba abba    " : il y a des espaces au début et à la fin, mais aussi au milieu de la chaine ! Et je ne dois pas en tenir compte !
 
Dans mon programme, je compare les éléments du début et de la fin tant que ce ne sont pas des espaces ... Donc, de cette manière, je ne tiens compte ni des espaces des extrémités, ni de ceux dans la chaine.
Of course, il y a d'autres manières de faire (style ne recopier que les caractères différents de ' ' dans un autre tableau et tester si les caractères forment un palindrome). Le problème, c'est que j'aimerais comprendre mon erreur dans ce programme-ci ! Je ne la trouve pas !
 
Mais merci pour ton aide ! Si toi ou d'autres avez encore des suggestions, n'hésitez pas ! :)

Reply

Marsh Posté le 15-12-2002 à 01:34:47    

"  abba ab ba abba    " passera pas...
mais   "abba ab ba abba" passera...
 
rien à foutre des espaces à -l'intérieur-, l'espace est un caractère comme un autre, seul les espaces de trop au début et à la fin feront chier, mais ceux entre, je vois pas le problème...
 
comment vois-tu ta routine ?
doit-elle considérer que toute la chaine saisie doit passer au teste du palindrome ?
 
du style: "azertytreza"
 
ou tu dois essayer des séparer les mots pour les tester séparément ?
 
du style:         le bo kayak de bob"
palindromes trouvés:      ^       ^
 
si c'est le premier cas je vois pas pourquoi tu te préoccupes des espaces, sauf si ton prof t'as indiqué que tu devais "sauter" les espaces, donc qu'un "oh mon bo truc" soit testé comme "ohmonbotruc"....
 
dans ce cas l'algo est effectivement:
 
 
;positionnement à la fin  
 
fin<-deb  
 
tant que fin != 0  
    avancer fin  
 
si fin==deb
   chaine vide on quitte
 
reculer fin ; positionnement sur le dernier carc non nul
 
etiquette_boucle:
 
   tant que deb == espace  
     avancer deb  
 
   tant que fin == espace  
     reculer fin  
 
si deb==fin et adresse deb < adresse fin  
  avancer deb  
  reculer fin  
  boucler à etiquette
 
si deb==fin  
  c'est un palindrome  
 

Reply

Marsh Posté le 15-12-2002 à 14:02:15    

Ben encore heureux que tu es là  :jap:  
 
 
Alors : je dois faire le test "palindrome" sur toute la chaine et pas sur chaque mot séparément. Cependant, dans la chaine, je dois sauter les espaces ! De sorte que "aze r ty y tre za" soit bien un palindrome alors que ce n'est pas vraiment symétrique à première vue ("géométriquement" parlant ...).
 
Donc, je crois que l'algo que tu as proposé à la fin correspond bien à ce que je cherche à faire ! Et je pense que c'est grosso modo ce que mon programme fait ! Je vais essayer de le réexpliquer ! Parce que tu vois, je préfèrerais comprendre pourquoi le mien ne fonctionne pas ! Je pourrais naturellement faire d'autres versions, mais ça m'ennuie de ne pas comprendre pourquoi celui-ci ne va pas !
 
Donc, je reprend en détail ! J'espère que tu pourras trouver ce qui coince parce que je cale sérieusement !
 
.model small  
.stack  
.data  
   ac_intro DB "Veuillez entrer la chaine de caractères à tester : $"  
   ac_pos DB 0ah, 0dh, "La chaine que vous avez entré est un palindrome !$"  
   ac_neg DB 0ah, 0dh, "La chaine que vous avez entré n'est pas un palindrome !$"  
   ac_work DB 250, ?, 251 dup ('$';)
 
.code  
 
main :  
   mov ax, @data  
   mov ds, ax  
     
   mov ax, 0900h  
   lea dx, ac_intro  
   int 21h ;affichage du message d'intro  
 
   mov ax, 0a00h  
   lea dx, ac_work  
   int 21h

;Cette sous fonction du DOS permet de saisir une chaine avec un certain nombre de caractère maximum. Ce nombre est placé dans le premier octet du tableau ac_work (ici : 250). Elle place les caractères encodés dans le 3° octet et les suivants (j'ai prévu 251 emplacements). Elle renvoie en plus le nombre de caractère qui a été effectivement encodé par l'utilisateur et place ce nombre dans le second octet de ac_work (à la place du '?').


   mov si, 2  
   mov di, ac_work[1]  
   inc di  

;Le registre SI correspond à ton "adresse deb" (plus ou moins, car c'est en fait l'offset par rapport à l'adresse de ac_work) et DI à "adresse fin". Je place si sur le premier caractère de la chaine encodée (qui se trouve au 3° octet du tableau ac_work)(si je voulais pointer le 1° caractère, je mettrais si à 0, pour le 2°, si=1 et pour le 3°, si=2).
Pour di, je récupère le nombre de caractère encodés par l'utilisateur stocké dans le 2° octet du tableau ac_work (à la place du '?') et puisque le début de la chaine est en 2 et non en 0, j'ajoute 1 à di. D'après les tests que j'ai pu faire, si et di sont correctement initialisés.


 
until :  
   cmp si, di  
   jae fin1  
   cmp ac_work[si], 20h  
   je si_space  
   cmp ac_work[di], 20h  
   je di_space  
   mov dl, ac_work[di]  
   cmp ac_work[si], dl  
   jne fin2  
   dec di  
   inc si  
   jmp until  
 
si_space :  
   inc si  
   jmp until  
 
di_space :  
   dec di  
   jmp until
 

;Pour toute la boucle, voici ce que je fais :
boucle:
if (si >= di) {c'est un palindrome ;}
if (ac_work[si]==' ') {si = si + 1; retour à l'étiquette "boucle"}
if (ac_work[di]==' ') {di = di - 1; retour à l'étiquette "boucle"} /*De cette manière, j'ignore bien TOUS les espaces, où qu'ils soient*/
if (ac_work[si] == ac_work[di]) {si = si + 1; di = di - 1; retour à l'étiquette "boucle"}
else {ce n'est pas un palindrome}


 
 
fin1 :  
   mov ax, 0900h ; affichage du message de succès  
   lea dx, ac_pos  
   int 21h  
   jmp quit  
 
fin2 :  
   mov ax, 0900h ; affichage du message d'échec  
   lea dx, ac_neg  
   int 21h  
     
quit :  
   mov ax, 4c00h  
   int 21h  
 
end main
 
 
Voila ! Donc, je sais bien que je peux faire d'autres versions de ce programme, et c'est ce que je ferai si personne ne trouve mon erreur ! Mais j'aimerais vraiment bien comprendre pourquoi ceci ne fonctionne pas !
Merci pour ton aide (et celle des autres, s'il y en a un jour  :)  
 
:hello:

Reply

Marsh Posté le 15-12-2002 à 19:43:38    

je penses que tu pourrais réorganiser tes boucles pour plus de clarté....

Reply

Marsh Posté le 18-12-2002 à 13:10:48    

Salut,
 
D'après les quelques tests que j'ai réalisés, je dirai que DI n'est pas bien initialisé comme tu le penses.
 
C'est un registre 16 bits et tu places dedans le nombre de caractères lus, qui tient sur 1 octet.  
 
Ceci devrait arranger le problème:
 

Code :
  1. mov bx,offset ac_work
  2. mov al,[bx+1]
  3. mov ah,0
  4. mov di,ax
  5. inc di


 
Ce n'est peut-être pas très optimisé mais le prog que j'ai fait ainsi fonctionne.
 
J'espère t'avoir aidé.
 
@+

Reply

Marsh Posté le 08-01-2003 à 00:00:14    

Biglo a écrit :

Salut,
 
D'après les quelques tests que j'ai réalisés, je dirai que DI n'est pas bien initialisé comme tu le penses.
 
C'est un registre 16 bits et tu places dedans le nombre de caractères lus, qui tient sur 1 octet.  
 
Ceci devrait arranger le problème:
 

Code :
  1. mov bx,offset ac_work
  2. mov al,[bx+1]
  3. mov ah,0
  4. mov di,ax
  5. inc di


 
Ce n'est peut-être pas très optimisé mais le prog que j'ai fait ainsi fonctionne.
 
J'espère t'avoir aidé.
 
@+


 
 
Oups, je suis un peu en retard ^^
Mais effectivement, tu avais raison : c'était bien le problème que tu as souligné, le reste fonctionnait bien ^^
En fait, j'avais trouvé tout seul il y a quelques semaines ! J'aurais peut-être dû posté la réponse pour t'éviter de chercher inutilement  :( Je ne l'ai pas fait parce que mon problème n'avait pas eu un grand succès  :)
 
Donc, je répond surtout pour te dire merci d'avoir répondu à mon message et d'avoir essayé de m'aider :jap:


Message édité par yannick_frere le 08-01-2003 à 00:01:21
Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed