例10.15 在NumLock处于“开状态”时,每按小键盘(Numeric Keypad)上的数字键,给出“啪啪”响声。

解:
CSEG SEGMENT 'CODE'
ORG 100H
start:
JMP init
INT9 DD ?
TSR:
PUSH AX
PUSH CX
PUSH DS ;保存寄存器
MOV AH, 2
INT 16H ;读取键盘当前状态
TEST AL, 00100000B ;检测NumLock的状态
JZ TSRExit
IN AL, 60H
CMP AL, 71
JL TSRExit
CMP AL, 83
JG TSRExit
MOV AL, 10110110B
OUT 43H, AL ;向端口43H送特定的数0B6H
MOV AX, 1000
OUT 42H, AL
MOV AL, AH
OUT 42H, AL ;向端口42H送声音频率
IN AL, 61H ;读取扬声器的当前状态
MOV AH, AL ;把扬声器的状态保存在AH中
OR AL, 03
OUT 61H, AL ;开声音
MOV CX, 9000
delay:
LOOP delay ;声音延迟
MOV AL, AH
OUT 61H, AL ;恢复扬声器原来的状态,即关声音
TSRExit:
POP DS
POP CX
POP AX  ;恢复寄存器
JMP CS:INT9 ;转向中断9H原来的处理程序
init:
CLI ;关中断
MOV AH, 35H
MOV AL, 09H
INT 21H
MOV WORD PTR INT9, BX
MOV WORD PTR INT9+2, ES ;保存中断9H原处理程序入口地址
MOV  AH, 25H
MOV AL, 09H
LEA DX, TSR
INT 21H ;设置中断9H新的处理程序入口地址
STI ;开中断
LEA DX, init
ADD DX, 15
MOV CL, 4 ;把init的偏移量转换成“节数”
SHR DX, CL ;每节内有16个字节
MOV AX, 3100H
INT 21H
CSEG ENDS
END start

关 闭