仿真原理图如下(proteus仿真工程文件可到本帖附件中下载)
8086汇编语言源程序如下:
- DATA SEGMENT
- X DB ?,?,?,? ;存放数据的每一位
- X1 DW ? ;存放第一个数据值
- X2 DW ? ;存放第二个数据值
- Y DW ? ;存放运算结果
- S DB ? ;存放运算符号值
- E DB ? ;按下等号键标记
- CC DB ? ;存放运算数据位数
- H DB 0 ;存放按键行号
- L DB 0 ;存放按键列号
- DISCODE DB 3FH,06H,5BH,4FH,66H,6DH,7DH,07H,7FH,6FH,77H,7CH,39H,5EH,79H,71H ;段码表
- DATA ENDS
- CODE SEGMENT
- ASSUME CS:CODE,DS:DATA
- START: MOV AX,DATA
- MOV DS,AX
- MOV AL,90H ;设置为A口输入,B口输出,C口输出
- OUT 46H,AL
- MOV DI,OFFSET X+3 ;DI指向X的高位
- KKK: CALL KEY ;扫描按键
- JMP KKK
- ;以下为按键扫描子程序,程序返回后,在变量H和L中存放当前按键的行列号
- KEY PROC
- CHECK: CALL DISP ;等待按键按下的同时进行显示
- MOV AL,0F0H ;所有行输出低电平
- OUT 44H,AL
- IN AL,40H
- CMP AL,0FFH ;读列值
- JZ CHECK ;若都为高电平则无键按下,等待
- MOV CX,50
- LOOP $ ;延时消抖
- IN AL,DX ;重读列值
- CMP AL,0FFH
- JZ CHECK ;无键按下一直等待
- MOV H,0 ;有键按下,先把行列号变量清0
- MOV L,0
- MOV BL,01H
- MOV BH,0FEH ;扫描法读键值:从第一行开始测试,即PC0输出低电平
- NEXT: MOV AL,BH
- OUT 44H,AL
- NEXTH: IN AL,40H ;读列值,判断是第几列有键按下
- TEST AL,BL ;从第一列开始判断
- JZ WAIT0
- ROL BL,1
- CMP BL,10H ;当前行状态下没有任何列有键按下,则转为对下一行的测试
- JZ NEXTL
- INC H ;每判断一列,列号加1
- JMP NEXTH ;再对下一列进行判断
- NEXTL: MOV H,0
- MOV BL,01H
- ROL BH,1 ;对下一行测试,让下一个PC口输出低电平
- CMP BH,0EFH
- JZ EXIT
- INC L
- JMP NEXT
- WAIT0: IN AL,40H ;若有键按下,则等该按键松开后再计算键值
- CMP AL,0FFH
- JNZ WAIT0
- MOV CX,50
- LOOP $ ;延时消抖
- IN AL,40H
- CMP AL,0FFH
- JNZ WAIT0
- CALL KEYVALUE ;调计算键值子程序
- EXIT: RET
- KEY ENDP
- ;以下为计算键值子程序,通过行列号计算键值(键值=列号*4+行号)
- ;键值存放在DL寄存器中
- KEYVALUE PROC
- MOV DL,L
- MOV DH,H
- SHL DL,1
- SHL DL,1 ;列号乘4
- ADD DL,DH
- CMP DL,9 ;按下的是数字键
- JNG NUM_CALL
- CMP DL,14
- JL CONT_CALL ;按下的是运算键
- CMP DL,14
- JZ OUTP_CALL ;按下的是等于键
- CMP DL,15
- JZ CLR_CALL ;按下的是清除键
- NUM_CALL: CALL NUMBER ;调数字键处理子程序
- JMP EXIT1
- CONT_CALL: MOV S,DL ;存放运算键的键值
- MOV E,0
- CALL COUNT ;调运算键处理子程序,计算第一个加数
- JMP EXIT1
- OUTP_CALL: CALL OUTP ;调等号键处理子程序
- JMP EXIT1
- CLR_CALL: CALL CLEAR ;调清除键处理子程序
- EXIT1: RET
- KEYVALUE ENDP
- ;以下为清除键处理子程序,按下清除键后,X变量全部清0
- CLEAR PROC
- MOV X[3],0
- MOV X[2],0
- MOV X[1],0
- MOV X[0],0
- CALL BITP
- RET
- CLEAR ENDP
- ;以下为等号键处理子程序,该子程序负责将第二个运算数据的数值计算出来存入X2变量
- ;并根据运算符号,调用相应的运算子程序
- OUTP PROC
- PUSH AX
- PUSH DX
- PUSH BX
- INC E
- CALL COUNT ;调运算键处理子程序,计算第二个运算数据
- CMP S,10
- JZ ADD_CALL ;运算符为加号,则调用加法子程序
- CMP S,11
- JZ SUB_CALL ;运算符为减号,则调用减法子程序
- CMP S,12
- JZ MUL_CALL ;运算符为乘号,则调用乘法子程序
- CMP S,13
- CALL DIVP ;运算符为除号,则调用除法子程序
- JMP STORE1
- ADD_CALL: CALL ADDP
- JMP STORE1
- SUB_CALL: CALL SUBP
- JMP STORE1
- MUL_CALL: CALL MULP
- STORE1: MOV AX,Y ;以下程序将各运算子程序返回的运算结果,按位分解,送入X变量
- MOV DX,0
- MOV BX,1000
- DIV BX
- MOV X[0], AL
- MOV AX,DX
- MOV BL,100
- DIV BL
- MOV X[1],AL
- MOV AL,AH
- MOV AH,0
- MOV BL,10
- DIV BL
- MOV X[2],AL
- MOV X[3],AH
- POP BX
- POP DX
- POP AX
- RET
- OUTP ENDP
- ;以下为运算键处理子程序,该程序将第一个运算数据的数值计算出来并存入X1变量
- ;或者将第二个运算数据的数值计算出来并存入X2变量
- ;将运算符的值存入S变量
- COUNT PROC
- PUSH AX
- PUSH BX
- PUSH DX
- MOV DX,0
- CALL BITP ;测试X中的数据是多少位
- CMP CC,4 ;输入的数据是4位数 ?
- JZ C4
- CMP CC,3 ;输入的数据是3位数 ?
- JZ C3
- CMP CC,2 ;输入的数据是2位数 ?
- JZ C2
- JMP C1 ;输入的数据是1位数 ?
- C4: MOV AX,0
- MOV AL,X[0]
- MOV BX,1000
- MUL BX
- MOV DX,AX
- C3: MOV AL,X[1]
- MOV BL,100
- MUL BL
- ADD DX,AX
- C2: MOV AL,X[2]
- MOV BL,10
- MUL BL
- ADD DX,AX
- C1: MOV AL,X[3]
- MOV AH,0
- ADD DX,AX
- CMP E,1
- JNZ X1_S
- MOV X2,DX ;按下的是等号,则将第二个运算数据的值存入X2变量
- JMP EXIT3
- X1_S: MOV X1,DX ;按下的是运算符号,则将第一个运算数据的值存X1变量
- MOV X[3],0 ;清空X变量
- MOV X[2],0
- MOV X[1],0
- MOV X[0],0
- EXIT3: POP DX
- POP BX
- POP AX
- RET
- COUNT ENDP
- ;以下为数字键处理子程序
- ;该程序,将输入的数据按位存放在X变量中,并由CC记录数据的位数
- NUMBER PROC
- CMP E,1
- JNZ CONTINUE
- MOV E,0
- CALL CLEAR
- CONTINUE: CMP CC,0 ;目前数据为0位,即没有数据,则转到SSS
- JZ SSS
- ;若已有数据,以下程序将X左移8位。
- ;例如:先输入“1”,当再输入2时,
- ;先要将“1”从个位移到十位,然后再将“2”存放到个位
- PUSH AX
- PUSH DX
- MOV AL,X[3]
- MOV AH,X[2]
- MOV DL,X[1]
- MOV DH,X[0]
- MOV CX,8
- LL: SHL AX, 1
- RCL DX,1
- LOOP LL
- MOV X[3],AL
- MOV X[2],AH
- MOV X[1],DL
- MOV X[0],DH
- POP DX
- POP AX
- SSS: MOV [DI],DL ;将当前键入的数据存放到X的最低位
- INC CC ;数据位数加1
- CMP CC,4 ;判断数据位数
- JNG EXIT2
- MOV CC,0 ;如果数据超过4位,重新从最低位开始存放
- MOV X[2],0
- MOV X[1],0
- MOV X[0],0
- EXIT2: CALL DISP ;调显示子程序,显示输入的数据
- RET
- NUMBER ENDP
- ;加法子程序
- ADDP PROC
- PUSH AX
- MOV AX,X1
- ADD AX,X2
- MOV Y,AX
- POP AX
- RET
- ADDP ENDP
- ;减法子程序
- SUBP PROC
- PUSH AX
- MOV AX,X1
- SUB AX,X2
- MOV Y,AX
- POP AX
- RET
- SUBP ENDP
- ;乘法子程序
- MULP PROC
- PUSH AX
- PUSH DX
- MOV AX,X1
- MOV DX,X2
- MUL DX
- MOV Y,AX
- POP DX
- POP AX
- RET
- MULP ENDP
- ;除法子程序
- DIVP PROC
- PUSH AX
- PUSH BX
- PUSH DX
- MOV DX,0
- MOV AX,X1
- MOV BX,X2
- DIV BX
- MOV Y,AX
- POP DX
- POP BX
- POP AX
- RET
- DIVP ENDP
- ;显示子程序 ,将X中的数值按位显示出来
- DISP PROC
- PUSH BX
- PUSH AX
- MOV BH,0
- LEA SI,DISCODE
- CALL BITP ;测试X位数
- CMP CC,4
- JZ QIAN
- CMP CC,3
- JZ BAI
- CMP CC,2
- JZ SHI
- CMP CC,1
- JMP G
- JMP NONE
- QIAN: MOV AH,11100000B ;从第4位开始显示
- MOV AL,AH
- OUT 44H,AL
- MOV BL,X[0]
- MOV AL,[SI+BX]
- OUT 42H,AL
- CALL DELY
- MOV AL,0
- OUT 42H,AL
- BAI: MOV AH,11010000B ;从第3位开始显示
- MOV AL,AH
- OUT 44H,AL
- MOV BL,X[1]
- MOV AL,[SI+BX]
- OUT 42H,AL
- CALL DELY
- MOV AL,0
- OUT 42H,AL
- SHI: MOV AH,10110000B ;从第2位开始显示
- MOV AL,AH
- OUT 44H,AL
- MOV BL,X[2]
- MOV AL,[SI+BX]
- OUT 42H,AL
- CALL DELY
- MOV AL,0
- OUT 42H,AL
- G: MOV AH,01110000B ;从第1位开始显示
- MOV AL,AH
- OUT 44H,AL
- MOV BL,X[3]
- MOV AL,[SI+BX]
- OUT 42H,AL
- CALL DELY
- JMP EXIT4
- ……………………
- …………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码 代码与Proteus仿真下载:
计算器8086.7z
(45.45 KB, 下载次数: 109)
|