Вывести целое число на консоль в сборке x86 - PullRequest
7 голосов
/ 22 ноября 2010

Когда я добавляю два значения в 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.

Ответы [ 4 ]

12 голосов
/ 22 ноября 2010

Как правило, вы хотите разделить на 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'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

Как примечание, у вас есть ошибка в вашем коде прямо здесь:

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.
5 голосов
/ 28 апреля 2011

Просто исправим порядок кода @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
4 голосов
/ 22 ноября 2010

Основной алгоритм:

divide number x by 10, giving quotient q and remainder r
emit r
if q is not zero, set x = q and repeat 

Обратите внимание, что это приведет к получению цифр в обратном порядке, поэтому вы, вероятно, захотите заменить шаг "emit" чем-то, что хранит каждую цифру, чтобы впоследствии вы могли выполнять итерацию в обратном порядке по сохраненным цифрам.

Также обратите внимание, что для преобразования двоичного числа от 0 до 9 (десятичного) в ascii просто добавьте к числу код ascii для «0» (который равен 48).

1 голос
/ 22 ноября 2010
mov dl, ax

Это не будет работать, поскольку dl и ax имеют разные размеры битов. Что вы хотите сделать, это создать цикл, в котором вы делите 16-битное значение на 10, запоминаете остаток в стеке, а затем продолжаете цикл с результатом целочисленного деления. Когда вы получите результат 0, очистите стопку цифрой за цифрой, добавив 48 к цифрам, чтобы превратить их в цифры ASCII, а затем напечатайте их.

...