📄 键盘功能扩展.asm
字号:
DATAS SEGMENT
;此处输入数据段代码
BUFFER DB 16H DUP(0)
BUFPT1 DW 0
BUFPT2 DW 0
;当两个指针相等时候队为空
KBFLAG DB 0 ;标志位
PROMPT DB '---KBD-IO PROGRAME BEGDIN --- ',13.10,'&'
SCANTAB DB 0,0,'1234567890-=',8,0
DB 'qwertyuiop[]',0DH,0
DB 'asdfghjkl',0,0,0,0
db 'zxcvbnm,./',0,0,0
db ' ',0,0,0,0,0,0,0,0,0,0,0,0,0
db '789-456+1230.'
SHIFTTAB DB 0,0,'!@#$%^&*()_+',0,0
DB 'QWERTYUIOP{}_+',0DH,0
DB 'ASDFGHJKL:"',0,0,0
DB 'ZXCVBNM<>?',0,0,0
DB ' ',26 DUP(0)
even
oldcs9 dw ?
oldip9 dw ?
DATAS ENDS
STACKS SEGMENT
;此处输入堆栈段代码
STACKS ENDS
CODES SEGMENT
MAIN PROC FAR
ASSUME CS:CODES,DS:DATAS,SS:STACKS
START:
MOV DX, DATAS
MOV DS,DX
CLI
MOV AL,9
MOV AH,35
INT 21H
MOV OLDCS9,ES
MOV OLDIP9,BX
PUSH DS
MOV DX,SEG KBINT
MOV DS,DX
LEA DX,KBINT
MOV AL,9H
MOV AH,25H
INT 21H
POP DS
IN AL,21H
AND AL,0FDH ;开中断屏蔽
OUT 21H,AL
FOREVER:
CALL KBGET
TEST KBFLAG,80H
JNZ ENDINT
PUSH AX
CALL DISPCHAR
POP AX
CMP AL,0DH
JNZ FOREVER
MOV AL,0AH
CALL DISPCHAR
JMP FOREVER
ENDINT:MOV DX,OLDIP9 ; 恢复中断向量
MOV AX,OLDCS9
MOV DS,AX
MOV AL,9H
MOV AH,25H
INT 21H
MOV AH,4CH ;返回DOS
INT 21H
MAIN ENDP
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
KBGET PROC NEAR
;队列处理函数
PUSH BX
CLI
;比较判断队列是否已经存满
MOV BX,BUFPT1
CMP BX,BUFPT2
;若不满则转向KBGET2
JNZ KBGET2
;判断标志位是否为0
TEST KBFLAG,80H
; 循环条件
;判断是否为看是否正确
;若不为0,则转想KBGET3
JNZ KBGET3
STI
POP BX
JMP KBGET
KBGET2:
MOV AL,[BUFFER+BX] ;将队列中传入AL中显示
INC BX ;增加BX
CMP BX,16 ;与16判断看是否到了队尾
JC KBGET3; 若没到则转向KBGET3
MOV BX,0
KBGET3:
MOV BUFPT1,BX
POP BX
RET
KBGET ENDP
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
KBINT PROC FAR ;键盘中断程序
PUSH BX; 保存使用的寄存器
PUSH AX
IN AL,60H ;CPU取出扫描码并放入AL
PUSH AX ; 发出应答信号
IN AL,61H
OR AL,80H
OUT 61H,AL
AND AL,7FH ;恢复应答信号
OUT 61H,AL
POP AX
TEST AL,80H
jnz kbint2
cmp al,54;当输入左SHIFT时候改变标志位然后退出中断
jnz next1
or kbflag ,1
jmp outs
NEXT1: CMP AL,42;当输入右SHIFT时候改变标志位然后退出中断
JNZ NEXT2
OR KBFLAG ,2
JMP OUTS
NEXT2: TEST KBFLAG ,3
JZ NEXT3;判断标志位最后2位是否为1
MOV BX, OFFSET SHIFTTAB;若最后两位为1则转换SHIFT表
XLAT SHIFTTAB
JMP NEXT4
NEXT3: MOV BX,OFFSET SCANTAB;标志位最后两位为0 则转向SCAN表
XLAT SCANTAB
NEXT4: CMP AL,0;若输入其他功能键则退出
JNZ KBINT4
MOV KBFLAG,80H
JMP OUTS
KBINT4: MOV BX,BUFPT2
MOV [BX+BUFFER],AL
INC BX
CMP BX,16
JC KBINT3 ;比较是否到了队尾
MOV BX,0 ;到队尾则循环转向队首
KBINT3:
CMP BX,BUFPT1 ;判断队是否满
JZ KBINT2 ;满了则不再添加字符
MOV BUFPT2,BX ; 没满则在队尾添加
KBINT2:
CMP AL,0AAH;对SHIFT键松开要特殊处理
JZ LOOP1
CMP AL,0B6H
JZ LOOP1
JMP OUTS
LOOP1:
MOV KBFLAG,0 ;松开SHIFT则 标志位边为0
OUTS: CLI ;关中断
MOV AL,20H
OUT 20H ,AL ;关屏蔽
POP AX
POP BX
STI
IRET
KBINT ENDP
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
DISPCHAR PROC NEAR
PUSH BX ;显示字符
MOV BX,0
MOV AH,0EH
INT 10H
POP BX
RET
DISPCHAR ENDP
CODES ENDS
END START
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -