驻留程序TSR(Terminate but Stay Resident)是一种特殊应用程序,它在装入内存运行后,其部分代码仍然驻留在内存,当该段代码被激活时,它又进入运行状态。常用的驻留程序是作为某个中断处理程序的一部分,其激活条件就是系统产生了此中断的中断请求。
虽然驻留程序可根据具体的需要有不同的编写方式,但其典型结构包括以下几部分:
例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
例10.16 编写一个驻留程序,它可显示当前时间的秒数。
解:
CSEG SEGMENT 'CODE' ORG 100H start: JMP init INT1C DD ? SEC DW ? TSR: PUSH AX PUSH BX PUSH CX PUSH DX PUSH BP PUSH DS PUSH ES ;保存所用到的寄存器 MOV AX, CS MOV DS, AX MOV ES, AX ;把CS的值赋给DS和ES MOV AH, 2H INT 1AH ;读取当前时间 MOV DL, DH AND DH, 0FH MOV CL, 4 SHR DL, CL ADD DX, 3030H MOV SEC, DX ;把当前秒数转化成字符串 MOV AH, 13H MOV AL, 0 MOV BH, 0 MOV BL, 7 MOV CX, 2 MOV DX, 004EH ;指定显示位置为(0,78) LEA BP, SEC INT 10H ;在指定位置显示秒数 POP ES ;恢复所用寄存器的值 POP DS POP BP POP DX POP CX POP BX POP AX JMP CS:INT1C ;转向中断1CH原服务程序 init: CLI MOV AX, 351CH INT 21H MOV word ptr INT1C, BX MOV word ptr INT1C+2, ES MOV AX, 251CH LEA DX, TSR INT 21H STI LEA DX, init ADD DX, 15 MOV CL, 4 ;把init的偏移量转换成“节数” SHR DX, CL ;每节内有16个字节 MOV AX, 3100H INT 21H CSEG ENDS END start