标签:
开学第一周完成的汇编计算器:前后一共写了很多版本,下面是俩个版本:
by hfut 叶泽坤 冯弘承 许金龙 宋彬彬。
基础功能完善版:
stack segment stack db 1024 dup(?) stack ends data 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 ends code segment'code' assume cs:code,ds:data,ss:stack org 1000h Start: 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 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 left go6: mov ch,0feh; cmp byte ptr stack_sign[si],0eh; ;若是右括号,是否遇到左括号 jne go12 call mypop_sign ;遇到左括号,出栈之 jmp ss1 go12: call calcu jmp go6 left: call mypush_sign ;左括号入站 jmp ss1 go2: cmp byte ptr stack_sign[si],0eh ;否则必是运算符号,比较优先级 jne go7 call mypush_sign ;若是栈顶是左括号,必入栈 jmp ss1 go7: 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 mymul myadd: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 mov dx,ax call mypush_numb pop dx pop cx pop bx pop ax ret get_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 ret clearbuf: 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 ret mypush_numb : ;dx->操作数入栈子程序 add di,2 mov word ptr stack_numb[di],dx ret mypop_sign : ; 出栈->al mov al,stack_sign[si] cmp al,0ffh je next3 dec si next3: ret mypop_numb : ;出栈->dx mov dx,stack_numb[di] cmp dx,0ffffh je next11 dec di dec di next11: ret renew_led: ;更新buff子程序子程序 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,25 xx: call show loop xx pop cx ret show: ;显示当前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; 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,8 key1: 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 key1 nkey: mov al,20h pop cx pop dx pop bx ret key2: test al,1 je key3 mov al,0 jmp key6 key3: test al,2 je key4 mov al,8 jmp key6 key4: test al,4 je key5 mov al,10h jmp key6 key5: test al,8 je nkey mov al,18h key6: add al,bl cmp al,10h jnc fkey mov bx,offset KeyTable xlat pop cx pop dx pop bx fkey: ret code ends end Start
功能加强版:(所有括号自动匹配(如25*((15+5)+125)-10*(21*6)= ),还有溢出警报(警示灯),并显示,error)
;****************************************** ; 硬件综合实训 模拟计算器实验 ; By 叶泽坤 冯弘承 许金龙 宋彬彬 ; 2015.3 ;****************************************** stack segment stack db 1024 dup(?) stack ends data 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 ends code segment'code' assume cs:code,ds:data,ss:stack org 1000h Start: 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 left go6: mov ch,0feh; cmp byte ptr stack_sign[si],0eh; ;若是右括号,是否遇到左括号 jne go12 call mypop_sign ;遇到左括号,出栈之 jmp ss1 go12: call calcu jmp go6 left: call mypush_sign ;左括号入站 jmp ss1 go2: cmp byte ptr stack_sign[si],0eh ;否则必是运算符号,比较优先级 jne go7 call mypush_sign ;若是栈顶是左括号,必入栈 jmp ss1 go7: 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 mymul myadd: 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 ret mypush_numb: ;dx->操作数入栈子程序 add di,2 mov word ptr stack_numb[di],dx ret mypop_sign: ;出栈->al mov al,stack_sign[si] cmp al,0ffh je next3 dec si next3: ret mypop_numb: ;出栈->dx mov dx,stack_numb[di] cmp dx,0ffffh je next11 dec di dec di next11: 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,25 xx: 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,8 key1: 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 key1 nkey: mov al,20h pop cx pop dx pop bx ret key2: test al,1 je key3 mov al,0 jmp key6 key3: test al,2 je key4 mov al,8 jmp key6 key4: test al,4 je key5 mov al,10h jmp key6 key5: test al,8 je nkey mov al,18h key6: add al,bl cmp al,10h jnc fkey mov bx,offset KeyTable xlat pop cx pop dx pop bx fkey: ret code ends end Start
标签:
原文地址:http://blog.csdn.net/u011498819/article/details/44180347