title	'PUT.RSX 3.0 - CP/M 3.0 Output Redirection - August 1982'
;******************************************************************
;
;	PUT  'Output Redirection Facility'  version 3.0
;
; 	11/30/82 - Doug Huskey
;	This RSX redirects console or list output to a file.
;******************************************************************
;
;
;	generation procedure
;
;	rmac putrsx
;	xref putrsx
;	link putrsx[op]
;	ERA put.RSX
;	REN put.RSX=putRSX.PRL
;	GENCOM put.com put.rsx
;
;	initialization procedure
;
;	PUTF makes a RSX function 60 call with a sub-function of
;	128.  PUTRSX returns the address of a data table containing:
;
;	init$table:
;		dw	kill		;remove PUT at warmboot flg
;		dw	0		;reserved
;		dw	bios$output	;BIOS entry point into PUT
;		dw	putfcb		;FCB address
;
;	PUTF initializes the data are between movstart: and movend:
;	and moves it into PUT.RSX.  This means that data should not
;	be reordered without also changing PUTF.ASM.
;
;		
true		equ	0ffffh
false		equ	00000h
;
bios$functions	equ	true	;intercept BIOS console functions
remove$rsx	equ	false	;this RSX does its own removal
;
;	low memory locations
;
wboot	equ	0000h
wboota	equ	wboot+1
bdos	equ	0005h
bdosl	equ	bdos+1
buf	equ	0080h
;
;	equates for non graphic characters
;
ctlc	equ	03h	; control c
ctle	equ	05h	; physical eol
ctlh	equ	08h	; backspace
ctlp	equ	10h	; prnt toggle
ctlr	equ	12h	; repeat line
ctls	equ	13h	; stop/start screen
ctlu	equ	15h	; line delete
ctlx	equ	18h	; =ctl-u
ctlz	equ	1ah	; end of file
rubout	equ	7fh	; char delete
tab	equ	09h	; tab char
cr	equ	0dh	; carriage return
lf	equ	0ah	; line feed
ctl	equ	5eh	; up arrow
;
;	BDOS function equates
;
cinf	equ	1	;read character
coutf	equ	2	;output character
crawf	equ	6	;raw console I/O
creadf	equ	10	;read buffer
cstatf	equ	11	;status
lchrf	equ	5	;print character
pbuff	equ	9	;print buffer
resetf	equ	13	;reset drive
openf	equ	15	;open file
closef	equ	16	;close file
delf	equ	19	;delete file
dreadf	equ	20	;disk read
writef	equ	21	;disk write
dmaf	equ	26	;set dma function
userf	equ	32	;set/PUT user number
resdvf	equ	37	;reset drive function
flushf	equ	48	;flush buffers function
scbf	equ	49	;set/PUT system control block word
loadf	equ	59	;Program load function
rsxf	equ	60	;RSX function call
resalvf	equ	98	;reset allocation vector
pblkf	equ	111	;print block to console
lblkf	equ	112	;print block to list device
ginitf	equ	128	;GET initialization sub-function no.
gkillf	equ	129	;GET delete sub-function no.
gfcbf	equ	130	;GET file display sub-function no.
pinitf	equ	132	;PUT initialization sub-function no.
pckillf	equ	133	;PUT console delete sub-function no.
plkillf	equ	137	;PUT list delete sub-function no.
pcfcbf	equ	134	;return PUT console fcb address
plfcbf	equ	138	;return PUT list fcb address
jinitf	equ	140	;JOURNAL initialization sub-function no.
jkillf	equ	141	;JOURNAL delete sub-function no.
jfcbf	equ	142	;return JOURNAL fcb address
;
;	System Control Block definitions
;
scba	equ	03ah	;offset of scbadr from SCB base
ccpflg	equ	0b3h	;offset of ccpflags word from page boundary
ccpres	equ	020h	;ccp resident flag = bit 5
bdosoff equ	0feh	;offset of BDOS address from page boundary
errflg	equ	0aah	;offset of error flag from page boundary
conmode	equ	0cfh	;offset of console mode word from pag. bound.
outdel	equ	0d3h	;offset of print buffer delimiter
listcp	equ	0d4h	;offset of ^P flag from page boundary
usrcode	equ	0e0h	;offset of user number from pg bnd.
dcnt	equ	0e1h	;offset of dcnt, searcha & searchl from pg bnd.
constfx	equ	06eh	;offset of constat JMP from page boundary
coninfx	equ	074h	;offset of conin JMP from page boundary
;
;
;******************************************************************
;		RSX HEADER 
;******************************************************************

