?? caculator.asm
字號:
;*************************************************
;funtion:caculator
;1.receive the arithmatic expression
;2.conver the nuber into integal number and push
; into stack as the order input
;3.if without "()":call caculator to get the result
; else :be priority to deal with the data con-
; tained in the "()"and push result into
; stack until no "()" among the express-
; ion,then call Caculator to gain result.
;**************************************************
;illustrate:si indicate the current character inputed
stack segment para stack
db 256 dup (?)
top label word
stack ends
data segment
ESCAPE = 1BH
stoax dw ?
stobx dw ?
stocx dw ?
stodx dw ?
prompt db "Please input the expression:",0dh,0ah,'$'
commons db "Press any key to continue or ESCAPE to exit!",0dh,0ah,'$'
err_1 db "Please make sure the first operand is number",0dh,0ah,'$'
err_2 db "Data is out of the range(0~32768)",0dh,0ah,'$'
err_3 db "The data operand is needed",0dh,0ah,'$'
err_4 db "Maybe the operade is missed",0dh,0ah,'$'
err_5 db "invalid caculate expression(maybe you drop the operate)",0dh,0ah,'$'
err_6 db "empty!",0dh,0ah,'$'
err_7 db "Match error!('(' and ')' don't match)",0dh,0ah,'$'
buffer db 128 ;the buffer receiving input
db ?
equal db 120 dup (0)
tempdata dw 0 ;store the current data
tempoper dw 0 ;store the current operade
mutex db 0 ;strict with the input expression
data ends
code segment
assume ds:data,cs:code,ss:stack
;==================main funtion=====================
main proc far
start:
mov ax,stack
mov ss,ax
mov sp,offset top ;set stack area
mov ax,data
mov ds,ax ;set the data area
mov dx,offset prompt
mov ah,9
int 21h ;print the input prompt
mov dl,' '
mov ah,2
int 21h ;inset the first bankspace
mov dx,offset buffer
mov ah,0ah
int 21h ;receive the input expression
call crlf
mov si,-1 ;initial the read pointer
mov cl,buffer+1 ;get the expression length
xor ch,ch
sub cx,si
dec cx ;the lenght can caculate
cmp cx,0
jnz next
jmp exit ;no input
next: mov dx,-1
push dx ;set a mark as sign to be out of stack
dis1: inc si
cmp equal[si],' '
jz dis1 ;dispose the backspace
cmp equal[si],'0'
jb crash
cmp equal[si],'9'
jbe next_con
crash:mov dx,offset err_1
mov ah,9
int 21h
jmp exit ;ensure the first operand is a number
next_con:
mov dl,buffer+1
xor dh,dh
mov si,dx ;si->the last character(0dh)
;set string pointer(si)
cycle:dec si ;dipose the extra character
mov al,equal[si]
cmp equal[si],' '
jz cycle ;remove the ' '
cmp si,-1
jz final ;when the expression contain ' ' at the head
cmp equal[si],0dh
jz cycle ;remove the CR key
cmp equal[si],')'
jz push_sign ;')' possess the highest priority
cmp equal[si],'0' ;at the end of the expression
jb err_miss ;miss a operade
cmp equal[si],'9'
ja err_miss ;si point to the first number
call convert ;start deal with the data
push dx ;store a operand
cmp equal[si],'('
jz call_ca
deduce:
cmp equal[si],' '
jz cycle ;remove the ' '
cmp equal[si],'+' ;push the differnt operade
jz push_op ;into the stack
cmp equal[si],'-'
jz push_op
cmp equal[si],'*'
jz push_op
cmp equal[si],'/'
jz push_op
cmp si,0
jle final
jmp err_miss ;miss an operade
;
err_miss:
mov dx,offset err_4
mov ah,9
int 21h
jmp exit
;
push_sign: ;push the exit paremeter of
inc mutex
mov dx,-1 ;the stack
push dx
jmp cycle
;
final:
cmp mutex,0
jnz err_match
call caculate
push dx
mov dl,'='
mov ah,2
int 21h ;print '='
pop dx
cmp dx,32768
jb print
neg dx
push dx
mov dl,'-'
mov ah,2
int 21h
pop dx
print:call decimal ;display the result as a decimal number
call crlf
jmp exit
;
call_ca: ;caculate the expression in '()'
dec mutex
call caculate
push dx
dis2: dec si
cmp equal[si]," "
jz dis2
jmp deduce ;deal with the '+、-、*、/'
;
push_op: ;push the operade
mov dl,equal[si]
xor dh,dh
push dx
jmp cycle
;
err_match:
mov dx,offset err_7
mov ah,9
int 21h ;'('、')' don't match
jmp exit
;
exit: mov dx,offset commons
mov ah,9
int 21h ;make a choice
mov ah,8
int 21h ;read the key input
cmp al,ESCAPE
jz _exit
jmp start
_exit:mov ax,4c00h
int 21h
main endp
;========caculator the in order expression============
;in: stack
;out:cx+dx=final result (the final or middle result)
caculate proc
pop stodx ;store the address to return
mov stoax,ax
mov stobx,bx
mov stocx,cx ;store the register data
next_sum:
pop dx ;store data in the stack to dx
cmp dx,-1
jnz start_sum ;is the end of the stack?
cmp tempdata,0 ;dealing with the rest data before return
jz exit_sum
cmp tempoper,'+'
jz deal_add
jmp deal_sub
pop dx ;pop the extral '+' or '-'
exit_sum:mov dx,cx ;return the result
mov cx,stocx
mov bx,stobx
mov ax,stoax ;recover the register data
push stodx ;recover the address to return
ret
start_sum:
cmp dx,'*'
jz deal_mul
cmp dx,'/'
jz deal_div
cmp dx,'+'
jz deal_add
cmp dx,'-'
jz deal_sub
mov cx,dx ;store the first operand to cx
jmp next_sum
;
;
deal_mul: ;multiply
pop ax ;the second operand
next_mul:xor dx,dx
mul cx ;the first operand
cmp dx,0
jnz err_mul
push ax ;mul result store to continue
con_mul: jmp next_sum
err_mul: mov dx,offset err_6
mov ah,9
int 21h
mov dx,-1
push stodx
ret ;out of range and unusual return
;
;
deal_div: ;divide
pop ax ;the second operand
next_div:xor dx,dx
xchg ax,cx
div cx
push ax ;mod result
con_div: jmp next_sum
;
deal_add: ;addition
cmp tempdata,0
jz store_add ;need to caculate or not?
push dx ;push the operade(+)
cmp tempoper,'-'
jz case_sub
add cx,tempdata
jmp next_add
case_sub:xchg tempdata,cx
sub cx,tempdata
next_add:mov tempdata,0
mov tempoper,0 ;temporarily store data and operater
push cx
jmp next_sum
store_add: ;no need to caculate
mov tempdata,cx ;(cx)the current number
mov tempoper,dx ;(dx)the current operade
jmp next_sum ;get the next data or operade
;
;
deal_sub: ;subtract
cmp tempdata,0
jz store_sub ;Dose need to caculate?
push dx ;push the operade '-'
cmp tempoper,'+'
jz case_add
xchg tempdata,cx
sub cx,tempdata
jmp next_sub
case_add:add cx,tempdata
next_sub:
mov tempdata,0
mov tempoper,0 ;temporary store
push cx ;push the middle result in cx
jmp next_sum
store_sub: ;no need to caculate
mov tempdata,cx ;(cx)the current number
mov tempoper,dx ;(dx)the current operade
jmp next_sum ;continue to get the data of the stack
;
;
ret_sum: ;mov cx,stocx
;mov bx,stobx
;mov ax,stoax ;recover the register data
;push stodx
;ret
caculate endp
;###conver the character into the integral number####
;describe:the si register indicate the first numberal operand
;in:si
;out:dx (push the intergral number into the stack
change proc
mov stoax,ax
mov stobx,bx
mov stocx,cx ;store the register data
xor dx,dx
mov cx,10d
next_ver:
mov ax,dx ;sotre the number
xor dx,dx
mul cx
mov bl,byte ptr equal[si]
sub bl,30h
xor bh,bh ;convert equal[si] to the integral data
add ax,bx
cmp dx,0
jnz err_ver
mov dx,ax ;store the data into dx(return)
inc si
mov al,byte ptr equal[si]
cmp al,'0'
jb ret_ver
mov al,byte ptr equal[si]
cmp al,'9'
ja ret_ver
jmp next_ver
err_ver: mov dx,offset err_2;unreachable range of the data(0~32768)
mov ah,9
int 21h
ret_ver:
mov cx,stocx
mov bx,stobx
mov ax,stoax ;recover the register data
ret
change endp
;in:si (pointer to the first integral number )
;out:dx=the integral data(≥0)
; si=point to the current character that will be analysised
;function:vonvert a series of numberal characters to a decimal number
convert proc
push ax
push cx
mov cx,1
xor dx,dx
push dx ;initial the enterance
next_chg:
cmp si,0
jb exit_chg ;at the end of stack
cmp equal[si],'0'
jb exit_chg ;<0
cmp equal[si],'9' ;>9
ja exit_chg ;the sign to exit
mov al,equal[si]
sub al,30h
xor ah,ah
xor dx,dx
mul cx
pop dx
add dx,ax ;store the result
push dx
mov ax,10
mul cx ;weight*10
mov cx,ax
dec si
jmp next_chg ;cycle to convert to intergral number
exit_chg:
pop dx
pop cx
pop ax
ret
convert endp
crlf proc
push dx
push ax
mov dx,0dh
mov ah,2
int 21h
mov dx,0ah
mov ah,2
int 21h
pop ax
pop dx
ret
crlf endp
;in:dx
;out:
;print the decimal number on the screen
decimal proc
push ax
push bx
push cx
push dx
mov ax,dx
mov cx,10
mov dx,-1
push dx ;the exit paremeter of the stack
next_de:xor dx,dx
div cx
add dx,30h
push dx
or ax,ax
jnz next_de
dis_de: pop dx
or dx,dx
jz dis_de
cmp dx,-1
jnz deal_de
mov dx,30h
mov ah,2
int 21h
ret
deal_de:mov ah,2
int 21h
pop dx
cmp dx,-1
jnz deal_de
pop dx
pop cx
pop bx
pop ax
ret
decimal endp
code ends
end start
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -