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

发布于 2024-10-03 13:45:39 字数 541 浏览 5 评论 0原文

当我在 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。

When I add two values in 16 bit assembly, what is the best way to print the result to console?

At the moment I have this 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---;;

I think that dl value should be in ASCII code, but I'm not sure how to convert ax value after addition into ASCII.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

不如归去 2024-10-10 13:45:39

您基本上想要除以 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.

You basically want to divide by 10, print the remainder (one digit), and then repeat with the 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

As a side note, you have a bug in your code right here:

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.

You put 2 in ah, and then you put ax in dl. You're basically junking ax before printing it.

You also have a size mismatch since dl is 8 bits wide and ax is 16 bits wide.

What you should do is flip the last two lines and fix the size mismatch:

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.
神经大条 2024-10-10 13:45:39

只是修复 @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

Just fixing the order of @Nathan Fellman 's code

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
无边思念无边月 2024-10-10 13:45:39

基本算法是:

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

请注意,这将以相反的顺序生成数字,因此您可能需要用存储每个数字的内容替换“发出”步骤,以便稍后可以对存储的数字进行反向迭代。

另请注意,要将 0 到 9(十进制)之间的二进制数转换为 ascii,只需将“0”的 ascii 代码(即 48)添加到该数字中即可。

The basic algorithm is:

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

Note that this will yield the digits in the inverse order, so you are probably going to want to replace the "emit" step with something that stores each digit, so that you can later iterate in reverse over the stored digits.

Also, note that to convert a binary number between 0 and 9 (decimal) to ascii, just add the ascii code for '0' (which is 48) to the number.

油饼 2024-10-10 13:45:39
mov dl, ax

这不起作用,因为 dlax 具有不同的位大小。您想要做的是创建一个循环,在其中将 16 位值除以 10,记住堆栈上的其余部分,然后使用整数除法结果继续循环。当结果为 0 时,逐位清理堆栈,将这些数字加上 48 将其转换为 ASCII 数字,然后打印它们。

mov dl, ax

This won't work as dl and ax have different bit sizes. What you want to do is create a loop in which you divide the 16 bit value by 10, remember the rest on the stack, and then continue the loop with the integer division result. When you reach a result of 0, clean up the stack digit by digit, adding 48 to the digits to turn them into ASCII digits, then print them.

囚我心虐我身 2024-10-10 13:45:39

接受的答案是错误的,因为它显示的结果相反!这就是我今天写这个答案的原因。我的回答展示了一口气输出结果的更好技术(通过 DOS.function 09h)

你的代码

mov ah,2 ; 2是DOS服务中输出字符的函数号。
mov dl, 斧头; DL取值。
整数 21 小时;调用 DOS 服务

始终在 int 21h 指令之前的指令中加载 DOS 函数编号。
请务必检查您的大小:您无法从 16 位寄存器移动到 8 位寄存器。

我认为dl值应该是ASCII码,但我不知道如何将加法后的ax值转换为ASCII。

您的号码允许使用 DOS.PrintCharacter 函数。要将值3转换为字符“3”,只需添加48即可在DL中获得ASCII码。

当我在 16 位汇编中添加两个值时,将结果打印到控制台的最佳方式是什么?

一位数结果的示例

; Sum
  mov  al, 1
  add  al, 2

; Print
  add  al, '0'
  mov  dl, al
  mov  ah, 02h        ; DOS.PrintCharacter
  int  21h

; Exit
  mov  ax, 4C00h      ; DOS.TerminateWithExitcode
  int  21h

多位结果的解决方案

; Sum
  mov  ax, 7346
  add  ax, 913

; Print
  mov  bx, Buffer + 5 ; Position of the mandatory '

NASM 使用 mov bx, Buffer + 5
MASM 使用mov bx, OFFSET Buffer + 5

terminator mov cx, 10 More: xor dx, dx div cx dec bx add dl, '0' ; Convert to ASCII mov [bx], dl test ax, ax jnz More mov dx, bx mov ah, 09h ; DOS.PrintString int 21h ; Exit mov ax, 4C00h ; DOS.TerminateWithExitcode int 21h ; Storage Buffer: db '.....

NASM 使用 mov bx, Buffer + 5
MASM 使用mov bx, OFFSET Buffer + 5

NASM 使用 mov bx, Buffer + 5
MASM 使用mov bx, OFFSET Buffer + 5

The accepted answer is wrong in that it displays the result reversed! That's why I write this answer today. My answer demonstrates the better technique of outputting the result in one gulp (via DOS.function 09h).

Your code

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

Always load the DOS function number in the instruction right before the int 21h instruction.
Always check your sizes: you cannot move from a 16-bit register to an 8-bit register.

I think that dl value should be in ASCII code, but I'm not sure how to convert ax value after addition into ASCII.

Your numbers allow the use of the DOS.PrintCharacter function. To convert the value 3 into the character "3", you just need to add 48 so as to have an ASCII code in DL.

When I add two values in 16-bit assembly, what is the best way to print the result to console?

Your example for a single-digit result

; Sum
  mov  al, 1
  add  al, 2

; Print
  add  al, '0'
  mov  dl, al
  mov  ah, 02h        ; DOS.PrintCharacter
  int  21h

; Exit
  mov  ax, 4C00h      ; DOS.TerminateWithExitcode
  int  21h

Solution for a multi-digit result

; Sum
  mov  ax, 7346
  add  ax, 913

; Print
  mov  bx, Buffer + 5 ; Position of the mandatory '

NASM use mov bx, Buffer + 5
MASM use mov bx, OFFSET Buffer + 5

terminator mov cx, 10 More: xor dx, dx div cx dec bx add dl, '0' ; Convert to ASCII mov [bx], dl test ax, ax jnz More mov dx, bx mov ah, 09h ; DOS.PrintString int 21h ; Exit mov ax, 4C00h ; DOS.TerminateWithExitcode int 21h ; Storage Buffer: db '.....

NASM use mov bx, Buffer + 5
MASM use mov bx, OFFSET Buffer + 5

NASM use mov bx, Buffer + 5
MASM use mov bx, OFFSET Buffer + 5

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文