它可以很好地读取整数并找到最小的整数。然而,当总和 > 9 时,它会给出错误的结果。
我正在尝试将 BH 中的总和计算为小数。但是,如果我要求它添加 9 和 9,它会在 BH 中存储 12,而不是 18。
data segment
msg db "chiffre: $"
petit db "plus petit chiffre: $"
somme db "somme: $"
ends
stack segment
dw 128 dup(0)
ends
code segment
start:
; set segment registers:
mov ax, data
mov ds, ax
mov es, ax
mov ah, 09h
mov dl, offset msg
int 21h
mov ah, 01h
int 21h
mov bl, al ; bl contains the smallest number
mov bh,al
sub bh,'0'
mov cx,3
etq:
mov ah, 02h
mov dl,0Dh
int 21h
mov ah, 02h
mov dl,0Ah
int 21h
mov ah, 09h
mov dl, offset msg
int 21h
mov ah, 01h
int 21h
cmp al, bl
jb min
jae reste ; jump to the end of the loop
min:
mov bl, al
reste:
sub al,'0'
add bh,al
loop etq
调试器显示正确的结果,但使用十六进制。
使用 DOS 显示数字解释了如何将数字转换为十进制字符字符串,然后可以将其显示在屏幕上,这样您就不必解释在调试窗口中找到的十六进制值。
mov dl, offset msg
这是一个您应该注意的错误。 DOS.PrintString 函数 09h 需要字大小的 DX 寄存器中的字符串地址。你不应该只加载低字节 DL 并相信高字节 DH 包含 0。所以写
mov dx, OFFSET msg
。
cmp al, bl jb min jae reste ; jump to the end of the loop min: mov bl, al reste:
您可以轻松避免跳过新最小值的分配。如果您选择相反的条件跳转,则可以用单个指令
jb min
替换 jae reste
jnb reste
对。
我发现您的程序正在重复一些指令。在下面的代码片段中,在循环开始之前对 BX 进行适当的初始化后,我让循环执行 4 次迭代:
mov bx, 000Ah ; BH is sum (0), BL is smallest number (10)
mov cx, 4
etiquette:
mov ah, 09h
mov dx, OFFSET msg
int 21h
mov ah, 01h
int 21h ; -> AL = ['0','9']
sub al, '0' ; From ['0','9'] to [0,9]
cmp al, bl ; (*)
jnb passer
mov bl, al ; Assign a new minimum
passer:
add bh, al ; Sum
mov ah, 02h
mov dl, 13
int 21h
mov dl, 10
int 21h
loop etiquette
(*) 因为最小数字变量 BL 被初始化为 10,大于用户可以输入的任何(十进制)数字,所以第一个
cmp al, bl
将已经设置以下条件,因此将分配第一个新的最小值从第一个用户输入开始(就像在您的程序中一样)。
您的程序可以期望的最大总和是 36 (9+9+9+9)。作为一种替代方法,您可以使用下一个代码来显示 [0,99] 范围内的小数字,而不是使用我在上面提供的链接的 Q/A 中描述的方法:
mov al, bh ; Sum eg. 18
aam ; -> AH = AL / 10 AL = AL % 10 eg. AH = 1 AL = 8
add ax, '00' ; Convert into text eg. AH = '1' AL = '8'
mov cx, ax
mov ah, 02h
mov dl, ch ; Tens eg. '1'
int 21h
mov dl, cl ; Ones eg. '8'
int 21h