IMPRIMENTO INTEIRO PARA CONSOLAR NA COMPLEMA X86
Pergunta
Quando adiciono dois valores na montagem de 16 bits, qual é a melhor maneira de imprimir o resultado do console?
No momento eu tenho este código:
;;---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---;;
Eu acho que o valor de DL deve estar no código ASCII, mas não tenho certeza de como converter o valor do AX após a adição em ASCII.
Solução
Você basicamente deseja dividir por 10, imprimir o restante (um dígito) e depois repetir com o quociente.
; 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
Como nota lateral, você tem um bug no seu código aqui:
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.
Você coloca 2
dentro ah
, e então você coloca ax
dentro dl
. Você está basicamente, está bem ax
antes de imprimi -lo.
Você também tem uma incompatibilidade de tamanho desde dl
tem 8 bits de largura e ax
tem 16 bits de largura.
O que você deve fazer é virar as duas últimas linhas e consertar o tamanho de incompatibilidade:
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.
Outras dicas
Basta consertar a ordem do código do @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
O algoritmo básico é:
divide number x by 10, giving quotient q and remainder r
emit r
if q is not zero, set x = q and repeat
Observe que isso renderá os dígitos na ordem inversa, então você provavelmente deseja substituir a etapa "emitir" por algo que armazena cada dígito, para que você possa iterar posteriormente no reverso sobre os dígitos armazenados.
Além disso, observe que, para converter um número binário entre 0 e 9 (decimal) em ASCII, basta adicionar o código ASCII para '0' (que é 48) ao número.
mov dl, ax
Isso não vai funcionar como dl
e ax
tem tamanhos de bits diferentes. O que você deseja fazer é criar um loop no qual você divida o valor de 16 bits por 10, lembre -se do restante na pilha e continue o loop com o resultado da divisão inteira. Quando você atingir o resultado de 0, limpe o dígito da pilha por dígito, adicionando 48 aos dígitos para transformá -los em dígitos ASCII e imprimi -los.