soucis avec une chaine de caractères

Pour discuter de l'assembleur
Thierry 31
Messages : 25
Inscription : mar. 08/févr./2005 21:44
Localisation : Toulouse

soucis avec une chaine de caractères

Message par Thierry 31 »

toujours dans ma fonction de conversion décimal-> binaire

j'ai rajouté qq lignes pour éliminer les 0 superflus, ça fonctionne plustôt bien sauf avec qq valeurs : 1, 2, 10, 100010 ect

la conversion est correcte mais la chaine retournée est plus longue que nécéssaire ... :mad:

si quelqu'un a une idée :?:

Code : Tout sélectionner

Procedure.s Binaire32b(decimal.l)
resultat.s=""

MOV eax,[esp]
MOV ebx,[esp+4]
MOV ecx,1
XOR dh,dh                   ; initialisation de l'indicateur du premier bit à 1
                            ; permettra de ne pas porter une chaine de 0 précedent
                            ; la conversion
CLC                         ; mise à 0 de cf

bouclefor: 
CMP ecx,32
JA l_finbouclefor 	
XOR dl,dl                   ; mise à 0 de dl
RCL eax,1                   ; extraction du ecx ième bit
ADC dl,0                    ; dl <-- 0 + cf

        ; teste si dl=o et dh=0 alors décrémente ebx et sauter vers saute:
CMP dh,0
JNZ l_sortietest            ; si dh<>0 sotir du test sinon instruction suivante
CMP dl,0
JNZ l_sortietest            ; si dl<>0 sortir du test sinon instruction suivante
DEC ebx                     ; si on arrive ici c'est que dl et dh sont nuls
JMP l_saute                 ; permettra d'éliminer les 0 inutiles en début de chaine

sortietest:
CMP dl,0  					
JE l_ajout0 
MOV dh, 1                   ; mise à 1 de dh tous les bits suivants seront pris en compte
MOV byte [ebx-1+ecx], 49    ; 49 ascii de 1
JMP l_saute														
ajout0:
MOV byte [ebx-1+ecx], 48    ; ascii de 0

saute:
INC ecx																
JMP l_bouclefor 												
finbouclefor:

ProcedureReturn resultat
EndProcedure

OpenConsole()
PrintN ("entrez un nombre de type long: ")
valeur.l=Val(Input())
PrintN("")
PrintN(Binaire32b(valeur))
PrintN("longueur de la chaine retournee: "+Str(Len(binaire32b(valeur))))
Input()
PrintN("avec la fonction PureBasic Bin")
PrintN(Bin(valeur))
PrintN("longueur de la chaine retournee par Bin: "+Str(Len(Bin(valeur))))
Input()
CloseConsole()
Debug binaire32b(valeur)
Debug "longueur de la chaine retournee: "+Str(Len(binaire32b(valeur)))
Debug "avec la fonction PureBasic Bin"+Bin(valeur)
Debug "longueur de la chaine retournee par Bin: "+Str(Len(Bin(valeur)))
End
si on retire les tests aprés

Code : Tout sélectionner

ADC dl,0                    ; dl <-- 0 + cf
tous se passe bien, sauf des 0 précédants la conversion

voilà voilà
Lna
Messages : 181
Inscription : mar. 21/juin/2005 11:11

Message par Lna »

Salut Thierry,

Tu n'as pas tenu compte de la réservation mémoire pour le traitement mémoire, ce qui va remettre en cause l'algorithme pensé initialement.

Code : Tout sélectionner

Procedure.s Binaire32b(decimal.l) 

[color=red]resultat.s=Space(32)        ; *** < ne pas écrire au hasard dans la mémoire sans avoir la certitude d'avoir l'espace pour>

MOV eax,[esp] 
MOV ebx,[esp+4] 
MOV ecx,1 
XOR dh,dh                   ; initialisation de l'indicateur du premier bit à 1 
                            ; permettra de ne pas porter une chaine de 0 précedent 
                            ; la conversion 
CLC                         ; mise à 0 de cf 

bouclefor: 
CMP ecx,32 
JA l_finbouclefor     
XOR dl,dl                   ; mise à 0 de dl 
RCL eax,1                   ; extraction du ecx ième bit 
ADC dl,0                    ; dl <-- 0 + cf 

        ; teste si dl=o et dh=0 alors décrémente ebx et sauter vers saute: 
