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