汇编计算器
来源:互联网 发布: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
- 汇编计算器
- 32位汇编写简单加减乘除计算器
- mips汇编简单实例——一个小计算器
- 【汇编】计算器,支持带括号的四则混合运算
- mips汇编简单实例——一个小计算器
- mips汇编简单实例——一个小计算器
- 计算器
- 计算器
- /* 计算器 */
- 计算器
- 计算器
- 计算器
- 计算器
- 计算器
- 计算器
- 计算器
- 计算器
- 计算器
- HDU 1231 最大连续子序列
- 什么是 DNS Prefetch ?
- JNDI ??
- 谈及jsp
- bcgcontroler 简介
- 汇编计算器
- 输入输出的注意事项
- ASM增加局部变量
- UVALive - 4727 Jump 约瑟夫环
- codeforces 159D Palindrome pairs
- UNP 学习笔记4
- HDU 1274 展开字符串
- INVISIBLE DESIGN设计之下
- PAT1091解题报告