將結果轉換回數字時,您正在使用簽名比較。如果結果高於128,它將被視爲負數,並且您的轉換將失敗。
這裏是一個de-obfuscated和稍微清理的版本的代碼,可能工作,如果你將兩個越野車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
陰性結果(即輸入< 20)處理不好。
.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黑客:)
你做錯的第一件事就是把零點意見中彙編源代碼文件併爲大多數變量和標籤使用1或2個字母。雖然大約在1990年的反向工程DOS代碼可能很有趣,但它也有點耗時。反混淆你的來源,也許更多的人會看看它。 –
請記住,因爲您使用的是字節變量,所以_signed_字節的範圍是-128 .. + 127,而'jg'和'jge'的意思是_signed_大於(/或相等)。 – Michael