驻留程序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