;Program to allow a program to be interupted at any time.
;assemble with bat file makeint, for tandy 2000
;Assemble with the DeSmet assembler using the make file makeint.bat
;Written by John N. White		last mod 1/25/85
;Note that some tricks were used to get a .com file with an interupt handler
;with the DeSmet package which normally produces .exe files.
;The timer interupt is intercepted and every 20 ticks this code is entered.
;If the cs:ip that was being executed is greater than the end of this
;program (which is terminate and stay resident) then a check is made on
;the keyboard status. If both shifts and the alt key are depresed then
;the program is terminated by putting an int 21h into its code and jumping to
;it. The address that was interupted will be displayed. If cs:ip is less
;than the end of this program then every tick will be checked instead of every
;20. The normal clock tick point is entered after this program finishes.
DAT	equ	+100h			;The DeSmet stuff assumes CS:0 is the
					;start while in a .com file CS:100 is.

EXTRA	equ	0Ch			;This is the extra bytes on the stack
					;over what a simple interupt should
					;have. Tandy 2000 = 1Ah, IBM = 0Ch
					;(for dos 2.x)
	cseg
	jmp	init

check:
	sti
	push	bp
	push	ax
	push	cx
	mov	bp,sp
	mov	ax,[bp+6+EXTRA]		;1A extera stuff on stack over raw int
	mov	cl,4
	shr	ax,cl
	add	ax,[bp+8+EXTRA]
	cmp	ax,cs:addr DAT
	jbe	next_tick
	cmp	ax,0C000h
	jae	next_tick
	mov	ah,2
	int	16h
	not	al
	and	al,0Bh			;see if both shifts and alt key pressed
	jz	interupt_process
next_tick:
	pop	cx
	pop	ax
	pop	bp
tick:	db	0EAh,0,0,0,0		;will be set by init

interupt_process:
	push	bx
	push	si
;grab old cs:ip of doomed program
	mov	bx,[bp+6+EXTRA]
	push	bx
	mov	bx,[bp+8+EXTRA]
;cause return to die instead of return to doomed program
	mov	word [bp+6+EXTRA],offset die DAT
	mov	word [bp+8+EXTRA],cs
	mov	si,offset csnum DAT
	mov	cx,4
csloop:
	call	cdigit
	loop	csloop
	mov	si,offset ipnum DAT
	pop	bx
	mov	cx,4
iploop:
	call	cdigit
	loop	iploop
	mov	si,offset dstring DAT	;display dstring
dloop:
	mov	bl,0
	mov	al,cs:[si]
	inc	si
	and	al,al
	jz	done
	mov	ah,14
	int	10h			;display char
	jmp	dloop

done:
	pop	si
	pop	bx
	jmp	next_tick

die:
	mov	ax,4c01h		;terminate current process
	int	21h

;convert lowest 4 bits in bx (>>=4) to hex digit at [si--]
cdigit:
	mov	al,bl
	and	al,0Fh
	shr	bx,1
	shr	bx,1
	shr	bx,1
	shr	bx,1
	cmp	al,9
	jle	noadd
	add	al,7
noadd:	add	al,30h
	mov	cs:byte [si],al
	dec	si
	ret

addr:	dw	0FFFFh			;segment addr at end of this code
dstring:db	0Dh,0Ah,'c','s','=',0,0,0
csnum:	db	0,',',' ','i','p','=',0,0,0
ipnum:	db	0,0Dh,0Ah,0

init:
	mov	ax,351Ch		;get tick interupt vector
	int	21h
	mov	ds:word tick+1 DAT,bx
	mov	ds:word tick+3 DAT,es

	mov	ax,251Ch		;set new tick vector
	mov	dx,offset check DAT
	int	21h

	mov	ax,cs
	mov	dx,offset init+0Fh DAT
	mov	cl,4
	shr	dx,cl
	add	ax,dx
	mov	ds:addr DAT,ax
	mov	ax,3100h		;terminate and stay resident
	int	21h
	end
