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

nfs0ujit  于 2023-01-02  发布在  其他
关注(0)|答案(5)|浏览(125)

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

ryoqjall

ryoqjall1#

基本上,您需要除以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

顺便说一句,您的代码中有一个bug:

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.
lx0bsm1f

lx0bsm1f2#

我只是在修改“内森·费尔曼的代码”的顺序

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
zfciruhq

zfciruhq3#

基本算法为:

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,只需将“0”的ascii代码(即48)添加到该数字即可。

ej83mcc0

ej83mcc04#

mov dl, ax

由于dlax的位数不同,因此这是行不通的。您需要创建一个循环,将16位值除以10,记住堆栈中的其余部分,然后使用整数除法结果继续循环。当结果为0时,逐位清除堆栈,将数字加上48以将其转换为ASCII数字。然后打印出来。

wlsrxk51

wlsrxk515#

  • 接受的答案是错误的,因为它显示的结果颠倒了!这就是为什么我今天写这个答案。我的答案演示了一口输出结果的更好的技术(通过DOS.函数09 h)*。

您的代码

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

总是在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 '$' 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

相关问题