;[]-------------------------------------------------------------------------[]
;|	Program name: 2_5_7.ASM                                              |
;|	Image   file: 2_5_7.COM                                              |
;|	Note        : This is a TSR program.                                 |
;|                    In INT 21H, it will increase and decrease count value, |
;|                      and in INT 05H, it will display this count value.    |
;[]-------------------------------------------------------------------------[]


cseg	segment
	assume	cs:cseg,ds:cseg
	org	100H
start:
	jmp	initialize

;------- Data area ---------------------

old_int05	dd	?
old_int21	dd	?
old_int60	dd	?
count		dw	0
hextab		db	'0123456789ABCDEF'

;------- Subroutine --------------------

dchar	proc	near			; display character
	mov	bh,1
	mov	ah,0EH
	int	10H
	ret
dchar	endp

dbyte	proc	near			; display byte
	push	ax
	shr	al,1
	shr	al,1
	shr	al,1
	shr	al,1
	and	ax,000FH
	mov	si,ax
	mov	al,cs:hextab[si]
	call	dchar
	pop	si
	and	si,000FH
	mov	al,cs:hextab[si]
	call	dchar
	ret
dbyte	endp

dsword	proc	near			; display short word
	push	ax
	mov	al,ah
	call	dbyte
	pop	ax
	call	dbyte
	ret
dsword	endp

dreturn	proc	near			; display return
	mov	al,0AH
	call	dchar
	mov	al,0DH
	call	dchar
	ret
dreturn	endp

;------- INT 05H -----------------------

new_int05	proc	far

	sti

	push	ax			; Save register
	push	bx
	push	si

	call	dreturn			; Display count value
	mov	ax,cs:count
	call	dsword
	call	dreturn
	call	dreturn

	pop	si			; Restore register
	pop	bx
	pop	ax

	iret

new_int05	endp

;------- INT 21H -----------------------

new_int21	proc	far

	sti

	push	ax			; Save register
	push	bx
	push	si

	call	dsword			; Display AX in DOS function call
	call	dreturn

	pop	si			; Restore register
	pop	bx
	pop	ax

	inc	cs:count		; Increase count

	cli				; Execute the old INT 21H function
	pushf
	call	cs:old_int21
	sti

	dec	cs:count		; Decrease count

	iret

new_int21	endp

;------- INT 60H -----------------------

new_int60	proc	far

	sti

	push	ax
	push	dx
	push	ds

	mov	dx,cs:word ptr old_int21	; restore INT 21H
	mov	ds,cs:word ptr old_int21[2]
	mov	ax,2521H
	int	21H

	mov	dx,cs:word ptr old_int60	; restore INT 60H
	mov	ds,cs:word ptr old_int60[2]
	mov	ax,2560H
	int	21H

	pop	ds
	pop	dx
	pop	ax

	iret

new_int60	endp

;------- Main program ------------------

initialize:

	mov	al,05H			; Get the INT 05H interrupt vector
	mov	ah,35H
	int	21H
	mov	word ptr old_int05,bx	; Save the vector in old_int05
	mov	word ptr old_int05[2],es

	mov	al,21H			; Get the INT 21H interrupt vector
	mov	ah,35H
	int	21H
	mov	word ptr old_int21,bx	; Save the vector in old_int21
	mov	word ptr old_int21[2],es

	mov	al,60H			; Get the INT 60H interrupt vector
	mov	ah,35H
	int	21H
	mov	word ptr old_int60,bx	; Save the vector in old_int60
	mov	word ptr old_int60[2],es

	mov	dx,offset new_int05	; Set the INT 05H interrupt vector
	mov	al,05H
	mov	ah,25H
	int	21H

	mov	dx,offset new_int21	; Set the INT 21H interrupt vector
	mov	al,21H
	mov	ah,25H
	int	21H

	mov	dx,offset new_int60	; Set the INT 60H interrupt vector
	mov	al,60H
	mov	ah,25H
	int	21H

	mov	dx,offset initialize	; Terminate and stay resident
	int	27H

cseg	ends
	end	start