CMP dh,0 
JNZ l_sortietest            ; si dh<>0 sotir du test sinon instruction suivante 
CMP dl,0 
JNZ l_sortietest            ; si dl<>0 sortir du test sinon instruction suivante 
DEC ebx                     ; si on arrive ici c'est que dl et dh sont nuls 
JMP l_saute                 ; permettra d'éliminer les 0 inutiles en début de chaine 

sortietest: 
CMP dl,0                  
JE l_ajout0 
MOV dh, 1                   ; mise à 1 de dh tous les bits suivants seront pris en compte 
MOV byte [ebx-1+ecx], 49    ; 49 ascii de 1 
JMP l_saute                                           
ajout0: 
MOV byte [ebx-1+ecx], 48    ; ascii de 0 

saute: 
INC ecx                                                 
JMP l_bouclefor                                      
finbouclefor: 

resultat=Rtrim(resultat)    ; *** <Efface les espaces latéraux droits>
IF resultat=""
  ProcedureReturn "0"       ; *** <pour que le cas de la valeur 0 pour retourner un caractère et obtenir 1 par le Len)
ENDIF

ProcedureReturn resultat

EndProcedure 
Le plus simple serait de tester chaque bit à l'aide d'un TEST qui correspond à un AND, avec la valeur $80000000 pour tester le bit de poids fort, mais aussi commencer à partir du bit de poids fort de la valeur pour éliminer les 0. En occasionnant les décalages à gauche, pour transformer chaque bit en "0" ou "1". Pour la fin, il est possible de terminer par un 0, si PureBasic le permet dans sa gestion des chaînes. Sinon une allocation mémoire fixe le fera. Ne pas oublier de régler le cas du 0.

Comme tu as déjà de bonnes notions, tu feras cela sans problèmes. :wink:

A +
Thierry 31
Messages : 25
Inscription : mar. 08/févr./2005 21:44
Localisation : Toulouse

désolé pour le retard

Message par Thierry 31 »

j'ai été absent du forum qq temps (petitou trés malade), je te remercie pour ton aide. :D
Thierry 31
Messages : 25
Inscription : mar. 08/févr./2005 21:44
Localisation : Toulouse

suite et fin?

Message par Thierry 31 »

la même chose revue et corrigée:

Code : Tout sélectionner

Procedure.s Binaire32b(decimal.l)
resultat.s=""

!MOV eax, dword[esp]            ; eax <-- decimal par [esp]
!MOV ebx, dword[esp+4]          ; ebx <-- adresse de decimal.l
!CMP eax, 0                     ; test si decimal=0
!JNZ principale                 ; si decimal<> 0 sauter à principale
!MOV byte [ebx], 48             ; ajout de "0"
!MOV byte [ebx+1], 0            ; ajout de "NUL" en fin de chaine
ProcedureReturn resultat

!principale:
!BSR ecx, eax                   ; ecx <-- position du premier bit de poids fort à 1 (31---0)
!bsr edx, eax                   ; ecx <-- position du premier bit de poids fort à 1 (31---0)
!INC ecx                        ; pour les besoins de la boucle
!repete:                        ; début dela boucle
!CMP ecx,0
!JE finrepete
  !RCR eax,1                    ; décalage de 1 bit vers la droite --> CF
	!JC adchar1                 ; test de CF si =1 saut vers adchar1: sinon inst suivante
	!MOV byte [ebx-1+ecx], 48   ; ajout de "0"
	!JMP suite                  ; saut vers suite:
	!adchar1:                   ; si CF=1
	!MOV byte [ebx-1+ecx], 49   ; ajout de "1"
	!suite:
!DEC ecx
!JMP repete
!finrepete:                     ; fin de la boucle

!MOV byte [ebx+1+edx], 0        ; ajout de "NUL" en fin de chaine
ProcedureReturn resultat
EndProcedure

OpenConsole()
valeur.l=Val(Input())
PrintN("")
PrintN("retour par Binaire32b: "+Binaire32b(valeur))
PrintN("longueur parBinaire32b: "+Str(Len(Binaire32b(valeur))))
PrintN("")
PrintN("retour par Bin: "+Bin(valeur))
PrintN("longueur par Bin: "+Str(Len(Bin(valeur))))
Input()
CloseConsole()

End
à priori je pense avoir réglé les pb précédents.

je vais essayer de créer une lib pour voir comment ça fonctionne à l'aide des tuts de Denis.
Répondre