serial:	db	0,0,0,0,0,0

trapjmp:
	jmp	trap		;trap read buff and DMA functions
next:	jmp	0		;go to BDOS
prev:	dw	bdos
kill:	db	0FFh		;Remove at wstart if not zero
nbank:	db	0
rname:	db	'PUT     '	;RSX name
space:	dw	0
patch:	db	0

;******************************************************************
;		START OF CODE
;******************************************************************
;
;	ABORT ROUTINE
;
puteof:				;close output file and abort
	lda	cbufp
	ora	a
	jz	restor
	mvi	e,ctlz
	call	putc
	jmp	puteof


;
;******************************************************************
;		BIOS TRAP ENTRY POINT
;******************************************************************
;
;
;	ARRIVE HERE ON EACH INTERCEPTED BIOS CALL
;
;
bios$output:
	;
if bios$functions
	;
	;enter here from BIOS constat
	mov	e,c		;character in E
	lda	bdosfunc	;BDOS function to use
	mov	c,a
	mvi	a,1		;offset in exit table = 1
	jmp	bios$trap
endif
;
;
;******************************************************************
;		BDOS TRAP ENTRY POINT 
;******************************************************************
;
;
;	ARRIVE HERE AT EACH BDOS CALL
;
trap:
	;
if bios$functions
	;
	xra 	a
biostrap:
	;enter here on BIOS calls
	sta	exit$off
endif
	pop	h		;return address
	push	h		;back to stack
	lda	trapjmp+2	;PUT.RSX page address
	cmp	h		;high byte of return address
	jc	exit		;skip calls on bdos above here
	mov	a,c
	cpi	rsxf
	jz	rsxfunc		;check for initialize or abort
	cpi	dmaf
	jz	dmafunc		;save users DMA address
	cpi	14		;reset function + 1
	jc	tbl$srch	;search if func < 14
	cpi	98
	jnc	tbl$srch	;search if func >= 98
	cpi	resdvf
	jz	tbl$srch	;search if func = 37
	;
	;	EXIT - FUNCTION NOT MATCHED
	;
exit:

if not bios$functions
	;
exit1:	jmp	next		;go to next RSX or BDOS

else
	lda	exit$off	;PUT type of call:
exit1:	lxi	h,exit$table	;0=BDOS call, 1=BIOS call
endif

tbl$jmp:

	;  a = offset (rel 0) 
	; hl = table address
	add	a		;double for 2 byte addresses
	call	addhla		;HL = .(exit routine)
	mov	b,m		;get low byte from table
	inx	h
	mov	h,m
	mov	l,b		;HL = exit routine
	pchl			;gone to BDOS or BIOS

tbl$srch:

	;
	;CHECK IF THIS FUNCTION IS IN FUNCTION TABLE
	;if matched b = offset in table (rel 0)
	;FF terminates table
	;FE is used to mark non-intercepted functions
	;
	lxi	h,func$tbl	;list of intercepted functions
	mvi	b,0		;start at beginning
tbl$srch1:
	mov	a,m		;get next table entry
	cmp	c		;is it the same?
	jz	intercept	;we found a match, B = offset
	inr	b
	inx	h
	inr	a		;0FFh terminates list 
	jnz	tbl$srch1	;try next one
	jmp	exit		;end of table - not found

;
;
;******************************************************************
;		REDIRECTION PROCESSOR
;******************************************************************
;
;
;	INTERCEPTED BDOS FUNCTIONS ARRIVE HERE 
;
;	enter with 
;			 B = routine offset in table
;			 C = function number
;			DE = BDOS parameters

intercept:

	;switch to local stack
	lxi	h,0
	dad	sp
	shld	oldstack
	lxi	sp,stack

redirect:

	push	d		;save info
	push	b		;save function
	lhld	scbadr
	;
	;are we active now?
	;
	lda	program
	ora	a		;program output only?
	cnz	ckccp		;if not, test if CCP is calling
	jz	cklist		;jump if not CCP or program output
	mov	a,c
	cpi	0ah		;is it function 10?
	jnz	skip		;skip if not
	lxi	h,ccpcnt	;decrement once for each
	dcr	m		;CCP function 10
	cm	puteof		;if 2nd appearance of CCP
	jmp	skip		;if CCP is active
	;
	;check for list processing and ^P status
	;
