Nasm 32 - conversion hexa / décimal => division (32 bits) par 10

Soyez le premier à donner votre avis sur cette source.

Snippet vu 10 354 fois - Téléchargée 43 fois

Contenu du snippet

La conversion héxa => décimal s'effectue par divisions successives par 10.
Prenons l'exemple de la conversion de 255 (0xFF) :
255 / 10 = 25 dans eax + 5 dans edx
25/10 = 2 dans eax + 5 dans edx.
Il faut donc afficher dans l'ordre :
- le dernier quotient (<10) : 2
- le second reste : 5
- le premier reste : 5

Il y a probablement + simple. Toute suggestion sera la bienvenue.

Rappel : compilation sous NASM : nasm -f bin file.asm -o file.exe

Source / Exemple :


[ORG 0x0100]

[SEGMENT .data]
decimal db '0123456789'

[SEGMENT .text]
call vga_mode
mov eax,0xFF
call write_eax
call end

vga_mode:		; cls sur la console
mov al,00h
int 10h
ret

write_eax:
push eax			; On pousse les valeurs des registres utilisés
push ebx			; sur la pile afin de pouvoir les restaurer
push ecx			; après calcul.		
push edx
push si
mov ebx,0x0A		; Diviseur dans ebx : ici division par 10.
xor ecx,ecx		; On met ecx à 0.
label1:
xor edx,edx		; On met edx à 0.
div ebx			; Division de eax par ebx.
			; Lors d'une division avec registres
			; de 32 bits,le quotient est placé
			; dans eax, le reste dans edx.
push dx			; On pousse le reste sur la pile :
				
inc ecx			; Incrémentation de ecx pour connaître
			; le nombre de valeurs à récupérer sur la pile
			; lors de l'affichage du résultat de la
			; division en décimal
cmp eax,ebx		; Comparaison eax avec ebx :
jg label1			; si > on recommence
			; sinon, la division est terminée
push ax			; On pousse ax contenant le premier terme du résultat. 
label2:			; boucle pour affichage
pop si			; on récupère la valeur à afficher dans si
add si,decimal		; on l'additionne à l'offset de la chaîne décimal
			; pour obtenir l'offset du caractère à afficher.
mov al,[ds:si]		; On place la valeur à afficher dans al.
mov ah,0x0E		; fonction 0x0E interruption 10h pour affichage de al.
int 10h
dec ecx
cmp ecx,0x00		; On recommence jusqu'au second caractère.
jne label2
pop si			; Idem : affichage du premier caractère.
add si,decimal
mov al,[ds:si]
mov ah,0x0E
int 10h
pop si
pop edx			; On restaure les registres avec leur valeur initiale.
pop ecx
pop ebx
pop eax
ret

end: 			; Fin correcte du programme.
mov ax,0x4C00
int 21h
ret

A voir également

Ajouter un commentaire Commentaires
BruNews Messages postés 21041 Date d'inscription jeudi 23 janvier 2003 Statut Modérateur Dernière intervention 21 août 2019
24 sept. 2004 à 12:34
Salut,

div est une calamite en terme de performances, quand le diviseur est connu (constante) on multiplie par son inverse.
Exemple divise 10 sur registres 32 bits:
mov eax, dividend
mov ecx, 3435973837
mul ecx
shr edx, 3
EDX = RESULT

Bonne continuation.
ToutEnMasm Messages postés 591 Date d'inscription jeudi 28 novembre 2002 Statut Membre Dernière intervention 13 décembre 2022 3
25 sept. 2004 à 16:43
salut,
La méthode de masm32 pour passer d'un DW a une chaine de caractere ascii, dwtoa
ToutEnMasm


; #########################################################################

; ---------------------------------------------------------------
; This procedure was originally written by Tim Roberts
;
; Part of this code has been optimised by Alexander Yackubtchik
; ---------------------------------------------------------------

.386
.model flat, stdcall ; 32 bit memory model
option casemap :none ; case sensitive

.code

; #########################################################################

dwtoa proc dwValue:DWORD, lpBuffer:DWORD

; -------------------------------------------------------------
; convert DWORD to ascii string
; dwValue is value to be converted
; lpBuffer is the address of the receiving buffer
; EXAMPLE:
; invoke dwtoa,edx,ADDR buffer
;
; Uses: eax, ecx, edx.
; -------------------------------------------------------------

push ebx
push esi
push edi

mov eax, dwValue
mov edi, [lpBuffer]

or eax,eax
jnz sign

zero:
mov word ptr [edi],30h
jmp dw2asc

sign:
jns pos
mov byte ptr [edi],'-'
neg eax
inc edi

pos:
mov ecx,429496730
mov esi, edi

.while (eax > 0)
mov ebx,eax
mul ecx
mov eax,edx
lea edx,[edx*4+edx]
add edx,edx
sub ebx,edx
add bl,'0'
mov [edi],bl
inc edi
.endw

mov byte ptr [edi], 0 ; terminate the string

; We now have all the digits, but in reverse order.

.while (esi < edi)
dec edi
mov al, [esi]
mov ah, [edi]
mov [edi], al
mov [esi], ah
inc esi
.endw

dw2asc:

pop edi
pop esi
pop ebx

ret

dwtoa endp

; #########################################################################

end
BruNews Messages postés 21041 Date d'inscription jeudi 23 janvier 2003 Statut Modérateur Dernière intervention 21 août 2019
25 sept. 2004 à 17:03
Cas typique de proc non optimisee qui ressemble fort a ce que produisait un vieux compilo C.*
A quoi sert l'empilage et depilage des 2 params ???
Ils ne sont lus qu'1 seule fois donc devaient etre passes en registres, 6 cycles de gagnes rien que la.
cs_Nikro Messages postés 1 Date d'inscription vendredi 24 septembre 2004 Statut Membre Dernière intervention 26 septembre 2004
26 sept. 2004 à 00:45
Merci pour ces commentaires qui contriburont à m'orienter vers une meilleure vision des choses.
C'est ma première routine en assembleur, excepté le Hello World de prise en main.
J'essaie en fait de programmer un convertisseur multi-base pour me familiariser avec l'assembleur.
Visiblement ça prendra du temps, je le prendrai.
@++.
vecchio56 Messages postés 6535 Date d'inscription lundi 16 décembre 2002 Statut Membre Dernière intervention 22 août 2010 13
28 sept. 2004 à 18:22
mov eax, dividend
mov ecx, 3435973837
mul ecx
shr edx, 3

J'ai pas du tout compris ca!

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.