begin process at 2010 02 10 00:47:34
  Trouver un code source :
 
dans
 
Accueil > 

Code

 > 

Applications ms-dos

 > NASM 32 - CONVERSION HEXA / DÉCIMAL => DIVISION (32 BITS) PAR 10

NASM 32 - CONVERSION HEXA / DÉCIMAL => DIVISION (32 BITS) PAR 10


 Information sur la source

Note :
10 / 10 - par 1 personne
10,00 / 10

  • 1

  • 2

  • 3

  • 4

  • 5

  • 6

  • 7

  • 8

  • 9

  • 10
Catégorie :Applications ms-dos Niveau :Débutant Date de création :24/09/2004 Vu :5 938

Auteur : Nikro

Ecrire un message privé
Commentaire sur cette source (8)
Ajouter un commentaire et/ou une note

 Description

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

  • [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
[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



 Sources de la même categorie

Source avec une capture LECTURE CHAINE ET COMPARAISON[MASM] par w4kfu
Source avec une capture LECTURE TOUCHE CLAVIER[MASM] par w4kfu
Source avec Zip UN RESOLVEUR SUDUKO AVEC ASSEMBLEUR NASM par msavyo1
Source avec Zip TESTEUR DE COMPATIBILITTÉ VESA (SUPER VGA) par bofur
Source avec Zip COMMUNICATION SÉRIE RS232 AVEC INTERRUPTIONS par bouffa

Commentaires et avis

Commentaire de BruNews le 24/09/2004 12:34:46 administrateur CS

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.

Commentaire de ToutEnMasm le 25/09/2004 16:43:52

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

Commentaire de BruNews le 25/09/2004 17:03:52 administrateur CS

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.

Commentaire de Nikro le 26/09/2004 00:45:39

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.
@++.

Commentaire de vecchio56 le 28/09/2004 18:22:34 administrateur CS

mov   eax, dividend
mov   ecx, 3435973837
mul   ecx
shr   edx, 3

J'ai pas du tout compris ca!

Commentaire de BruNews le 28/09/2004 18:50:25 administrateur CS

Vaut mieux faire un 'mul' que un 'div' si on connait le diviseur. Vois que dans le dwtoa de MASM32 c'est aussi fait de cette maniere, avec d'autres valeurs mais le but est toujours de mettre un mul au lieu d'un div.

Commentaire de vecchio56 le 28/09/2004 18:58:50 administrateur CS

Oui mais pourquoi cela fait il division par 10?

Commentaire de BruNews le 28/09/2004 19:09:23 administrateur CS

C'est calcule par un algo infernal.
Je te send mon utilitaire qui te calculera tout cela.

 Ajouter un commentaire




Nos sponsors


Sondage...

CalendriCode

Février 2010
LMMJVSD
1234567
891011121314
15161718192021
22232425262728

Consulter la suite du CalendriCode

 
Développement réalisé par Nicolas SOREL (Nix) avec l'aide de : Cyril DURAND et Emmanuel (EBArtSoft), Merci à Vincent pour ses précieux conseils.
CodeS-SourceS.com© Toute reproduction même partielle est interdite sauf accord écrit du Webmaster
CodeS-SourceS.com© est une marque déposée tous droits réservés

Google Coop CodeS-SourceS Google Coop CodeS-SourceS
Temps d'éxécution de la page : 0,265 sec (3)

Nous contacter | Annoncer sur CodeS-SourceS | Mentions légales