cklist:
	lda	list
	ora	a		;list redirection?
	jz	ckecho		;jump if not
	mvi	l,listcp	;HL = .^P flag
	mov	a,m
	ora	a		; ^P on?
	jnz	setecho		;set echo on if so
	mov	a,b
	cpi	2		;console function?
	jnc	skip		;skip if so
ckecho:	lda	echoflg		;echo parameter
setecho:
	sta	echo
	;
	;go to function trap routine
	;
gofunct:
	lxi	h,retmon	;program return routine
	push	h		;push on stack 
	mov	a,b		;offset
	lxi	h,trap$tbl
	jmp	tbl$jmp		;go to table address
;
;
rawio:
	;direct console i/o - read if 0ffh
	;returns to retmon
	mov 	a,e	
	cpi	0fdh
	jc	putchr
	cpi	0feh
	rz			;make the status call  (FE)
	jc	conin		;make the input call   (FD)
	call	next		;call for input/status (FF)
	ora	a
	jz	retmon1
	jmp	conin1
	;
	;input function
	;
conin:
	call	exit		;make the call
conin1:	mov	e,a		;put character in E
	push	psw		;save character
	call	conout		;put character into file
	pop	psw		;character in A
	;
	;	RETURN FROM FUNCTION TRAP ROUTINE
	;
	cpi	cr
	jnz	retmon1

retmon2:
	;output linefeed before returning
	push	psw		;save character
	lda	echo
	ora	a		;no echo mode
	mvi	e,lf
	mvi	c,coutf
	cz	next		;output lf if so
	lda	input
	ora	a
	cnz	conout
	pop	psw		;restore character

retmon1:
	;return to calling program
	lhld	old$stack
	sphl
	mov	l,a
retmon0:
	ret			;to calling program
	;
retmon:
	;echo before returning?
	lda	echo
	ora	a
	jz	retmon1		;return to program if no echo
	;otherwise continue 
	;
	;	PERFORM INTERCEPTED BDOS CALL
	;
skip:
	;restore BDOS call and stack
	pop	b		;restore BDOS function no.
	pop	d		;restore BDOS parameter
	lhld	old$stack
	sphl
	jmp	exit		;goto BDOS

;******************************************************************
;		BIOS FUNCTIONS (REDIRECTION ROUTINES)
;******************************************************************
;
putchr:
	;put out character in E unless putting input
	lda input! ora a! rnz  	;return (retmon) if input redirection
listf:
conout:
conoutf:	
ctlout:
	;send E character with possible preceding up-arrow
	mov a,e! cpi ctlz! jz ctlout1 	;always convert ^Z
	call echoc 	;cy if not graphic (or special case)
	jnc putc 	;skip if graphic, tab, cr, lf, or ctlh

	ctlout1:
		;send preceding up arrow
		push psw! mvi e,ctl! call putc ;up arrow
		pop psw! ori 40h ;becomes graphic letter
		mov e,a ;ready to print
		;(drop through to PUTC)
;
;
;	put next character into file
;
;
putc:	;write sector if full, close in each physical block
	;abort PUT if any disk error occurs
	;character in E
	lxi	h,cbufp
	mov	a,m		; A = cbufp
	push 	h
	inx	h		;HL = .cbuf
	call	addhla		;HL = .char
	mov	m,e		;store character
	pop	h
	inr	m		;next chr position
	rp			;minus flag set after 128 chars
;
;	WRITE NEXT RECORD
;
write:
	mvi	c,writef
	call	putdos
	cnz	restor		;abort RSX if error
	xra	a
	sta	cbufp		;reset buffer position to 0
	lxi	h,record
	dcr	m		;did we cross the block boundary?
	rp			;return if not
	call	close		;close the file if so
	cnz	restor		;abort RSX if error
	lxi	h,blm		;HL = .blm
	mov	a,m		
	dcx	h
	mov	m,a		;set record = blm
	ret
;
;	CLOSE THE FILE
;
close:
	mvi 	c,closef
