⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 caculator.asm

📁 利用汇编语言实现的一个打字练习程序
💻 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 + -