emu 8086 汇编计算器百分比错误

问题描述

我正在编写一个简单的汇编计算器,但无论我做什么,我都无法让百分比部分开始正常工作

我几乎花了 2 天半的时间来研究它,看起来它不喜欢改变任何东西。 我尝试了乘法和除法、混合或单独的每一种组合,但我无法使它起作用。

.model small

.data
    greating_msg db 0AH,0DH,"Welcome  to Calculator $"   
    name_data db 0AH,"name : vahid ... $"
    birthday_data db 0AH,"birthday : 1378/05/24 $"
    instruction_msg db 0AH,"type simple equations to solve Examples : 1+1 or 5*8 :  $",0AH," c"   
    error_msg db 10,"Exit due error$"
    division_reminder_msg db " and remainder=$"
    input db 3 DUP('0')

PRINTLINE macro str          
            LEA DX,str              ;to print string
            MOV AH,09H              ;To display character string
            INT 21H                 ;call DOS function
            
endm
.code
    ; printing greating_msg
    mov dx,@data ;move offsets to data segment
    mov ds,dx
    
   PRINTLINE greating_msg
   PRINTLINE name_data
   PRINTLINE birthday_data
   PRINTLINE instruction_msg
   
    mov bx,0
take_input:                        ; loop to take input and print dl for each letter
    mov ah,8        ; to input 1 character
    int  21h
    mov cl,al
    cmp bx,1        ; if it's the second character then it's opreation
    je check_cl_opreation
    call check_cl_number
    cmp al,1
    je assign
    jmp print_error_and_quit
check_cl_opreation:    ; to check if the input operation is a supported one
    cmp cl,'+'
    je assign
    cmp cl,'-'
    je assign
    cmp cl,'*'
    je assign
    cmp cl,'/'
    je assign 
    cmp cl,']'
    je assign
    jmp print_error_and_quit

assign:
    call print_cl
    mov input[bx],cl
    inc bx
    cmp bx,3
    jne take_input

calculate_input:
    mov cl,input[0]         ; First number
    mov bl,input[1]         ; the mark between the numbers
    mov ch,input[2]          ; Second number
    cmp bl,'+'
    je adding
    cmp bl,'-'
    je subtracting
    cmp bl,'*'
    je multiplying
    cmp bl,'/'
    je dividing  
    cmp bl,']'
    je percentage
print_error_and_quit:
    mov ah,9
    mov dx,offset error_msg
    int 21h         ; '!' = 21h
    
quit: ; Quit the program
    mov ah,'L'  ; 'L' = 4Ch
    int 21h
    
adding:
    call print_equal_sign
    sub ch,'0'
    add cl,ch
    mov ch,'0' ; ch will be used as 10's number
    jmp check_and_print_cx
    
subtracting:
    call print_equal_sign
    sub ch,'0'
    sub cl,ch
    call check_cl_number
    cmp al,1
    je print_sub
    mov bh,cl
    mov cl,'-'
    call print_cl
    mov cl,':'     ; ':' = '9'+1
    sub bh,'0'    ; make bh contains exact number
    add bh,10   ; add 10 to get number in positive in next instruction
    sub cl,bh     ; remove bh from cl to get positive number in cl
print_sub:
    call print_cl
    jmp quit

multiplying:
    call print_equal_sign
    sub ch,'0'
    mov al,ch
    mul cl
    mov cl,al
    mov ch,ah
    add cl,'0'
    add ch,'0'
    call check_and_print_cx
    
check_and_print_cx:
    call check_cl_number
    cmp al,1
    je print_cx
    inc ch
    sub cl,10
    jmp check_and_print_cx
print_cx:
    cmp ch,'0'
    je print_units
    mov bh,cl ; using bh as temp
    mov cl,ch
    call print_cl
    mov cl,bh
print_units:
    call print_cl
    jmp quit

dividing:
    call print_equal_sign
    sub cl,'0'                      ; to use the real value of cl not '0'+value
    sub ch,'0'                     ; to use the real value of ch not '0'+value
    mov ah,0                    ; clear ah to use ax in division
    mov al,cl
    mov bl,ch
    div bl
    mov ch,ah
    mov cl,al
    add cl,'0'
    call print_cl
    mov ah,9
    cmp ch,0
    je quit_division
    mov dx,offset division_reminder_msg
    int  21h        ; '!' = 21h
    mov cl,ch
    add cl,'0'
    call print_cl
quit_division:
    jmp quit
percentage:
   call print_equal_sign
    sub ch,100
    mul cl
    mov cl,'0'
    call check_and_print_cx
    
print_equal_sign:
    mov ah,2
    mov dl,'='
    int  21h
    ret
    
print_cl:
    mov ah,cl
    int  21h
    ret

check_cl_number: ; check if the CL is a number if so return 1 in AL else return 0 in AL
    cmp cl,'0'
    jb not_number
    cmp cl,'9'
    ja not_number
    mov al,1
    ret
not_number:
    mov al,0
    ret       
    
lpt_port PROC                    ;//////////////////////////// lpt1 port  procedure //////////////////////////; 

MOV DX,0378H
MOV AL,birthday_data
OUT DX,AL    

ENDP                 ;//////////////////////////// END of lpt1  port procedure //////////////////////////; 
end

解决方法

您的百分比部分忘记除以第二个数字!

a ] b = a * 100 / b

对于第一个数字 (a) 小于第二个数字 (b) 的情况,否则您会得到一个 3 位数的结果 (100+ %)您的程序(还)不能输出。这立即排除了第二个数字中的零,这是所需除法所必需的。

percentage:
    call print_equal_sign
    sub cx,'00'   ; From ASCII to digits : CL is 1st number,CH is 2nd number
    mov al,100
    mul cl        ; e.g. 1 * 100 = 100      3 * 100 = 300
    div ch        ; e.g. 100 / 2 = 50 %     300 / 7 = 42 %
    mov cl,al     ; Quotient  (AH is remainder)
    mov ch,0
    add cx,'00'   ; Back to ASCII
    jmp check_and_print_cx