;
;	PUT FILE OPERATION
;
putdos:	
	push	b		;function no. in C
	lxi	d,cbuf
	call	setdma		;set DMA to our buffer
	pop	b		;function no. in C
	lhld	scbadr
	push	h		;save for restore
	lxi	d,sav$area	;10 byte save area
	push	d		;save for restore
	call	mov7		;save hash info in save area
	mvi	l,usrcode	;HL = .BDOS user number in SCB
	call	mov7		;save user, dcnt, search addr, len &
	dcx	h		; multi-sector count
	mvi	m,1		;set multi-sector count=1
	mvi	l,usrcode	;HL = .BDOS user number
	lxi	d,putusr
	ldax	d
	mov	m,a		;set BDOS user = putusr
	inx	d		;DE = .putfcb
	call	next		;write next record or close file
	pop	h		;HL = .sav$area
	pop	d		;DE = .scb
	push	psw		;save A (non-zero if error)
	call	mov7		;restore hash info
	mvi	e,usrcode	;DE = .user num in scb
	call	mov7		;restore dcnt search addr & len
	lhld	udma
	xchg
	call	setdma		;restore DMA to program's buffer
	pop	psw
	ora	a
	ret			;zero flag set if successful
;
;	CLOSE FILE AND TERMINATE RSX
;
restor:
	call	close
	lxi	d,close$err
	cnz	msg		;print message if close error
	lxi	h,0ffffh
	shld	rsxfunctions	;set killf and fcbf to inactive
	;
	;set RSX aborted flag
	;
	lxi	h,kill		;0=active, 0ffh=aborted
	mvi	m,0ffh		;set to 0ffh (in-active)
	;are we the bottom RSX, if so remove ourselves immediately
	;to save memory
	lda	bdosl+1		;get high byte of top of tpa
	CMP	H		;Does location 6 point to us

if remove$rsx
	jnz	bios$fixup	;done, if not
	lhld	next+1
	shld	bdosl
	xchg
	lhld	scbadr
	mvi	l,bdosoff	;HL = "BDOS" address in SCB
	mov	m,e		;put next address into SCB
	inx	h
	mov	m,d
	xchg
	mvi	l,0ch		;HL = .previous RSX field in next RSX
	mvi	m,7
	inx	h
	mvi	m,0		;put previous into previous
else
	mvi	c,loadf
	lxi	d,0
	cz	next		;fixup RSX chain, if this RSX on bottom
endif

if bios$functions

bios$fixup:
	;
	;restore bios jumps
	lda	restore$mode		;may be FF, 7f or 0
	inr	a	
	rz				; FF = no bios interception
	lhld	wmsta			;real warm start routine
	xchg
	lhld	wmjmp			;wboot jump in bios
	mov	m,e
	inx	h
	mov	m,d			;restore real routine in jump
	lhld	biosout			;conin,conout or list jmp
	xchg
	lhld	biosjmp			;address of real bios routine
	mov	m,e
	inx	h
	mov	m,d
	rm				; 7f = RESBDOS jmps not changed
	lhld	wmfix
	mvi	m,jmp			;replace jmp for warm start
	lhld	biosfix
	mvi	m,jmp			;replace jmp for other trapped jump
endif
	ret				; 0  = everything done
;
;	set DMA address in DE
;
setdma:	mvi	c,dmaf
	jmp	next
;
;	print message to console
;
msg:	mvi	c,pbuff
	jmp	next
;
;	move routine
;
mov7:	mvi	b,7
	;			HL = source
	;			DE = destination
	;	 		B = count
move:	mov	a,m
	stax	d
	inx	h
	inx	d
	dcr	b
	jnz	move
	ret
;
;	add a to hl
;
addhla:	add	l
	mov	l,a
	rnc
	inr	h
	ret

;
;	check if CCP is calling
;
ckccp:
	;returns zero flag set if not CCP
	lhld	scbadr
	mvi	l,ccpflg+1	;HL = .ccp flag 2
	mov	a,m
	ani	ccpres		;is it the CCP?
	ret
;
;******************************************************************
;		BDOS FUNCTION HANDLERS
;******************************************************************
;
;
;	FUNCTION 26 - SET DMA ADDRESS
;
dmafunc:
	xchg			;dma to hl
	shld	udma		;save it
	xchg
	jmp	next
;
;
;	BIOS WARM START TRAP FUNCTION
;
warmtrap:
	lxi	sp,stack
	call	close		;close if wboot originated below RSX
	jmp	wstart
