2014-02-18 19 views
0

這是我的計劃,我用TASM寫道:TASM程序採取三數字輸入,從輸入減去一個數,並輸出結果

dosseg 
.model small 
.stack 100h 
.data 
h1 db 0 
t1 db 0 
o1 db 0 
n db 0 
hc db 0 
tc db 0 
prompt db 'Input 3 digit number: $' 
prompt2 db 'Result: $' 
lf db 0Dh,0Ah,24h 

.code 
mov ax,@data 
mov ds,ax 

lea dx,prompt 
mov ah,09h 
int 21h 

mov ah,01h 
int 21h 
sub al,30h 
mov h1,al 

int 21h 
sub al,30h 
mov t1,al 

int 21h 
sub al,30h 
mov o1,al 

cmp h1,00h 
jg hn 
add n,00h 

o: 
mov bl,o1 
add n,bl 
jmp t 

hn: 
add n,64h 
dec h1,01h 
cmp h1,00h 
jne hn 

t: 
cmp t1,00h 
jg tn 
add n,00h 
jmp d 

tn: 
add n,0Ah 
dec t1,01h 
cmp t1,00h 
jg tn 
jmp o 

d: 
sub n,14h 
cmp n,64h 
jge d2 
mov hc,00h 

da: 
cmp n,0Ah 
jge d3 
mov tc,00h 
jmp dsp 

d2: 
sub n,64h 
add hc,01h 
cmp n,64h 
jge d2 
jmp da 

d3: 
sub n,0Ah 
add tc,01h 
cmp n,0Ah 
jge d3 

dsp: 
add hc,30h 
add tc,30h 
add n,30h 

lea dx,lf 
mov ah,09h 
int 21h 

lea dx,prompt2 
mov ah,09h 
int 21h 




mov dl,hc 
mov ah,02h 
int 21h 







mov dl,tc 
mov ah,02h 
int 21h 


mov dl,n 
mov ah,02h 
int 21h 

mov ah,4Ch 
int 21h 
end 

程序將顯示3位數字輸入之間的差異和20. 我對小於148的輸入沒有問題。當我輸入148或更高時,它不顯示128.我該怎麼辦?

+2

你做錯的第一件事就是把零點意見中彙編源代碼文件併爲大多數變量和標籤使用1或2個字母。雖然大約在1990年的反向工程DOS代碼可能很有趣,但它也有點耗時。反混淆你的來源,也許更多的人會看看它。 –

+0

請記住,因爲您使用的是字節變量,所以_signed_字節的範圍是-128 .. + 127,而'jg'和'jge'的意思是_signed_大於(/或相等)。 – Michael

回答

2

將結果轉換回數字時,您正在使用簽名比較。如果結果高於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黑客:)

+0

jae做了什麼? – JetYamato

+0

如果大於或等於,則跳轉。它將最後比較的結果解釋爲無符號,而jge(如果大於或等於則跳轉)將其解釋爲有符號。 –

相關問題