汇编计算器

来源:互联网 发布:mt4 画线下单源码 编辑:程序博客网 时间:2024/06/05 08:03

开学第一周完成的汇编计算器:前后一共写了很多版本,下面是俩个版本:

by  hfut  叶泽坤 冯弘承 许金龙 宋彬彬。

基础功能完善版:

stack segment stack       db 1024 dup(?)stack endsdata segment    LedMap       db    0c0h,0f9h,0a4h,0b0h,099h,092h,082h,0f8h                  ;0 1 2 3 4.....                 db    080h,090h,088h,083h,0c6h,0a1h,086h,08eh    KeyTable     db    07h,04h,08h,05h,09h,06h,0ah,0bh                          ;键码定义                 db    01h,00h,02h,0fh,03h,0eh,0ch,0dh    bit          dw    0h    stack_sign   db    0ffh,   100 dup(?)                                       ;符号栈    stack_numb   dw    0ffffh, 100 dup(?)        ;操作数栈    OUTSEG  equ  0ffdch                                 ;段控制口    OUTBIT  equ  0ffddh                              ;位控制口/键扫口    IN_KEY  equ  0ffdeh                                                          ;键盘读入口    TEN     db   10    LedBuf  db   00h,  00h, 00h, 00h, 00h, 00h                    ;显示缓冲data endscode    segment'code'        assume cs:code,ds:data,ss:stack        org  1000hStart:        mov  LedMap+0,0c0h     ;初始化工作        mov  LedMap+1,0f9h        mov  LedMap+2,0a4h        mov  LedMap+3,0b0h        mov  LedMap+4,099h        mov  LedMap+5,092h        mov  LedMap+6,082h        mov  LedMap+7,0f8h        mov  LedMap+8,080h        mov  LedMap+9,090h        mov  LedMap+10,088h        mov  LedMap+11,083h        mov  LedMap+12,0c6h        mov  LedMap+13,0a1h        mov  LedMap+14,086h        mov  LedMap+15,08eh        mov  KeyTable+0, 07h        mov  KeyTable+1, 04h        mov  KeyTable+2, 08h        mov  KeyTable+3, 05h        mov  KeyTable+4, 09h        mov  KeyTable+5, 06h        mov  KeyTable+6, 0ah        mov  KeyTable+7, 0bh        mov  KeyTable+8, 01h        mov  KeyTable+9, 00h        mov  KeyTable+10, 02h        mov  KeyTable+11, 0fh        mov  KeyTable+12, 03h        mov  KeyTable+13, 0eh        mov  KeyTable+14, 0ch        mov  KeyTable+15, 0dh        mov stack_sign,0ffh;        mov stack_numb,0ffffh;        mov  TEN,10        mov ch,0ffh;        call get0 ss1:      mov bl,ch;                            前一个符号      call show;                              显示灯      mov al,20h;      call getkey;                           获得键      cmp al,20h;                           是否有键按下      je  ss1;                               若无键按下,重新显示       and  al,0fh                          ;高位清零!       call myDelay                           ;这段时间应该等于手离开键盘的时间      mov ch,al;                           保存前一个符号      cmp al,10      jnb next0                             ;若是数字:      cmp bl,10        jb go1        call clearbuf;      cmp dx,0                              ;若是0,则buff改为0先      jne  go1      call clearbuf;go1:      call renew_led;                         更新显示      inc bit                               ;位数+1      mov bh,al ;                            乘以10加个位法      mov ax,dx ;      mul TEN   ;      add al,bh ;      adc ah,0  ;      mov dx,ax ;                           中间结果暂存与dx      jmp ss1;next0:                                      ;若是符号      cmp bl,10      jnb go0                                                  ;之前的是符号就跳      call mypush_numb                     ;先将之前的数字入栈go0:      mov dx,0;      cmp al,0fh                         ;是否=      jne go3go4:                                ;  是的话      cmp byte ptr stack_sign[si],0ffh           ;  是的话,一直爆栈,是否栈底      jne go11      call get_ans                       ;       是栈底,显示结果结束。      jmp ss1go11:     call calcu     jmp go4;go3:      cmp al,0ch                           ;是否复位      jne go5      call get0;      jmp ss1;go5:      cmp al,0eh;                          ;是否括号      jne go2            cmp bl,0feh;      je  go6            cmp bl,10                          ;是否左括号 (符号后面必是左括号)      jnb leftgo6:      mov ch,0feh;      cmp byte ptr stack_sign[si],0eh;              ;若是右括号,是否遇到左括号      jne go12      call mypop_sign                      ;遇到左括号,出栈之      jmp ss1go12:       call calcu       jmp go6left:      call mypush_sign                     ;左括号入站      jmp ss1go2:      cmp byte ptr stack_sign[si],0eh                 ;否则必是运算符号,比较优先级      jne  go7      call mypush_sign                       ;若是栈顶是左括号,必入栈      jmp ss1go7:      cmp al,0dh;                                若是乘号      jne go9      cmp byte ptr stack_sign[si],0dh;           ;栈顶是否也是乘号      jne go8      call calcu                                 ;计算,并*入栈go8:      call mypush_sign      jmp ss1go9:                                          ;若是加减号,必爆栈计算      cmp  si,0                                ;栈是否空,空必入栈      jne  go10      call mypush_sign      jmp ss1;go10:      call calcu      call mypush_sign      jmp  ss1calcu:                           ;爆栈计算子程序      push ax      push bx      push cx      push dx      call mypop_sign      mov bl,al      call mypop_numb      push dx      call mypop_numb      mov ax,dx      pop dx      cmp bl,0ah;      je myadd      cmp bl,0bh;      je mysub      cmp bl,0dh;      je mymulmyadd:add ax,dx      mov dx,ax      call mypush_numb      pop dx      pop cx      pop bx      pop ax      retmysub:sub ax,dx      mov dx,ax      call mypush_numb      pop dx      pop cx      pop bx      pop ax      retmymul:mul dx      mov dx,ax      call mypush_numb      pop dx      pop cx      pop bx      pop ax      retget_ans:                                     ;将答案(在栈底)显示器buf修改子程序     push bx;     push dx;     push ax;     push si     push di     call mypop_numb;        初始值弹出到DX     mov di,5;              从左边低位开始     mov  bx,10;     mov  ax,dx             ;将结果放在ax便于除法do:     xor  dx,dx     div  bx                  ;ax/10 ,余数在dx,结果在ax     mov si,dx     mov dl,LedMap[si];     mov  LedBuf[di],dl         ;改余数对应位的buff     dec di;     cmp ax,0;     jne  do     pop di     pop si     pop ax     pop dx     pop bx     retclearbuf:        mov  LedBuf+0,0ffh                      ;显示"0"子程序        mov  LedBuf+1,0ffh        mov  LedBuf+2,0ffh        mov  LedBuf+3,0ffh        mov  LedBuf+4,0ffh        mov  LedBuf+5,0c0h        mov dx,0        mov bit,0       ret;get0:        mov  LedBuf+0,0ffh                      ;显示"0"子程序        mov  LedBuf+1,0ffh        mov  LedBuf+2,0ffh        mov  LedBuf+3,0ffh        mov  LedBuf+4,0ffh        mov  LedBuf+5,0c0h        mov dx,0        mov si,0        mov di,0        mov bit,0      ret;mypush_sign :                 ;al->符号入栈 子程序             inc si             mov byte ptr  stack_sign[si],al             retmypush_numb  :                 ;dx->操作数入栈子程序             add di,2             mov word ptr   stack_numb[di],dx             retmypop_sign   :                  ; 出栈->al             mov al,stack_sign[si]             cmp al,0ffh             je  next3             dec sinext3:             retmypop_numb   :                   ;出栈->dx             mov dx,stack_numb[di]             cmp dx,0ffffh             je  next11             dec di             dec dinext11:             retrenew_led:                                ;更新buff子程序子程序      push si      push bx      push dx      mov si,bit;      mov bx,offset LedBuf;      cmp si,0      je  goagain:      neg si      mov dx,[bx+si+6];      mov [bx+si+5],dx;      neg si      dec si      jnz   againgo:     mov ah,0     mov si,ax     mov dl, [LedMap+si]     mov [bx+5],dl      pop dx      pop bx      pop si   ret;Delay:                                     ;延时子程序        push  cx        mov   cx,256        loop  $        pop   cx        retmyDelay:                                    ;键盘读入延时子程序        push  cx        mov   cx,25xx:        call show        loop  xx        pop   cx        retshow:                                                ;显示当前buff的子程序        push ax;        push bx        push cx;        push dx;        mov  bx,offset LEDBuf        mov  cl,6                            ;共6个八段管        mov  ah,00100000b                   ;从左边开始显示DLoop:       ; mov  dx,OUTBIT       ; mov  al,0       ; out  dx,al                             ;关所有八段管        mov  al,[bx]        mov  dx,OUTSEG        out  dx,al        mov  dx,OUTBIT        mov  al,ah        out  dx,al                              ;显示一位八段管        push ax        mov  ah,1        call Delay        pop  ax        shr  ah,1        inc  bx        dec  cl        jnz  DLoop       ; mov  dx,OUTBIT       ; mov  al,0h;      ;  out  dx,al              ;关所有八段管         pop dx         pop cx         pop bx         pop ax;        retgetkey:                          ;结果存在al中        push bx        push dx        push cx        mov  al,0ffh              ;关显示口        mov  dx,OUTSEG        out  dx,al        mov  bl,0        mov  ah,0feh        mov  cx,8key1:   mov  al,ah        mov  dx,OUTBIT        out  dx,al        shl  al,1        mov  ah,al        nop        nop        nop        nop        nop        nop        mov  dx,IN_KEY        in   al,dx        not  al        nop        nop        and  al,0fh        jnz  key2        inc  bl        loop key1nkey:   mov  al,20h        pop cx        pop dx        pop bx        retkey2:   test al,1        je   key3        mov  al,0        jmp  key6key3:   test al,2        je   key4        mov  al,8        jmp  key6key4:   test al,4        je   key5        mov  al,10h        jmp  key6key5:   test al,8        je   nkey        mov  al,18hkey6:   add  al,bl        cmp  al,10h        jnc  fkey        mov  bx,offset KeyTable        xlat        pop cx        pop dx        pop bxfkey:   retcode ends       end Start

 

 

 

 


 