;
;	BDOS FUNCTION 60 - RSX FUNCTION CALL	
;
rsxfunc:			;check for initialize or delete RSX functions
	ldax	d		;get sub-function number
	cpi	pinitf		;is it a PUT initialization
	lxi	h,init$table
	rz			;return to caller if init call
	;check for FCB display functions
	mov	b,a
	lda	fcbf		;is it a a PUT fcb request
	cmp	b
	lxi	h,putfcb
	rz			;return if so
	;check for kill function
	lda	killf		;local kill (kill only this one)
	cmp	b
	jz	puteof		;kill and return to caller
	jmp	exit		;abort any higher PUTs

;
;
;******************************************************************
;		BDOS OUTPUT ROUTINES
;******************************************************************
;
;
;       July 1982
;
;
;	Console handlers
;
echoc:
	;are we in cooked or raw mode?
	lda cooked! ora a! mov a,e! rz ;return if raw
	;echo character if graphic
	;cr, lf, tab, or backspace
	cpi cr! rz ;carriage return?
	cpi lf! rz ;line feed?
	cpi tab! rz ;tab?
	cpi ctlh! rz ;backspace?
	cpi ' '! ret ;carry set if not graphic
;
;
print:
	;print message until M(DE) = '$'
	lhld scbadr
	mvi l,OUTDEL
	ldax d! CMP M! rz ;stop on delimiter
		;more to print
		inx d! push d! mov e,a ;char to E
		call conout ;another character printed
		pop d! jmp print
;
;
read:	
	;put prompt if in no echo mode
	lda echo! ora a! jnz read1
	push d			
	lxi d,prompt! call msg		;output prompt
	pop d! mvi c,creadf		;set for read call
read1:
	;read console buffer
	pop h				;throw away return address
        push d
	call next			;make the call
	pop h! inx h! mov b,m! inr b	;get the buffer length
putnxt:		dcr b! jz read2
		inx h! mov e,m! push b! push h
		call conout! pop h! pop b	;put character
		jmp putnxt

read2:	lda input! ora a! push psw
	mvi e,cr! cnz conout			;call if putting input
	pop psw! mvi e,lf! cnz conout		;call if putting input
	jmp retmon1


;
func1:	equ	conin
;
func2:	equ	conout
	;write console character 
;
func5:	equ	listf
	;write list character
	;write to list device
;
func6:	equ	rawio
;
func9:	equ	print
 	;write line until $ encountered
;
func10:	equ	read
;
func11:	equ	retmon0
;
func13:	equ	close
;
func37:	equ	close
;
func98:	equ	close
;
FUNC111:			;PRINT BLOCK TO CONSOLE
FUNC112:			;LIST BLOCK
	XCHG! MOV E,M! INX H! MOV D,M! INX H
	MOV C,M! INX H! MOV B,M! XCHG
	;HL = ADDR OF STRING
	;BC = LENGTH OF STRING
BLK$OUT:
	MOV A,B! ORA C! RZ	;is length 0, return if so
	PUSH B! PUSH H
	mov e,m! call conout	;put character
	POP H! INX H! POP B! DCX B
	JMP BLK$OUT

;	end of BDOS Console module

;******************************************************************
;		DATA AREA
;******************************************************************

exit$off	db	0	;offset in exit$table of destination

trap$tbl:
	;function dispatch table (must match func$tbl below)
;	db	lchrf, lblkf, coutf, cstatf, crawf
;	db	pbuff, cinf, creadf, resetf, resdvf
;	db	resalvf, pblkf, eot

	dw	func5		;function 5   - list output
	dw	func112		;function 112 - list block
	dw	func2		;function 2   - console output
	dw	func11		;function 11  - console status
	dw	func6		;function 6   - raw console I/O
	dw	func9		;function 9   - print string
	dw	func1		;function 1   - console input
	dw	func10		;function 10  - read console buffer
	dw	func13		;function 13  - disk reset (close first)
	dw	func37		;function 37  - drive reset (close first)
	dw	func98		;function 98  - reset allocation vector
	dw	func111		;function 111 - print block

;******************************************************************
;	Following variables and entry points are used by PUT.COM
;	Their order and contents must not be changed without also
;	changing PUT.COM.
;******************************************************************

