Ce code est 16bits mode réel.
Il permet de convertir une chaine de caractères de DS:SI en un nombre dans AX pour plusieurs bases :
-> Décimale
-> Hexadécimale
-> Binaire
-> Octale
Le code a été dévellopé avec TASM.
Ce code est l'inverse de mon code
http://www.asmfr.com/code.aspx?ID=30896
Source / Exemple :
MODEL SMALL
STACK 100h
DATA SEGMENT
ChaineMax DB 25
ChaineLen DB ?
Chaine DB 25 DUP('$')
CRLF DB 13,10,'$'
DATA ENDS
CODE SEGMENT
ASSUME CS:CODE,DS:DATA
Scanf MACRO Buff
MOV AH,0Ah
LEA DX,Buff
INT 21h
ENDM
Printf MACRO BuffC
MOV AH,09h
LEA DX,BuffC
INT 21h
ENDM
TerminalChar EQU '$'
;inverse une chaine
;==================
;DS:SI : adresse du début de la chaine
;DS:DI : adresse de fin de la chaine (avant le caractère de terminaison de chaine)
InverseChaine PROC
;on inverse la chaine puisque l'on a calculé la représentation à l'envers (méthode des divisions successives)
boucleInv:
;on échange [DI] <-> [SI]
MOV AL,byte ptr [DI]
MOV AH,byte ptr [SI]
MOV byte ptr [SI],AL
MOV byte ptr [DI],AH
;octets suivants
DEC DI
INC SI
;tant que l'on n'a pas tout inversé (SI < DI)
CMP SI,DI
JL boucleInv
RET
InverseChaine ENDP
;convertit un nombre en sa représentation décimale (chaine)
;==========================================================
;DS:SI : adresse où stocker la chaine
;AX : nombre à convertir
;CX=1 : nombre signé, CX=0 : non signé
ChaineDec PROC
;sauvegarde des registres
PUSH DX
PUSH DI
PUSH CX
PUSH SI
PUSH AX
;si le nombre est non signé
CMP CX,0
;on passe à la conversion
JE PasSigne
;sinon, on calcule la valeur absolue
;si AX est >= 0
CMP AX,0
JGE PasSigne
;valeur absolue de AX
NEG AX
;on ajoute le signe
MOV byte ptr [SI],'-'
;on passe au caractère suivant
INC SI
PasSigne:
;sauvegarde de l'offset de départ de la chaine
MOV DI,SI
;mot de poids fort dans le dividende
XOR DX,DX
;tant qu'il y a des chiffres à ajouter
boucleDec:
;CX=AX pour le calcule du reste de division
MOV CX,AX
;division par 10 : algo de Terje Mathisen
;========================================
MOV DX,0CCCDh
;on divise AX par 10 : résultat dans DX
MUL DX
SHR DX,3
;========================================
;on sauvegarde de résultat dans AX
MOV AX,DX
;on calcule le reste de la division de CX(=AX avant division)
SHL DX,1 ;DX = quotient * 2
SUB CX,DX ;CX = divende - quotient * 2
SHL DX,2 ;DX = quotient * 2 * 4 = quotient * 8
SUB CX,DX ;CX = dividende - quotient * 2 - quotient * 8 = dividende - quotient * 10 = reste
;on ajoute '0'=48 pour convertir le chiffre en code ascii correspondant
ADD CX,'0'
;on le copie dans la chaine
MOV byte ptr [DI],CL
;on passe au caractère suivant
INC DI
;si le quotient est nul, on a fini la conversion
CMP AX,0
JA boucleDec
;on met un caractère de fin de chaine
MOV byte ptr [DI],TerminalChar
;on se place avant le caractère de la fin de chaine
DEC DI
;on inverse la chaine puisque l'on a calculé la représentation à l'envers (méthode des divisions successives)
CALL InverseChaine
;récupération des registres
POP AX
POP SI
POP CX
POP DI
POP DX
RET
ChaineDec ENDP
;convertit une chaine de caractère (décimale) en nombre
;======================================================
;DS:SI : chaine représentant le nombre décimal
;renvoie le nombre dans AX
DecChaine PROC
;sauvegarde des registres utilisés
PUSH BX
PUSH CX
PUSH SI
;init du nombre à 0
XOR AX,AX
;init de BH (et BL) à 0
XOR BX,BX
boucleDecC:
;on lit un caractrère ascii de la chaine
MOV BL,byte ptr [SI]
;on lui retranche le code ascii de '0' pour se placer dans la plage décimale 0-9
SUB BL,'0'
;si le caractère est en dessous de '0', erreur ou fin de chaine
JL FinDecC
;si le caractère est en dessus de '9', erreur ou fin de chaine
CMP BL,9
JA FinDecC
;on multiplie AX par 10 pour donner leur "poids" aux chiffres précédents
;=======================================================================
MOV CX,AX ;CX=AX
SHL CX,3 ;CX = CX * 2 ^ 3 = AX * 8
ADD AX,AX ;AX = AX + AX = AX * 2
ADD AX,CX ;AX = AX + CX = AX * 2 + AX * 8 = AX * 10
;=======================================================================
;on ajoute le valeur du chiffre courant à AX
ADD AX,BX
;caractère suivant
INC SI
;on boucle tant que l'on ne sort pas avec les conditions d'erreur ou de fin de chaine
JMP boucleDecC
FinDecC:
;on restaure les registres
POP SI
POP CX
POP BX
RET
DecChaine ENDP
;convertit une chaine de caractère (hexadécimale) en nombre
;==========================================================
;DS:SI : chaine représentant le nomre hexadécimal
;renvoie le nombre dans AX
HexChaine PROC
;sauvegarde des registres utilisés
PUSH BX
PUSH SI
;init du nombre à 0
XOR AX,AX
;init de BH (et BL) à 0
XOR BX,BX
boucleHexC:
;on lit un caractrère ascii de la chaine
MOV BL,byte ptr [SI]
;on lui retranche le code ascii de '0' pour se placer dans la plage décimale 0-9
SUB BL,'0' ;BL = caractère - '0'
;si le caractère est en dessous de '0', erreur ou fin de chaine
JL FinHexC
;si le caractère est entre '0' et '9', on convertit
CMP BL,9
JBE SuiteHexC
;BL = caractère - '0'
;on lui retranche le code ascii de 'A'(-'0'-10) pour se placer dans la plage décimale 10-15
SUB BL,'A'-'0'-10 ;BL = caractère - '0' - ('A' - '0' - 10) = caractère - 'A' + 10
;si le caractère est en dessous de 'A', erreur ou fin de chaine
JL FinHexC
;si le caractère est entre 'A' et 'F', on convertit
CMP BL,15
JBE SuiteHexC
;BL = caractère - 'A' + 10
;on lui retranche le code ascii de 'a'(-'A') pour se placer dans la plage décimale 10-15
SUB BL,'a'-'A' ;BL = caractère - 'A' + 10 - ('a' - 'A') = caractère - 'a' + 10
;si le caractère est en dessous de 'a', erreur ou fin de chaine
JL FinHexC
;si le caractère est au dessus de 'f', erreur ou fin de chaine
CMP BL,15
JA FinHexC
SuiteHexC:
;on multiplie AX par 16 pour donner leur "poids" aux chiffres précédents
;=======================================================================
SHL AX,4 ;AX = AX * 2 ^ 4 = AX * 16
;=======================================================================
;on ajoute le valeur du chiffre courant à AX
ADD AX,BX
;caractère suivant
INC SI
;on boucle tant que l'on ne sort pas avec les conditions d'erreur ou de fin de chaine
JMP boucleHexC
FinHexC:
;on restaure les registres
POP SI
POP BX
RET
HexChaine ENDP
;convertit une chaine de caractère (binaire) en nombre
;=====================================================
;DS:SI : chaine représentant le nombre binaire
;renvoie le nombre dans AX
BinChaine PROC
;sauvegarde des registres utilisés
PUSH BX
PUSH SI
;init du nombre à 0
XOR AX,AX
;init de BH (et BL) à 0
XOR BX,BX
boucleBinC:
;on lit un caractrère ascii de la chaine
MOV BL,byte ptr [SI]
;on lui retranche le code ascii de '0' pour se placer dans la plage décimale 0-1
SUB BL,'0'
;si le caractère est en dessous de '0', erreur ou fin de chaine
JL FinBinC
;si le caractère est en dessus de '1', erreur ou fin de chaine
CMP BL,1
JA FinBinC
;on multiplie AX par 2 pour donner leur "poids" aux chiffres précédents
;======================================================================
ADD AX,AX ;AX = AX + AX = AX * 2
;======================================================================
;on ajoute le valeur du chiffre courant à AX
ADD AX,BX
;caractère suivant
INC SI
;on boucle tant que l'on ne sort pas avec les conditions d'erreur ou de fin de chaine
JMP boucleBinC
FinBinC:
;on restaure les registres
POP SI
POP BX
RET
BinChaine ENDP
;convertit une chaine de caractère (octal) en nombre
;===================================================
;DS:SI : chaine représentant le nomre octal
;renvoie le nombre dans AX
OctChaine PROC
;sauvegarde des registres utilisés
PUSH BX
PUSH SI
;init du nombre à 0
XOR AX,AX
;init de BH (et BL) à 0
XOR BX,BX
boucleOctC:
;on lit un caractrère ascii de la chaine
MOV BL,byte ptr [SI]
;on lui retranche le code ascii de '0' pour se placer dans la plage décimale 0-7
SUB BL,'0'
;si le caractère est en dessous de '0', erreur ou fin de chaine
JL FinOctC
;si le caractère est en dessus de '7', erreur ou fin de chaine
CMP BL,7
JA FinOctC
;on multiplie AX par 8 pour donner leur "poids" aux chiffres précédents
;=======================================================================
SHL AX,3 ;AX = AX * 2 ^ 3 = AX * 8
;=======================================================================
;on ajoute le valeur du chiffre courant à AX
ADD AX,BX
;caractère suivant
INC SI
;on boucle tant que l'on ne sort pas avec les conditions d'erreur ou de fin de chaine
JMP boucleOctC
FinOctC:
;on restaure les registres
POP SI
POP BX
RET
OctChaine ENDP
Deb:
;init de DS
MOV AX,DATA
MOV DS,AX
;saisie chaine de caractères
Scanf ChaineMax
;conversion
LEA SI,Chaine
CALL HexChaine
;conversion en décimal non signé
XOR CX,CX
CALL ChaineDec
;affichage
Printf CRLF
Printf Chaine
;exit 0
MOV AL,0
MOV AH,4Ch
INT 21h
CODE ENDS
END Deb
Conclusion :
N'hésitez pas à commenter et à noter...
Le code est commenté et optimisé (principalement les multiplications) dans les limites de mes connaissances...
Vous n'êtes pas encore membre ?
inscrivez-vous, c'est gratuit et ça prend moins d'une minute !
Les membres obtiennent plus de réponses que les utilisateurs anonymes.
Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.
Le fait d'être membre vous permet d'avoir des options supplémentaires.