I am writing a simple calculator in assembly but no matter what I do, I can't get the percentage part to start to work correctly and consistently getting this error:
divide error - overflow.
I almost worked a day and a half on it and it looks like it doesn't like to change anything.
I tried every combination of multiplication and division and mix or separately and yet I can't make it work.
org 100h
jmp start ; jump over data declaration
hello db 0AH,0DH, "===========Calculator program assembly==========$"
my_name db 0AH,0DH, "========= behnam abbas abbadi =========$"
birthday db 0AH,0DH, "========= 1378/05/24 ========= $"
msg: db 0AH,0DH , "1-Add",0dh,0ah,"2-Multiply",0dh,0ah,"3-Subtract",0dh,0ah,"4-Divide",0dh,0ah,"5-Percentage", 0Dh,0Ah, '$'
msg2: db 0dh,0ah,"Enter First No : $"
msg3: db 0dh,0ah,"Enter Second No : $"
msg4: db 0dh,0ah,"Choice Error $"
msg5: db 0dh,0ah,"Result : $"
msg6: db 0dh,0ah ,'thank you for using the calculator! press any key... ', 0Dh,0Ah, '$'
input_message_and_function macro
mov ah,09h ;then let us handle the case of addition operation
mov dx, offset msg2 ;first we will display this message enter first no also using int 21h
int 21h
mov cx,0 ;we will call InputNo to handle our input as we will take each number seprately
call InputNo ;first we will move to cx 0 because we will increment on it later in InputNo
push dx
mov ah,9
mov dx, offset msg3
int 21h
mov cx,0
call InputNo
endm
info_print macro str
mov dx,offset str
mov ah,09h
int 21h
endm
print_anser_and_exit macro
push dx
mov ah,9
mov dx, offset msg5
int 21h
mov cx,10000
pop dx
call View
jmp exit
endm
start:
info_print hello
info_print my_name
info_print birthday
mov ah,9
mov dx, offset msg ;first we will display hte first message from which he can choose the operation using int 21h
int 21h
mov ah,0
int 16h ;then we will use int 16h to read a key press, to know the operation he choosed
cmp al,31h ;the keypress will be stored in al so, we will comapre to 1 addition ..........
je Addition
cmp al,32h
je Multiply
cmp al,33h
je Subtract
cmp al,34h
je Divide
cmp al,35h
je Percentage
call calc
mov ah,09h
mov dx, offset msg4
int 21h
mov ah,0
int 16h
jmp start
calc proc ;////////////////////////////////// start calculation procedure ///////////////////////////////////////////////////
Addition:
input_message_and_function
pop bx
add dx,bx
print_anser_and_exit
Multiply:
input_message_and_function
pop bx
mov ax,dx
mul bx
mov dx,ax
print_anser_and_exit
Subtract:
input_message_and_function
pop bx
sub bx,dx
mov dx,bx
print_anser_and_exit
Divide:
input_message_and_function
pop bx
mov ax,bx
mov cx,dx
mov dx,0
mov bx,0
div cx
mov bx,dx
mov dx,ax
push bx
print_anser_and_exit
Percentage:
input_message_and_function
; pop bx
; mov ax,100
; mul bx
; mov dx,ax
pop bx
mov ax, 100
mul ax
mov bx,ax
mov cx,dx
mov dx,0
mov bx,0
div cx
mov bx,dx
mov dx,ax
push bx
print_anser_and_exit
endp ;////////////////////////////////// end calculation procedure ///////////////////////////////////////////////////
func proc ;////////////////////////////////// start functions procedure ///////////////////////////////////////////////////
InputNo: mov ah,0
int 16h ;then we will use int 16h to read a key press
mov dx,0
mov bx,1
cmp al,0dh ;the keypress will be stored in al so, we will comapre to 0d which represent the enter key, to know wheter he finished entering the number or not
je FormNo ;if it's the enter key then this mean we already have our number stored in the stack, so we will return it back using FormNo
sub ax,30h ;we will subtract 30 from the the value of ax to convert the value of key press from ascii to decimal
call ViewNo ;then call ViewNo to view the key we pressed on the screen
mov ah,0 ;we will mov 0 to ah before we push ax to the stack bec we only need the value in al
push ax ;push the contents of ax to the stack
inc cx ;we will add 1 to cx as this represent the counter for the number of digit
jmp InputNo ;then we will jump back to input number to either take another number or press enter
;we took each number separatly so we need to form our number and store in one bit for example if our number 235
FormNo: pop ax
push dx
mul bx
pop dx
add dx,ax
mov ax,bx
mov bx,10
push dx
mul bx
pop dx
mov bx,ax
dec cx
cmp cx,0
jne FormNo
ret
View: mov ax,dx
mov dx,0
div cx
call ViewNo
mov bx,dx
mov dx,0
mov ax,cx
mov cx,10
div cx
mov dx,bx
mov cx,ax
cmp ax,0
jne View
ret
ViewNo: push ax ;we will push ax and dx to the stack because we will change there values while viewing then we will pop them back from
push dx ;the stack we will do these so, we don't affect their contents
mov dx,ax ;we will mov the value to dx as interrupt 21h expect that the output is stored in it
add dl,30h ;add 30 to its value to convert it back to ascii
mov ah,2
int 21h
pop dx
pop ax
ret
exit: mov dx,offset msg6
mov ah, 09h
int 21h
mov ah, 0
MOV DX,0378H
MOV AL, birthday
OUT DX,AL
int 16h
ret
endp ;////////////////////////////////// end functions procedure ///////////////////////////////////////////////////
Percentage: input_message_and_function pop bx mov ax, 100 mul ax mov bx,ax mov cx,dx <<<<< DX=0 here! mov dx,0 mov bx,0 div cx mov bx,dx mov dx,ax push bx print_anser_and_exit
input_message_and_function leaves the 1st number on the stack and the 2nd number in DX
.
The mul ax
immediately destroys the 2nd number!
Why do you even calculate 100^2? Just mov ax, 10000
if that's what you need.
e.g. First input is 80 and second input is 200, producing 40%
pop bx ; 1st number is 80
mov cx, dx ; 2nd number is 200
mov ax, 100
mul bx ; 80 * 100 = 8000
div cx ; 8000 / 200 = 40
mov dx, ax