我正在尝试将两个 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 c lower
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
另外,我在代码中做错了什么吗?
对于第二个数字的输入,您将重置
BX
寄存器,从而销毁第一个输入的数字!现在的美妙之处在于,您根本不需要将目标寄存器清零,因为将字寄存器移位 4 位并执行 4 次将不会留下任何预先写入的内容。所以只需删除那些初始化器即可。
您的级联 BCD 加法使用
AH
寄存器,但该寄存器 在程序中的此时没有任何用处。您应该使用 DH
寄存器来代替。加法结束时,
CX
寄存器保存一个 4 位压缩 BCD。您无法使用 DOS.PrintCharacter 函数 02h 一次性打印该内容,该函数的函数编号为
AH
(而不是 AX
)。您需要一个循环,从最高有效数字开始迭代 4 个 BCD 数字,该数字存储在 CH
寄存器的高半字节中。 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
将所有内容放在一起并写一些更好的评论
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