Печатать целое число для консоли в сборке x86
Когда я добавляю два значения в 16-битной сборке, что лучший способ распечатать результат на консоли?
В данный момент у меня есть этот код:
;;---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---;;
Я думаю, что значение dl должно быть в коде ASCII, но я не уверен, как преобразовать значение ax после добавления в ASCII.
Ответы
Ответ 1
В основном вы хотите разделить на 10, распечатать остаток (одну цифру), а затем повторить с частным.
; 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 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
В качестве побочной заметки у вас есть ошибка в вашем коде прямо здесь:
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.
Вы помещаете 2
в ah
, а затем вы помещаете ax
в dl
. В основном вы используете ax
перед печатью.
У вас также есть несоответствие размера, так как dl
имеет ширину 8 бит, а ax
- 16 бит.
Что вам нужно сделать, это перевернуть последние две строки и исправить несоответствие размера:
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.
Ответ 2
Основной алгоритм:
divide number x by 10, giving quotient q and remainder r
emit r
if q is not zero, set x = q and repeat
Обратите внимание, что это приведет к получению цифр в обратном порядке, поэтому вам, вероятно, захочется заменить шаг "испускать" чем-то, что хранит каждую цифру, чтобы впоследствии вы могли перебирать обратно по сохраненным цифрам. /p >
Также обратите внимание, что для преобразования двоичного числа между 0 и 9 (десятичным) в ascii просто добавьте код ascii для '0' (который равен 48) к числу.
Ответ 3
Просто исправление порядка кода @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 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
Ответ 4
mov dl, ax
Это не будет работать, поскольку dl
и ax
имеют разные размеры бит. То, что вы хотите сделать, это создать цикл, в котором вы разделите значение 16 бит на 10, запомните остальную часть в стеке и затем продолжите цикл с результатом целочисленного деления. Когда вы достигнете результата 0, очистите стек цифрами по цифре, добавив 48 к цифрам, чтобы превратить их в цифры ASCII, а затем распечатайте их.