movstart:
init$table:			;addresses used by PUT.COM for initial.
scbadr:				;address of System Control Block
	dw	kill		;kill flag for error on file make
				;(passed to PUT.COM by RSX init function)
	;
	if bios$functions	;PUT.RSX initialization
	;
gobios:	mov	c,e
	db	jmp
biosout	dw	bios$output	;set to real BIOS routine
				;(passed to PUT.COM by RSXFUNC)
biosjmp
	dw	warm$trap	;address of bios jmp initialized by COM
biosfix
	dw	0		;address of jmp in resbdos to restore
				;restore only if changed when removed.
wstart:	db	jmp
wmsta:	dw	0		;address of real warm start routine
wmjmp:	dw	0		;address of jmp in bios to restore
wmfix:	dw	0		;address of jmp in resbdos to restore
bdosfunc:
	db	coutf
restore$mode
	db	0		;0FFh = no bios restore, 07fh = restore
				;only bios jmp, 0 = restore bios jump and
				;resbdos jmp when removed.
	endif
;
;	equates function table
;
eot	equ	0ffh	; end of function table
skipf	equ	0feh	; skip this function
;
;
func$tbl:		;no trapping until initialized by PUT.COM
	db	eot,0,0,0,0,0,0,0,0,0,0,0,0
;	db	lchrf, lblkf, coutf, cstatf, crawf
;	db	pbuff, cinf, creadf, resetf, resdvf
;	db	resalvf, pblkf, eot
	;
input	db	0		;put console input to a file
list	db	0		;intercept list functions
echoflg:
	db	1		;echo output to device
cooked:				;must be next after echo
	db	0		;TRUE if ctrl chars (except ^Z) placed 
				;in the output file
rsxfunctions:
killf:	db	0ffh		;not used until PUT initialized
fcbf:	db	0ffh		;not used until PUT initialized
record:	db	0		;counts down records to block boundary
blm:	db	0		;block mask = records per block (rel 0)
program:			;this flag must be @ .PUTFCB-2
	db	0		;true if put program output only
putusr:	db	0		;user number for redirection file
putfcb:	db	0ffh		;preset to 0ffh to indicate not active
	db	'SYSOUT  '
	db	'$$$'
	db	0,0
putmod:	db	0
putrc:	ds	1
	ds	16		;map
putcr:	ds	1
	;
cbufp	db	0		;current character position in cbuf
movend:
;*******************************************************************

cbuf:				;128 byte buffer (could be ds 128)

	db	3,3,3,3, 3,3,3,3, 3,3,3,3, 3,3,3,3
	db	3,3,3,3, 3,3,3,3, 3,3,3,3, 3,3,3,3
	db	3,3,3,3, 3,3,3,3, 3,3,3,3, 3,3,3,3
	db	3,3,3,3, 3,3,3,3, 3,3,3,3, 3,3,3,3

	db	3,3,3,3, 3,3,3,3, 3,3,3,3, 3,3,3,3
	db	3,3,3,3, 3,3,3,3, 3,3,3,3, 3,3,3,3
	db	3,3,3,3, 3,3,3,3, 3,3,3,3, 3,3,3,3
	db	3,3,3,3, 3,3,3,3, 3,3,3,3, 3,3,3,3

	;
	if bios$functions
	;
exit$table:			;addresses to go to on exit
	dw	next		;BDOS
	dw	gobios
	endif
	;
udma:	dw	buf		;user dma
user:	db	0		;user user number
echo:	db	0		;echo output to console flag
ccpcnt:	db	1		;start at 1 (decremented each CCP)
sav$area:			;14 byte save area
	db	68h,68h,68h,68h,68h, 68h,68h,68h,68h,68h
	db	68h,68h,68h,68h
close$err:	
	db	cr,lf,'PUT ERROR: FILE ERASED',cr,lf,'$'
prompt:	db	cr,lf,'PUT>$'
	;
patch$area:
	ds	30h

	maclib	makedate	;[JCE] move all dates to one file
	db	' '
	@BDATE
	db	' '
	@SCOPY

	db	67h,67h,67h,67h, 67h,67h,67h,67h, 67h,67h,67h,67h
	db	67h,67h,67h,67h, 67h,67h,67h,67h, 67h,67h,67h,67h
	db	67h,67h,67h,67h, 67h,67h,67h,67h
	;
stack:				;16 level stack
oldstack:
	dw	0
	end
