Imprimer entier à console ensemble dans x86
Question
Quand j'ajoute deux valeurs dans l'assemblage 16 bits, ce qui est la meilleure façon d'imprimer le résultat à la console?
En ce moment j'ai ce code:
;;---CODE START---;;
mov ax, 1 ;put 1 into ax
add ax, 2 ; add 2 to ax current value
mov ah,2 ; 2 is the function number of output char in the DOS Services.
mov dl, ax ; DL takes the value.
int 21h ; calls DOS Services
mov ah,4Ch ; 4Ch is the function number for exit program in DOS Services.
int 21h ; function 4Ch doesn't care about anything in the registers.
;;---CODE END---;;
Je pense que la valeur dl doit être en code ASCII, mais je ne suis pas sûr de savoir comment convertir la valeur de hache après addition en ASCII.
La solution
Vous voulez essentiellement à diviser par 10, imprimer le reste (un chiffre), puis répéter avec le quotient.
; assume number is in eax
mov ecx, 10
loophere:
mov edx, 0
div ecx
; now eax <-- eax/10
; edx <-- eax % 10
; print edx
; this is one digit, which we have to convert to ASCII
; the print routine uses edx and eax, so let's push eax
; onto the stack. we clear edx at the beginning of the
; loop anyway, so we don't care if we much around with it
push eax
; convert dl to ascii
add dl, '0'
mov ah,2 ; 2 is the function number of output char in the DOS Services.
int 21h ; calls DOS Services
; now restore eax
pop eax
; if eax is zero, we can quit
cmp eax, 0
jnz loophere
Comme une note de côté, vous avez un bug dans votre code ici:
mov ax, 1 ;put 1 into ax
add ax, 2 ; add 2 to ax current value
mov ah,2 ; 2 is the function number of output char in the DOS Services.
mov dl, ax ; DL takes the value.
Vous mettez 2
à ah
, puis vous mettez ax
dans dl
. Vous junking essentiellement ax
avant de l'imprimer.
Vous avez également une différence de taille puisque dl
est de 8 bits de large et ax
est large de 16 bits.
Ce que vous devez faire est de retourner les deux dernières lignes et fixer la différence de taille:
mov ax, 1 ;put 1 into ax
add ax, 2 ; add 2 to ax current value
mov dl, al ; DL takes the value.
mov ah,2 ; 2 is the function number of output char in the DOS Services.
Autres conseils
Juste fixant l'ordre des codes de @Nathan Fellman
PrintNumber proc
mov cx, 0
mov bx, 10
@@loophere:
mov dx, 0
div bx ;divide by ten
; now ax <-- ax/10
; dx <-- ax % 10
; print dx
; this is one digit, which we have to convert to ASCII
; the print routine uses dx and ax, so let's push ax
; onto the stack. we clear dx at the beginning of the
; loop anyway, so we don't care if we much around with it
push ax
add dl, '0' ;convert dl to ascii
pop ax ;restore ax
push dx ;digits are in reversed order, must use stack
inc cx ;remember how many digits we pushed to stack
cmp ax, 0 ;if ax is zero, we can quit
jnz @@loophere
;cx is already set
mov ah, 2 ;2 is the function number of output char in the DOS Services.
@@loophere2:
pop dx ;restore digits from last to first
int 21h ;calls DOS Services
loop @@loophere2
ret
PrintNumber endp
L'algorithme de base est la suivante:
divide number x by 10, giving quotient q and remainder r
emit r
if q is not zero, set x = q and repeat
Notez que cela donnera les chiffres dans l'ordre inverse, de sorte que vous allez probablement vouloir remplacer l'étape « emit » avec quelque chose qui stocke chaque chiffre, afin que vous puissiez plus tard itérer en sens inverse sur les chiffres enregistrés.
En outre, notez que pour convertir un nombre binaire entre 0 et 9 (décimal) à ascii, ajoutez simplement le code ascii pour « 0 » (qui est 48) au nombre.
mov dl, ax
Cela ne fonctionnera pas comme dl
et ax
ont des tailles différentes de bits. Ce que vous voulez faire est de créer une boucle dans laquelle on divise la valeur 16 bits 10, rappelez-vous le reste sur la pile, puis continuer la boucle avec le résultat de la division entière. Lorsque vous atteignez un résultat de 0, nettoyer le chiffre de la pile par chiffre, en ajoutant 48 aux chiffres pour les transformer en chiffres ASCII, puis les imprimer.