基于8086与Proteus仿真的44键盘计算器的设计 下载本文

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