在x86程序集中将整数打印到控制台

pac*_*an. 7 assembly dos 16-bit

当我在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---;;
Run Code Online (Sandbox Code Playgroud)

我认为dl值应该是ASCII码,但我不确定如何在添加到ASCII后转换ax值.

Nat*_*man 13

你基本上想要除以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
Run Code Online (Sandbox Code Playgroud)

作为旁注,您的代码中有一个错误:

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.
Run Code Online (Sandbox Code Playgroud)

你把2ah,然后你把axdl.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.
Run Code Online (Sandbox Code Playgroud)

  • 是的。我想我在此处发表评论并继续查看其他答案之后注意到了同样的事情。该评论已被接受并得到大力支持,因此它仍然应该得到修复,因此我决定保留该评论。 (2认同)

sid*_*don 5

只是固定@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
Run Code Online (Sandbox Code Playgroud)

  • 第一个循环中的“push axe”/“pop axe”毫无意义,并且在循环中与推动数字相结合时会分散注意力。`add dl, '0'` 不影响 AX。(与 Nathan 的版本相比,您将“int 21h”调用移出第一个循环,但没有删除 AX 的保存/恢复)。堆栈上有数字的两个循环是实现此目的的一种方法,但向后存储到缓冲区通常很好,就像 Sep 的答案所示。 (2认同)