将结果转换回数字时,您正在使用带符号的比较。如果结果大于 128,将被视为负数,您的转换将失败。
如果您将两个有缺陷的jge 更改为jae,那么这是一个去混淆和稍微清理过的代码版本。
dosseg
.model small
.stack 100h
.data
; input digits
in_1 db 0
in_10 db 0
in_100 db 0
; output digits
out_1 db 0
out_10 db 0
out_100 db 0
; display
d_prompt db 'Input 3 digit number: $'
d_result db 'Result: $'
d_crlf db 0Dh,10,'$'
.code
mov ax,@data ; setup data segment
mov ds,ax
lea dx,d_prompt ; display prompt
mov ah,09h
int 21h
mov ah,01h ; read 3 decimal digits and turn them to numbers
int 21h
sub al,30h
mov in_1,al
int 21h
sub al,30h
mov in_10,al
int 21h
sub al,30h
mov in_100,al
cmp in_1,00h ; convert them to a byte
jg add_hundreds
add_units:
mov bl,in_100
add out_1,bl
jmp check_tens
add_hundreds:
add out_1, 100
dec in_1
cmp in_1,00h
jne add_hundreds
check_tens:
cmp in_10,00h
jg add_tens
jmp compute
add_tens:
add out_1,10
dec in_10
cmp in_10,00h
jg add_tens
jmp add_units
compute:
sub out_1, 20 ; substract 20 to result
cmp out_1, 100
jge above_99 ; ***bug*** should use unsigned comparison (jae)
convert_tens:
cmp out_1,10
jge between_10_and_99
jmp display_result
above_99:
sub out_1,100 ; convert hundreds
inc out_100
cmp out_1,100
jge above_99 ; ***bug*** should use unsigned comparison (jae)
jmp convert_tens
between_10_and_99:
sub out_1,10 ; convert tens
inc out_10
cmp out_1,10
jge between_10_and_99
display_result:
add out_100,30h ; convert digits to characters
add out_10,30h
add out_1,30h
lea dx,d_crlf ; display line break
mov ah,09h
int 21h
lea dx,d_result ; display result message
mov ah,09h
int 21h
mov dl,out_100 ; display output
mov ah,02h
int 21h
mov dl,out_10
mov ah,02h
int 21h
mov dl,out_1
mov ah,02h
int 21h
mov ah,4Ch ; terminate program
int 21h
end
我自己解决问题,能够处理数字 > 255
此版本将处理高达 65535 的任何内容,然后翻转到 0。
负面结果(即输入
.model small
.stack 100h
.data
; value to substract
SUB_VALUE equ 20
; number of digits
NUM_DIGITS equ 5
; conversion steps
convert label word
num = 1
rept NUM_DIGITS-1
num = num * 10
endm
rept NUM_DIGITS
dw num
num = num / 10
endm
; display
d_prompt db 'Enter a ',NUM_DIGITS+'0',' digits number: $'
d_result db 0Dh, 0Ah, 'Result: $'
.code
main:
mov ax,@data ; setup data segment
mov ds, ax
lea dx,d_prompt ; display prompt
mov ah, 09h
int 21h
mov ah,01h ; read decimal number
mov cx, NUM_DIGITS
lea si, convert
cld
read:
mov ah,01h ; read a digit
int 21h
sub al, '0' ; convert to number
mov dl, al
xor dh, dh
lodsw ; multiply by power of 10
mul dx
add bx, ax ; cumulate result
loop read
sub bx, SUB_VALUE ; do the substraction
lea dx,d_result ; display result message
mov ah,09h
int 21h
mov cx, NUM_DIGITS
lea si, convert
write:
lodsw ; power of 10 divider
xchg ax,bx
xor dx, dx
div bx ; divide result by power of 10
mov bx, dx ; store remainder
mov dl, '0' ; print current digit
add dl, al
mov ah,02h
int 21h
loop write
mov ah,4Ch ; terminate program
int 21h
end main
我花了一些时间来运行一个运行 TASM 的 DosBox,但这让我想起了我作为 DOS 黑客的日子 :)