首页 > 解决方案 > 16 位(4 位)BCD 加法 (TASM 8086)

问题描述

我正在尝试添加两个 4 位(16 位)BCD 数字并显示结果。

我已经编写了下面的代码,但我想知道如何处理进位位,因为该程序正在挂起 DosBox(TASM 模拟器)

出于某种原因,我的教授希望我们显示输入输出,请多多包涵:/

model small
.data 

 res dw ?
.code
.startup


; 1st number 
mov cx,4
mov bx,0
l1:
    shl bx,4
    mov ah,01
    int 21h

    and al,0FH
    add bl,al
    
loop l1

mov ah,02h   ; display + sign
mov dx,"+"
int 21h


; 2nd number
mov cx,4
mov bx,0
l3:
    shl dx,4
    mov ah,01
    int 21h

    and al,0FH
    add dl,al
loop l3

 mov al,bl
 add al,dl 
 daa
 mov cl,al  # storing lower byte in clower
 mov al,ah
 adc al,bh
 daa 
 mov ch,al  # storing higher byte in c higher
 
 mov [res],cx
 
 mov ax,02h
 mov dx,res  # To display the result
 int 21h




.EXIT
END

另外,我在代码中做错了吗?

标签: assemblyx86-16additiontasmbcd

解决方案


For the input of the second number you are resetting the BX register and thus are destroying the first inputted number! Now the beauty is that you don't need to zero the destination register at all because shifting a word register by 4 bits and doing it 4 times will leave nothing that was written to it in advance. So just drop those initializers.

Your cascaded BCD addition uses the AH register but that register has nothing useful in it at that point in the program. You should have used the DH register instead.

At the end of the addition the CX register holds a 4-digit packed BCD. You can not print that in one go using the DOS.PrintCharacter function 02h for which the function number goes to AH (and not AX). You need a loop that iterates over the 4 BCD digits starting at the most significand digit which is stored in the high nibble of the CH register.

  mov bx, 4
More:
  rol cx, 4        ; Brings highest nibble round to lowest nibble
  mov dl, cl       ; Move to register that DOS expects
  and dl, 15       ; Isolate it
  or  dl, '0'      ; Convert from value [0,9] to character ['0','9']
  mov ah, 02h      ; DOS.PrintCharacter
  int 21h
  dec bx
  jnz More

Putting it all together and writing some better comments

  call GetBCD      ; -> DX
  mov  bx, dx

  mov  dl, '+'     ; No need to store this in DX (DH is not used by DOS)
  mov  ah, 02h     ; DOS.PrintCharacter
  int  21h

  call GetBCD      ; -> DX

  mov al, bl
  add al, dl 
  daa              ; (*) -> CF
  mov cl, al

  mov al, bh
  adc al, dh       ; (*) Picking up the carry from above
  daa 
  mov ch, al
 
  mov bx, 4
More:
  rol cx, 4       ; Brings highest nibble round to lowest nibble
  mov dl, cl      ; Move to register that DOS expects
  and dl, 15      ; Isolate it
  or  dl, '0'     ; Convert from value [0,9] to character ['0','9']
  mov ah, 02h     ; DOS.PrintCharacter
  int 21h
  dec bx
  jnz More

  mov  ax, 4C00h  ; DOS.TerminateProgram
  int  21h

; IN () OUT (dx)
GetBCD:
  push ax
  push cx
  mov  cx, 4
T1:
  mov  ah, 01h    ; DOS.InputCharacter
  int  21h        ; -> AL=['0','9']
  sub  al, '0'    ; -> AL=[0,9]
  shl  dx, 4
  or   dl, al
  loop T1
  pop  cx
  pop  ax
  ret

推荐阅读