这是我的第一TSR程序
是DOS下的时间显示程序
可以按F11暂停显示
可以按F12退出内存
.286
.MODEL SMALL
.CODE
;-----------------------
CLOCK DB 11 DUP(?)
FLAG DB 00H
OLD1C LABEL DWORD
OLD1COFF DW ?
OLD1CSEG DW ?
OLD09 LABEL DWORD
OLD09OFF DW ?
OLD09SEG DW ?
BUSY DB 00H
ZJW_PSP DW ?
ZJW_EVB DW ?
FLAG1 DB 0
;-----------------------
NEW1C PROC FAR
CMP CS:[FLAG],0
JE ONE
THE: IRET
ONE: CMP CS:[FLAG1],1
JE THE
PUSH AX
PUSH BX
PUSH CX
PUSH DX
PUSH SI
PUSH DS
MOV CS:[FLAG],1
LEA SI,CLOCK
MOV AH,02H
INT 1AH
MOV AH,CH
MOV AL,CL
MOV CL,4
SHR CH,CL
OR CH,30H
MOV DS:[SI],CH
INC SI
MOV CH,AH
AND CH,0FH
OR CH,30H
MOV DS:[SI],CH
INC SI
MOV DL,3AH
MOV DS:[SI],DL
INC SI
MOV AH,AL
SHR AL,CL
OR AL,30H
MOV DS:[SI],AL
INC SI
MOV AL,AH
AND AL,0FH
OR AL,30H
MOV DS:[SI],AL
INC SI
MOV DS:[SI],DL
INC SI
MOV AH,DH
SHR DH,CL
OR DH,30H
MOV DS:[SI],DH
INC SI
MOV DH,AH
AND DH,0FH
OR DH,30H
MOV DS:[SI],DH
INC SI
MOV DL,5AH
MOV DS:[SI],DL
INC SI
MOV DL,4AH
MOV DS:[SI],DL
INC SI
MOV DL,57H
MOV DS:[SI],DL
LEA SI,CLOCK
PUSH ES
PUSH DI
MOV AX,008AH
MOV DI,AX
MOV AX,0B800H
MOV ES,AX
MOV CX,11
MOV AH,34H
DISP: PUSH CX
MOV AL,[SI]
INC SI
MOV CX,1
STOSW
POP CX
LOOP DISP
POP DI
POP ES
MOV CS:[FLAG],0
EXIT1:POP DS
POP SI
POP DX
POP CX
POP BX
POP AX
EXIT: IRET
NEW1C ENDP
NEW09 PROC FAR
CMP CS:BUSY,0
JE TWO
JMP CS:OLD09
TWO: PUSH AX
IN AL,060H
PUSH AX
IN AL,061H
OR AL,080H
OUT 061H,AL
AND AL,07FH
OUT 061H,AL
MOV AL,020H
OUT 020H,AL
POP AX
CMP AL,58H
JNE EXIT_NOT
PUSH ES
PUSH DS
PUSH BX
MOV BX,1CH*04H
XOR AX,AX
MOV ES,AX
MOV AX,CS:[OLD1COFF]
MOV ES:[BX],AX
MOV AX,CS:[OLD1CSEG]
MOV ES:[BX+2],AX
MOV BX,09H*04H
XOR AX,AX
MOV AX,CS:[OLD09OFF]
MOV ES:[BX],AX
MOV AX,CS:[OLD09SEG]
MOV ES:[BX+2],AX
MOV BX,1
MOV AX,CS:[ZJW_EVB]
MOV ES,AX
MOV WORD PTR ES:[BX],0
MOV AX,CS:[ZJW_PSP]
MOV ES,AX
MOV WORD PTR ES:[BX],0
POP BX
POP DS
POP ES
EXIT_NOT:
CMP AL,57H
JNE EXT
CMP CS:FLAG1,1
JNE EZ
MOV CS:FLAG1,0
JMP EXT
EZ: MOV CS:FLAG1,1
EXT: POP AX
JMP CS:OLD09
NEW09 ENDP
INIT: MOV AX,DS
DEC AX
MOV CS:[ZJW_PSP],AX
MOV BX,2CH
MOV AX,DS:[BX]
DEC AX
MOV CS:[ZJW_EVB],AX
PUSH CS
POP DS
MOV AX,351CH
INT 21H
LEA DX,NEW1C
CMP DX,BX
JE EX
MOV CS:OLD1CSEG,ES
MOV CS:OLD1COFF,BX
MOV AX,3509H
INT 21H
MOV CS:OLD09OFF,BX
MOV CS:OLD09SEG,ES
MOV AX,251CH
LEA DX,NEW1C
INT 21H
MOV AX,2509H
LEA DX,NEW09
INT 21H
LEA DX,PROMPT
MOV AH,09H
INT 21H
MOV AX,3100H
LEA DX,INIT
MOV CL,4
SHR DX,CL
ADD DX,11H
INT 21H
EX: MOV AH,4CH
INT 21H
PROMPT DB 0AH,0DH
DB 'CLOCKDISP ver 2.30'
DB 0AH,0DH,'H.S-Software Zhong Junwei copyright(c) 1997.1'
DB ' by Mr.Zjw'
DB 0AH,0DH
DB 'HotKey:F11 Is Pause Disp;F12 Is Exit System'
DB 0AH,0DH,'$'
END INIT
INTA00 EQU 20H
INTA01 EQU 21H
DATA SEGMENT
MESS DB 'THIS IS A 8259 INTERRUPT!',0AH,0DH,'$'
DATA ENDS
CODE SEGMENT
ASSUME CS:CODE,DS:DATA
START: MOV AX,CS
MOV DS,AX
MOV DX,OFFSET INT_PROC
MOV AX,250BH
INT 21H
CLI
MOV DX,INTA01
IN AL,DX
AND AL,0FBH
OUT DX,AL
MOV BX,10
STI
L1: JMP L1
INT_PROC:MOV AX,DATA
MOV DS,AX
MOV DX,OFFSET MESS
MOV AH,09H
INT 21H
MOV DX,INTA00
MOV AL,20H
OUT DX,AL
SUB BX,1
JNZ NEXT
MOV DX,INTA01
IN AL,DX
OR AL,04H
OUT DX,AL
STI
MOV AH,4CH
INT 21H
NEXT: IRET
CODE ENDS
END START
CODE SEGMENT
ASSUME CS:CODE,DS:DDATA,ES:EDATA,SS:STAK
START:
MOV AX,0
MOV ES,AX
MOV SI,20H ;timer0 ISR vector address is stored here
MOV WORD PTR ES:[SI], OFFSET TIMER_0_ISR
MOV WORD PTR ES:[SI+2], SEG TIMER_0_ISR
MOV DX,0F804H ;set the prescale to 512 p.8-7
IN AX,DX
AND AX,0FE00h
OR AX,01Fh
OUT DX,AX
MOV DX,0F834H ;disable the counters p.10-21
MOV AL,10000000B
OUT DX,AL
MOV DX,0F043H ;counter 0 will read/write least sig dig
MOV AL,00110100B ;first, the most second,mode 2, binary p.10-25
OUT DX,AL
MOV DX,0F040H ;the prescale (FFH) and timer count (FFFF)
MOV AL,0ffH ;give a delay of 1/2 sec approximately p.10-26
OUT DX,AL ;must be written twice for least/most sig
OUT DX,AL ;count
MOV DX,0F834H
MOV AL,01000010B ;enable timers, connect them all to
;PSCLK, disable timers 1 & 2, enable 0 p.10-21
OUT DX,AL
MOV DX,0F021H ;OCW1: enable timer 1 interrupt p.9-25
IN AL,DX
AND AL,0FEH
OUT DX,AL
MOV AL,0 ;initialize SI and AL for the infinite loops
MOV SI,0
LOOP_FOREVER:
MOV DX,0B800H ;DS holds the screen offset for video output
MOV DS,DX
MOV AH,2 ;AH holds color code, 2 is green
ADD AL,1 ;add 1 to AL
AND AL,0FH ;convert AL for ASCII representation
OR AL,030H
MOV [DS:3974],AX ;output the character to screen
MOV CX,0FFFH ;create a wait loop of count FFFFFH
LOOP1:
PUSH CX
MOV CX,0FH
LOOP2:
LOOP LOOP2
POP CX
LOOP LOOP1
JMP LOOP_FOREVER
TIMER_0_ISR:
PUSH AX
PUSH DX
PUSH DS
PUSH ES
MOV DX,0B800H ;initialize SI and AL for the infinite loops
MOV DS,DX
ADD SI,1 ;add 1 to SI
AND SI,000FH ;convert SI for ASCII representation, notice that
OR SI,0430H ;the top byte holds 4 which represents the color red
MOV AX,SI
MOV [DS:3972],AX ;output the character to screen
MOV DX,0F020H
MOV AL,20H ;end of interrupt command for 8259 p.9-26
OUT DX,AL
POP ES
POP DS
POP DX
POP AX
IRET
作为一个tsr程序,首先要截获某个中断:
用ax=35xxh int 21h得到int xx的中断向量,保存这个中断向量
用ax=25xxh int 21h置中断向量为你的程序,在你的中断服务程序中处理后,调用原中断处理程序.
用ah=31h int 21h驻留退出
其实一个真正的tsr程序还要复杂的多,要判断本程序是否已经驻留,避免重复驻留.还要提供退出驻留的方法等,而且tsr程序要尽可能的小.
具体情况,我寄给你一个TSR的例子,慢慢研究吧.