功能加强版:(所有括号自动匹配(如25*((15+5)+125)-10*(21*6)=   ),还有溢出警报(警示灯),并显示,error)

 

;******************************************; 硬件综合实训 模拟计算器实验; By 叶泽坤 冯弘承 许金龙 宋彬彬;  2015.3;******************************************stack segment stack       db 1024 dup(?)stack endsdata segment    LedMap       db    0c0h,0f9h,0a4h,0b0h,099h,092h,082h,0f8h                  ;0 1 2 3 4.....                 db    080h,090h,088h,083h,0c6h,0a1h,086h,08eh    KeyTable     db    07h,04h,08h,05h,09h,06h,0ah,0bh                          ;键码定义                 db    01h,00h,02h,0fh,03h,0eh,0ch,0dh    bit          dw    0h    stack_sign   db    0ffh,   100 dup(?)                                       ;符号栈    stack_numb   dw    0ffffh, 100 dup(?)                     ;操作数栈    OUTSEG  equ  0ffdch                                          ;段控制口    OUTBIT  equ  0ffddh                                         ;位控制口/键扫口    IN_KEY  equ  0ffdeh                                                         ;键盘读入口    PA      EQU 0FFD8H    PB      EQU 0FFD9H    PC      EQU 0FFDAH    PCTL    EQU 0FFDBH    TEN     db   10    LedBuf  db   00h,  00h, 00h, 00h, 00h, 00h                        ;显示缓冲data endscode    segment'code'        assume cs:code,ds:data,ss:stack        org  1000hStart:        mov  LedMap+0,0c0h                                 ;初始化工作        mov  LedMap+1,0f9h        mov  LedMap+2,0a4h        mov  LedMap+3,0b0h        mov  LedMap+4,099h        mov  LedMap+5,092h        mov  LedMap+6,082h        mov  LedMap+7,0f8h        mov  LedMap+8,080h        mov  LedMap+9,090h        mov  LedMap+10,088h        mov  LedMap+11,083h        mov  LedMap+12,0c6h        mov  LedMap+13,0a1h        mov  LedMap+14,086h        mov  LedMap+15,08eh        mov  KeyTable+0, 07h        mov  KeyTable+1, 04h        mov  KeyTable+2, 08h        mov  KeyTable+3, 05h        mov  KeyTable+4, 09h        mov  KeyTable+5, 06h        mov  KeyTable+6, 0ah        mov  KeyTable+7, 0bh        mov  KeyTable+8, 01h        mov  KeyTable+9, 00h        mov  KeyTable+10, 02h        mov  KeyTable+11, 0fh        mov  KeyTable+12, 03h        mov  KeyTable+13, 0eh        mov  KeyTable+14, 0ch        mov  KeyTable+15, 0dh        mov stack_sign,0ffh;        mov stack_numb,0ffffh;        mov  TEN,10        mov ch,0ffh;        call get0        ss1:            mov bl,ch                                    ;前一个符号      call show                                    ;显示灯      mov al,20h;      call getkey                                                   ;获得键      cmp al,20h;                                 ;是否有键按下      je  ss1;                              ;若无键按下,重新显示      and  al,0fh                                 ;高位清零!      call myDelay                                ;这段时间应该等于手离开键盘的时间      mov ch,al;                             ;保存前一个符号      cmp al,10      jnb next0                                   ;若是数字:      cmp bl,10      jb go1      call clearbuf;      cmp dx,0                              ;若是0,则buff改为0先      jne  go1      call clearbuf;  go1:      call renew_led;                            ;更新显示      inc bit                                  ;位数+1      cmp bit,5      jne gonext1      call error;      jmp ss1  gonext1:      mov bh,al ;                             ;乘以10加个位法      mov ax,dx ;      mul TEN   ;      add al,bh ;      adc ah,0  ;      mov dx,ax ;                                  ;中间结果暂存与dx      jmp ss1;next0:                                         ;若是符号      cmp bl,10      jnb go0                                                       ;之前的是符号就跳      call mypush_numb                           ;先将之前的数字入栈  go0:      mov dx,0;      cmp al,0fh                               ;判断是否=      jne go3  go4:                                        ;是的话      cmp byte ptr stack_sign[si],0ffh                 ;是的话,一直爆栈,是否栈底      jne go11      call get_ans                            ;是栈底,显示结果结束。      jmp ss1  go11:      call calcu      jmp go4; go3:      cmp al,0ch                                 ;是否复位      jne go5      call get0;      jmp ss1;go5:      cmp al,0eh;                                 ;是否括号      jne go2      cmp bl,0feh;      je  go6      cmp bl,10                             ;是否左括号 (符号后面必是左括号)      jnb leftgo6:      mov ch,0feh;      cmp byte ptr stack_sign[si],0eh;                ;若是右括号,是否遇到左括号      jne go12      call mypop_sign                              ;遇到左括号,出栈之      jmp ss1  go12:      call calcu      jmp go6left:      call mypush_sign                           ;左括号入站      jmp ss1go2:      cmp byte ptr stack_sign[si],0eh                ;否则必是运算符号,比较优先级      jne  go7      call mypush_sign                           ;若是栈顶是左括号,必入栈      jmp ss1go7:      cmp al,0dh;                               ;若是乘号      jne go9      cmp byte ptr stack_sign[si],0dh;               ;栈顶是否也是乘号      jne go8      call calcu                                ;计算,并*入栈  go8:      call mypush_sign      jmp ss1  go9:                                             ;若是加减号,必爆栈计算      cmp  si,0                                  ;栈是否空,空必入栈      jne  go10      call mypush_sign      jmp ss1  go10:      call calcu      call mypush_sign      jmp  ss1;**********************爆栈计算子程序************************calcu:                                 push ax      push bx      push cx      push dx      call mypop_sign      mov bl,al      call mypop_numb      push dx      call mypop_numb      mov ax,dx      pop dx      cmp bl,0ah;      je myadd      cmp bl,0bh;      je mysub      cmp bl,0dh;      je mymulmyadd:      add ax,dx      mov dx,ax      call mypush_numb      pop dx      pop cx      pop bx      pop ax      ret  mysub:      sub ax,dx      mov dx,ax      call mypush_numb      pop dx      pop cx      pop bx      pop ax      ret  mymul:      mul dx      cmp dx,0      je go13      call get0      call error      jmp ss1;      ret  go13:      mov dx,ax      call mypush_numb      pop dx      pop cx      pop bx      pop ax      ret  ;**********************将答案(在栈底)显示器buf修改子程序************************get_ans:                                           push bx;      push dx;      push ax;      push si      push di      call mypop_numb;            ;初始值弹出到DX      mov di,5;                    ;从左边低位开始      mov  bx,10;      mov  ax,dx                   ;将结果放在ax便于除法  do:      xor  dx,dx      div  bx                       ;ax/10 ,余数在dx,结果在ax      mov si,dx      mov dl,LedMap[si];      mov  LedBuf[di],dl          ;改余数对应位的buff      dec di;      cmp ax,0;      jne  do      pop di      pop si      pop ax      pop dx      pop bx      ret;**********************抛出异常子程序************************error:      push ax      mov dx,PCTL      mov al,080h;      out dx,al      mov dx,PB      mov al,00h      out dx,al;        mov  LedBuf+0,86h                            mov  LedBuf+1,0afh      mov  LedBuf+2,0afh      mov  LedBuf+3,0a3h      mov  LedBuf+4,0afh      mov  LedBuf+5,0ffh      mov dx,0              pop ax      ret;;*********************清buff,显示"0"子程序***********************clearbuf:      mov  LedBuf+0,0ffh                            mov  LedBuf+1,0ffh      mov  LedBuf+2,0ffh      mov  LedBuf+3,0ffh      mov  LedBuf+4,0ffh      mov  LedBuf+5,0c0h      mov dx,0      mov bit,0      ret;;************************显示"0"子程序******************************get0:      mov  LedBuf+0,0ffh                            mov  LedBuf+1,0ffh      mov  LedBuf+2,0ffh      mov  LedBuf+3,0ffh      mov  LedBuf+4,0ffh      mov  LedBuf+5,0c0h      mov dx,PCTL      mov al,080h;      out dx,al      mov dx,PB      mov al,0ffh      out dx,al;             mov dx,0      mov si,0      mov di,0      mov bit,0      ret;;**********************符号、数字的入栈、出栈************************mypush_sign:                        ;al->符号入栈 子程序             inc si             mov byte ptr  stack_sign[si],al             retmypush_numb:                      ;dx->操作数入栈子程序             add di,2             mov word ptr   stack_numb[di],dx             retmypop_sign:                      ;出栈->al             mov al,stack_sign[si]             cmp al,0ffh             je  next3             dec sinext3:             retmypop_numb:                   ;出栈->dx             mov dx,stack_numb[di]             cmp dx,0ffffh             je  next11             dec di             dec dinext11:             ret;**********************更新buff子程序子程序************************renew_led:                                      push si      push bx      push dx      mov si,bit;      mov bx,offset LedBuf;      cmp si,0      je  go  again:      neg si      mov dx,[bx+si+6];      mov [bx+si+5],dx;      neg si      dec si      jnz   again  go:      mov ah,0      mov si,ax      mov dl, [LedMap+si]      mov [bx+5],dl      pop dx      pop bx      pop si      ret;************************延时子程序************************Delay:                                             push  cx        mov   cx,256        loop  $        pop   cx        ret;********************键盘读入延时子程序********************myDelay:                                            push  cx        mov   cx,25xx:        call show        loop  xx        pop   cx        ret;********************显示当前buff的子程序********************show:                                                        push ax;        push bx        push cx;        push dx;        mov  bx,offset LEDBuf        mov  cl,6                                 ;共6个八段管        mov  ah,00100000b                   ;从左边开始显示DLoop:       ; mov  dx,OUTBIT       ; mov  al,0       ; out  dx,al                                 ;关所有八段管        mov  al,[bx]        mov  dx,OUTSEG        out  dx,al        mov  dx,OUTBIT        mov  al,ah        out  dx,al                             ;显示一位八段管        push ax        mov  ah,1        call Delay        pop  ax        shr  ah,1        inc  bx        dec  cl        jnz  DLoop       ; mov  dx,OUTBIT       ; mov  al,0h;       ; out  dx,al              ;关所有八段管        pop dx        pop cx        pop bx        pop ax;        ret;*************************获取按键的数值********************getkey:                       ;结果存在al中        push bx        push dx        push cx        mov  al,0ffh          ;关显示口        mov  dx,OUTSEG        out  dx,al        mov  bl,0        mov  ah,0feh        mov  cx,8key1:   mov  al,ah        mov  dx,OUTBIT        out  dx,al        shl  al,1        mov  ah,al        nop        nop        nop        nop        nop        nop        mov  dx,IN_KEY        in   al,dx        not  al        nop        nop        and  al,0fh        jnz  key2        inc  bl        loop key1nkey:   mov  al,20h        pop cx        pop dx        pop bx        retkey2:   test al,1        je   key3        mov  al,0        jmp  key6key3:   test al,2        je   key4        mov  al,8        jmp  key6key4:   test al,4        je   key5        mov  al,10h        jmp  key6key5:   test al,8        je   nkey        mov  al,18hkey6:   add  al,bl        cmp  al,10h        jnc  fkey        mov  bx,offset KeyTable        xlat        pop cx        pop dx        pop bxfkey:   retcode  ends       end  Start


 

 

 

1 0
原创粉丝点击