; mp/m basic input/output operating system (bios)
;
;
;
true	equ	0ffffh		;define value of true.
false	equ	not true	;define value of false.
;
msize	equ	48		;memory size in kbytes.
ndisks	equ	1		;number of disk drives
vers	equ	22		;cp/m version number
bvers	equ	18		;bios version number
onedsk	equ	not((((ndisks-1)+3)and 4)shr 2)

	if onedsk
disk4	equ	false
disk3	equ	false
	endif

	if not onedsk
disk4	equ	(ndisks and 0000$0100b) shr 2
disk3	equ	ndisks and 0000$0001b
	endif

dubsid	equ	false		;true for double sided drives.
intrp	equ	false		;set true for intrrupts allowed.
COLCNT	EQU 	TRUE		;SET TRUE FOR NETRONICS TERMINAL
cpl	equ	32		;characters/line
llimit	equ	cpl		;characters/line
;
cstat	equ	0E1H		;console status port
ccom	equ	0E1H		;console command port
cdata	equ	0E0H		;console data port
lstat	equ	0E3H		;list status port.
lcom	equ	0E3H		;list command port.
ldata	equ	0E2H		;list data port.
;
 plci0 equ 3
 plco0 equ 2
 pldsk equ 1
 pllpt equ 0
 poll equ 131
;
ckbr	equ	0000$0010b	;status bit on port 0.
cptr	equ	0000$0100b	;printer ready bit.
lrbit	equ	cptr		;lister ready bit.
;
iobyte	equ	3		;address of i/o byte.
cdisk	equ	4		;current selected disk


cbase	equ	12032	;bias for larger than 20k.
cpmb	equ	cbase+3400h	;start of cp/m 2.2
bdos	equ	cpmb+806h	;start of bdos 2.2
bios	equ	cpmb+1600h	;base of bios 2.2
 
 
nmbcns equ 1
	org	000h
 pdisp equ $-3
 xdos equ pdisp-3
nsects	equ	($-cpmb)/128	;number of sectors in it.

trks	equ	77		;# of tracks/disk
spt	equ	26		;sectors/track
off	equ	2		;# of reserved system trks
;
; i/o jump vector
; this is where cp/m calls whenever it needs
; to do any input/output operation.
; user programs may use these entry points
; also, but note that the location of this
; vector changes with the memory size.
;
	jmp	coldstart	;from cold start loader.
       jmp     warmstart       ;from warm boot.
	jmp	constd	;check console kb status.
	jmp	conind	;read console char.
	jmp	conotd	;write console char.
	jmp	list	;write listing char.
	jmp	rtnempty	;write punch char.
	jmp	rtnempty	;read reader char.
	jmp	home	;move disk to zero.
	jmp	seldsk	;select disk drive.
	jmp	settrk	;seek to track in reg a.
	jmp	setsec	;set sector number.
	jmp	setdma	;set disk starting address.
	jmp	read	;read selected sector.
	jmp	write	;write selected sector.
	jmp	pollpt	;return list status.
jmp sectran
 jmp selmemory
 jmp polldevice
 jmp startclock
 jmp stopclock
 jmp exitregion
 jmp maxconsole
 jmp systeminit
 jmp idle
 coldstart:
 warmstart:
 mvi c,0
 jmp xdos
;
; data byte for number of disk drives
;
nodsks:	db	ndisks
;

;
; fixed data tables for tw0-drive standard
; ibm-compatible 8" disks
;
; disk parameter header for disk 00
dpbase:	dw	trans,0000h
	dw	0000h,0000h
	dw	dirbf,dpblk
	dw	chk00,all00

; disk parameter header for disk 01
	dw	trans,0000h
	dw	0000h,0000h
	dw	dirbf,dpblk
	dw	chk01,all01

	if disk3 or disk4
; disk parameter header for disk 02
	dw	trans,0000h
	dw	0000h,0000h
	dw	dirbf,dpblk
	dw	chk02,all02
	endif

	if disk4
; disk parameter header for disk 03
	dw	trans,0000h
	dw	0000h,0000h
	dw	dirbf,dpblk
	dw	chk03,all03
	endif

;
;
; sector translate vector
;
trans:	db	1,7,13,19		;sectors 1,2,3,4
	db	25,5,11,17		;sectors 5,6,7,8
	db	23,3,9,15		;sectors 9,10,11,12
	db	21,2,8,14		;sectors 13,14,15,16
	db	20,26,6,12		;sectors 17,18,19,20
	db	18,24,4,10		;sectors 21,22,23,24
	db	16,22			;sectors 25,26
;
dpblk:	;disk parameter block, common to all disks
	dw	spt		;sectors per track

	if not dubsid
	db	3		;block shift factor
	db	7		;block mask
	db	0		;null mask
	dw	242		;disk size-1
	dw	63		;directory max
	db	192		;alloc 0
	db	0		;alloc 1
	dw	16		;check size
	endif

	if dubsid
	db	4		;block shift factor
	db	15		;block mask
	db	0		;null mask
	dw	246		;disk size-1
	dw	127		;directory max
	db	192		;alloc 0
	db	0		;alloc 1
	dw	32		;check size
	endif

	dw	off		;track offset
;
; end of fixed tables
;
;
; signon message
;
smsg:
	db	12,10,13
	db	'Explorer-85 '
 db 10,13
db'Multi processor'
 db 10,13
db'Time-Sharing'
 db 10,13
db'Computer System'
	
	if dubsid
	endif

	db	10,13
	db	10,13
	db	10,13
	db	0
;
; boot
; this section is executed whenever reset and run
; after the coldstart loader reads in
; the cp/m system.
;

STAT51	EQU	0E1H
cntl51	equ	0E1H
rxd51	equ	0E0H
mode51	equ	0ceH
cmd51	equ	27H
boot:

	mvi	a,mode51
	out	cntl51
	OUT	CNTL51+2
	mvi	a,cmd51
	out	cntl51
	OUT	CNTL51+2
	in	rxd51
	IN	RXD51+2
boot1:

	if intrp		;if interrupts allowed,
	ei			;enable them here.
	endif

	xra	a		;clear scratch area.
	sta	cdisk
	mvi	c,endz-startz	;get length of zero area.
	lxi	h,startz	;get scratch address.
bootl:	mov	m,a		;put zero in memory.
	inx	h		;increment pointer.
	dcr	c		;decrement counter.
	jnz	bootl		;loop till done.
	mvi	m,llimit	;set line limit
	inx	h		;point to latch byte
	mvi	m,0		;set latch code = 0.
	lxi	h,smsg		;print signon message.
	call	pmsg
gocpm:	
;
; set jumps into cp/m in lower memory.
;
	lxi	h,80h		;set default dma adr.
	shld	dmaadd
	jmp	bootr		;finish systeminit.
;
  
  
  
  
  
 constd:
 call ptbljmp
 dw pt0st
 conind:
 call ptbljmp
 dw pt0in
 conotd:
 call ptbljmp
 dw pt0out
 ptbljmp:
 mov a,d
 cpi nmbcns
 jc tbljmp
 pop psw
 rtnempty:
 xra a
 ret
 tbljmp:
 add a
 pop h
 mov e,a
 mvi d,0
 dad d
 mov e,m
 inx h
 mov d,m
 xchg
 pchl
 polci0:
 pt0st:
 jmp const
 pt0in:
 mvi c,poll
 mvi e,plci0
 call xdos
 jmp conin
 pt0out:
 in cstat
 ani cptr
 jnz co0rdy
 push b
 call pt0wait
 pop b
 co0rdy:
 jmp conot
 pt0wait:
 mvi c,poll
 mvi e,plco0
 jmp xdos
 ret
 polco0:
 in cstat
 ani cptr
 rz
 mvi a,0ffh
 ret
 list:
 call ltbsy
 ora a
 jnz lptrdy
 push b
 mvi c,poll
 mvi e,pllpt
 call xdos
 pop b
 lptrdy:
 mov a,c
 out ldata
 ret
 pollpt:
 jmp ltbsy
 nmbdev equ 4
 polldevice:
 mov a,c
 cpi nmbdev
 jc devok
 mvi a,nmbdev
 devok:
 call tbljmp
 dw pollpt
 dw poldsk
 dw polco0
 dw polci0
 dw rtnempty
 selmemory:
 ret
 startclock:
 mvi a,0ffh
 sta tickn
 ret
 stopclock:
 xra a
 sta tickn
 ret
 exitregion:
 lda preemp
 ora a
 rnz
 ei
 ret
 maxconsole:
 mvi a,nmbcns
 ret
 systeminit:
 di
call boot1
 bootr:
 mvi a,0c3h
 sta 0020h
 lxi h,intlhnd
 shld 0021h
 mvi a,9fh
 out 0efh
 ei
 ret
  
  
  
  
 idle:
 ei
hlt
  
 ret
 flagset equ 133
 dsptch equ 142
 intlhnd:
 push psw
 mvi a,9fh
 out 0efh
 lda slice
 dcr a
 sta slice
 jz t16ms
 pop psw
 ei
 ret
 t16ms:
 mvi a,16
 sta slice
 pop psw
 shld svdhl
 pop h
 shld svdret
 push psw
 lxi h,0
 dad sp
 shld svdsp
 lxi sp,intstk+48
 push d
 push b
 mvi a,0ffh
 sta preemp
 lda tickn
 ora a
 jz notickn
 mvi c,flagset
 mvi e,1
 call xdos
 notickn:
 lxi h,cnt64
 dcr m
 jnz notlsec
 mvi m,57h
 mvi c,flagset
 mvi e,2
 call xdos
 notlsec:
 xra a
 sta preemp
 pop b
 pop d
 lhld svdsp
 sphl
 pop psw
 lhld svdret
 push h
 lhld svdhl
 jmp pdisp
;
;
 slice: db 16
 cnt64: db 64
 intstk: ds 48
 svdhl: dw 0
 svdsp: dw 0
 svdret: dw 0
 tickn: db 0
 preemp: db 0
; check console input status.
;
const:
	in	cstat		;get status
	ani	ckbr		;look at flag bit
stat$ret:
	mvi	a,0		;set a=0, for return
	rz
	cma			;if ready (pressed) a=ff
	ret
;
; read a character from console.
;
conin:
	call	const		;get console status
	ora	a
	jz	conin		;not ready yet
	in	cdata		;get data byte
mask:
	ani	7fh		;make most sig. bit = 0.
	ret
;
; write a character to the console device.
;
conot:
	IF COLCNT
	push	h
	call	conota		;output the char
	lxi	h,lcount	;get char. counter
	mov	a,c		;get char.
	CPI	12		;IS IT FORM FEED
	JNZ	ISITCR		;JP TO ISITCR
	PUSH B
	PUSH H
	MVI	B,2
	LXI	H,0
WAIT1:
	DCR	L
	JNZ	WAIT1
	DCR	H
	JNZ	WAIT1
	DCR 	B
	JNZ	WAIT1
	POP	H
	POP	B
ISITCR:
	cpi	13		;is it 'cr'
	jz	slimit
	cpi	10		;is it 'lf'
	jz	lfeed
	cpi	8		;is it 'bs'
	jnz	getcnt
	inr	m
lfeed:
	inr	m
getcnt:
	dcr	m
	jnz	conxit
	mvi	c,13		;echo a 'cr'
	call	conota
	mvi	c,10		;and a 'lf'
	call	conota
slimit:
	mvi	m,llimit	;reset counter
conxit:
	pop	h
	ret
	ENDIF
conota:
	in	cstat		;read console status
	ani	cptr
	jz	conota		;loop until ready
	mov	a,c		;get character
	out	cdata		;print it
	ret
;
; write a character on listing device
;
ltbsy:
	in	lstat		;read lister status
	ani	lrbit		;look at ready bit
	jmp	stat$ret


;
; read paper tape
;
reader:
	mvi	a,1ah	;cp/m eof returned for them.
;
; punch paper tape.
;
punch:
	ret		;don't service them, just return.
;
;
;
; lisk i/o for the western digital 1771
; controller chip
;
; version of 3-29-80
;
;
;
;
;
hlab	set	8	;8 for hd ld at beg of seek.
stprat	set	2	;rate 1=6ms, 2=10ms, 3=20ms.
;
disk	equ	0e8h		;disk base address.

dcom	equ	disk		;disk command port.
dstat	equ	disk		;disk status port.
track	equ	disk+1		;disk track port.
sectp	equ	disk+2		;disk sector port.
ddata	equ	disk+3		;disk data port.
wait	equ	disk+4		;disk wait port.
dcont	equ	disk+4		;disk control port.

rtcnt	equ	10		;retry count.
;
;
; select dsk number according to register c.
;
seldsk:	lxi	h,0000h		;error return code
 di
 nop
 nop
 nop
 nop
 nop
 nop
 nop
 nop
	lda	nodsks		;get no. of dsks

	if not onedsk
	dcr	a
	endif

	cmp	c
	rc			;err ret if diskno > nodsks
new$old:
	mov	a,c		;get new dsk no.
	lxi	h,diskno	;get adr of old dsk no.
	cmp	m		;new = old?
	jz	getdph		;yes, return <hl> = dph

	if onedsk
	push	a		;save disk number.
	lxi	h,mntmsg	;get adr of mount mess.
	call	pmsg		;print "mount".
	pop	a		;get dsk number.
	sta	diskno		;update old with new.
	adi	'a'		;add ascii for 'a'.
	mov	c,a		;put into c.
	call	conot		;print it.
	call	conin		;read a character
	endif

	if not onedsk
selmor:
	mov	e,m		;put old dsk no. in  d&e.
	mvi	d,0
	lxi	h,trtab		;get addr. of track table.
	push	h
	dad	d		;add dsk no. to address.
	in	track		;read 1771 track reg.
	mov	m,a		;put into table.
	mov	e,c		;new disk no. in d$e.
	pop	h		;get addr. of track table
	dad	d		;add dsk no. to addr.
	mov	a,m		;get new track no.
	out	track		;put into 1771 track reg.
	mov	a,c		;update old dsk no.
	sta	diskno
	LXI	H,SELECT$TABLE
	MVI	B,0
	DAD	B
	MOV	A,M
	sta	latch		;save new latch code.
	endif

getdph:	
	lhld	diskno
	dad	h		;*2
	dad	h		;*4
	dad	h		;*8
	dad	h		;*16
	lxi	d,dpbase
	dad	d		;<hl> = dpbase(diskno*16)
 nop
 nop
 nop
 nop
 nop
	ret			;return from seldsk.
SELECT$TABLE:
	DB	0
	DB	6
	DB	10
	DB	18


;
 poldsk:
 in dstat ;read disk status.
 rrc ;look at bit 0.
 rc  ;not done.
 mvi a,0ffh ;done and ready flag.
 ret ;return to xdos
; move dsk to track zero.
;
home:	mvi	c,0		;seek to track zero.
;
; set track no. to whatever is in register c.
; also perform move to correct track (seek).
;
settrk:

	if not dubsid		;if not double-sided dsk
	push	h		;save h&l.
	lhld	latch		;get new & old latch.
	mov	a,l		;get new latch.
	out	dcont		;select drv. now.
	sta	clatch		;remember current latch.
	cmp	h		;is it same as old?
	mvi	a,0ffh		;if not, set flag = ff
	jnz	sflag
	cma			;if new = old, flag = 0.
sflag:	sta	hlsf		;set head-load/select flag.
	pop	h		;restore h&l.
	endif

	mov	a,c		;get new track no. 

	if dubsid		;if double-sided dsk
	rrc			;shift right once
	push	psw		;save revised trk #
	push	h
	lhld	latch		;get new & old latch
	mov	a,l		;put new latch in a
	jc	side2		;if trk # odd, side #2
	ani	1eh		;clear latch bit for side 1
	jmp	setlat		;go ahead and set latch
side2:	ori	1		;set latch bit for side 2
setlat:	out	dcont		;output to the latch
	sta	clatch		;set current latch code
	xra	h		;compare old with new
	ani	1eh		;ignore side bit
	mvi	a,0ffh		;if old not = new,
	jnz	setfl		;  set flag = ff
	cma			;if old = new, flag = 0
setfl:	sta	hlsf		;set flag zero if same
	pop	h
	pop	psw
	ani	7fh		;clear msb
	mov	c,a		;set c = trk #
	endif

	sta	trk		;update old with new.
;
; move head to the track in register a.
;
seek:	push	b		;save b&c.
	mov	b,a		;save destination track.
	mvi	a,rtcnt		;get retry count.
sretry:	sta	sercnt		;store in error counter.
	in	track		;read present track no.
	mov	c,a		;save in c.
	mov	a,c		;delay.
	cmp	b		;same as new track no.?
	mov	a,b		;restore a from b.
	jnz	nothr		;jump if not there.
there:	pop	b		;restore b&c.
	ret			;return from seek.
nothr:
;
; this routine is to allow time for the drive
; tunnel erase to terminate before moving the
; head. the delay is approx. 700 micro-sec. @
; 4 mhz cpu time, and double this for 2 mhz cpu's.
;
	push	psw		;save accum and flags
	mvi	a,0d0h		;delay count = 208
busy1:	dcr	a		;decrease count.
	jnz	busy1		;loop till done
	pop	psw		;restore accum and flags.
	out	ddata		;track to data register.
busy:	in	dstat		;read dsk status.
	rrc			;look a bit 0.
	jc	busy		;wait till not busy.
	mvi	a,14h+stprat+hlab	;get step rate, do
	out	dcom		;seek with verify.
	in	wait		;wait for intrq.
	in	dstat		;read status.
	ani	91h		;look at bits.
	jz	there		;ok, if zero.
	lda	sercnt		;get err cnt.
	dcr	a		;decrement cnt.
	jnz	sretry		;retry seek.
	pop	b		;restore b&c
	lxi	h,skmsg		;print "seek".
	jmp	ermsg		;do common messages.

;
; set dsk sector no.
;
setsec:	mov	a,c		;get sector no.
	sta	sect		;put at sect # addr.
	ret			;return from setsec.
;
; set dsk dma address.
;
setdma:	mov	h,b		;move b&c to h&l.
	mov	l,c
	shld	dmaadd		;put dma addr address.
	ret			;return from setdma.
;
; translate the sector given by <bc> using the
; translate table given by <de>
;
sectran:
	xchg			;<hl> = trans
	dad	b		;<hl> = trans(sector)
	mov	l,m		;<l> = trans(sector)
	mvi	h,0		;<hl> = trans(sector)
	ret			;with value in <hl>
;
; read the sector at sect, from the present track.
; use starting address at dmaadd.
;
read:	mvi	a,rtcnt		;get retry count.
rretry:	call	rw$retry	;store in error ctr.
	adi	88h		;add code for read sect.
reade:	out	dcom		;send command to 1771.
rloop:	in	wait		;wait for drq or intrq.
	ora	a		;set flags
	jp	rddone		;done if intrq.
	in	ddata		;get byte from dsk.
	mov	m,a		;put byte into memory.
	inx	h		;increment memory pointer.
	jmp	rloop		;keep reading.
rddone:	in dstat		;read dsk status.

	if intrp		;if interrupts allowed,
	ei			;allow again here.
	endif

	ani	9dh		;look at error bits. 
	rz			;return if none.
	call	erchk		;check for seek error.
	lda	ercnt		;get error count
	dcr	a		;decrement count.
	jnz	rretry		;try to read again.
	lxi	h,rdmsg		;print "read ".
ermsg:	call	pmsg		;print origin message.
ermsg1:
	lxi	h,errmsg	;print "error."
	call	pmsg
	mvi	a,1		;set for perm err msg
	ret
;
; erchk - check for record not found error.
;
erchk:	
	ani	10h		;if record not found,
	rz			;return, no errors
; check for seek to correct track,
; and change if necessary.
chksk:	mvi	a,0c4h		;send command to 1771
	out	dcom		;to read address.
	in	wait		;wait for drq or intrq.
	in	ddata		;read the track address.
	mov	b,a		;save in reg b.
chks2:	in	wait		;wait for intrq.
	ora	a		;se| flags.
	jp	chks3		;done with read adr op.
	in	ddata		;read another byte.
	jmp	chks2		;do it again.
chks3:	in	dstat		;read dsk status.
	ora	a		;set flags.
	jz	chks4		;read adr ok if 0.
	call	home		;otherwise, home first.
	jmp	chks5
chks4:	mov	a,b		;update track reg.
	out	track
chks5:	lda	trk		;get required track no.
	jmp	seek		;move head to it.
;
; write the sector at sect, on the present track.
; use starting address at dmaadd.
;
write:	mvi	a,rtcnt		;get retry count.
wretry:	call	rw$retry	;store in error counter.
	adi	0a8h		;add code for write.
write2:	out	dcom
wloop:	in	wait		;wait for ready.
	ora	a		;set flags.
	jp	wdone		;hop when done.
	mov	a,m		;get byte from mem.
	out	ddata		;write onto dsk.
	inx	h		;increment mem ptr.
	jmp	wloop		;keep writing.
wdone:	in	dstat		;read dsk status.

	if intrp		;if interrupts allowed,
	ei			;enable again here.
	endif

	ani	0fdh		;look at these bits.
	rz			;return if no err.
	call	erchk		;check/correct seek err.
	lda	ercnt		;get error count.
	dcr	a		;decrement count.
	jnz	wretry		;try to write again.
	lxi	h,wtmsg		;print "write ".
	jmp	ermsg
;
; read / write retry subroutine
;
rw$retry:
	sta	ercnt		;store in error counter
	lhld	dmaadd		;get starting addr.
	mvi	a,0d0h		;cause interrupt.
	out	dcom
	xthl			;some delay
	xthl

	if intrp		;if interrupts allowed,
	di			;disable them here.
	endif

	lda	sect		;get sector no.
	out	sectp		;set sector into 1771.
;
; hdld - get head-load bit if required.
;
hdld:	lda	hlsf		;get head-load flag.
	ora	a		;is a = 0?
	jz	hdld1		;hop if so.
	cma			;set a = 0.
	sta	hlsf		;set flag = 0 if not.
;
; if changing to a new drive, perform a seek to
; the same track to allow the head to unload.
;
	in	track		;get present track
	out	ddata		;and tell 1771 about it.
	mvi	a,14h+stprat+hlab	;get the step rate.
	out	dcom		;send it to floppy controller.
	in	wait		;wait for intrq.
hdldy:	mvi	a,4		;set bit to load head.
	ret			;return from hdld.
hdld1:	in	dstat		;read 1771 status.
	ani	20h		;look at hl bit.
	jz	hdldy		;load if not loaded.
	xra	a		;otherwise, a = 0.
	ret			;return from hdld.
;
; print the message at h&l until a zero.
;
pmsg:	mov	a,m		;get a char.
	ora	a		;if it's zero,
	rz			;return
	mov	c,a		;otherwise,
	call	conot		;print it.
	inx	h		;increment h&l,
	jmp	pmsg		;and get another.
;
; cbios messages
;
btmsg:	db	'Boot '
errmsg:	db	'Error.',0
rdmsg:	db	0dh,0ah,'Read ',0
wtmsg:	db	0dh,0ah,'Write ',0
skmsg:	db	0dh,0ah,'Seek ',0

	if onedsk
mntmsg:	db	0dh,0ah,'Mount ',0
	endif


; bios scratch area.
;	org	$
trk:	ds	1	;current track no.
sect:	ds	1	;current sector no.
dmaadd:	ds	2	;disk transfer address
;
; the next several bytes, between startz and
; endz, are set to zero at cold boot time.
;
	org	$
startz:			;start of zeroed area.
diskno:	ds	2	;disk no. (to cp/m).
; special flags.
hlsf:	ds	1	;head-load select flag.
;
; trtab - disk track table - present position of
;   heads for up to ndisks drvs
;
trtab:	ds	ndisks

endz:			;end of zeroed area.
;
	org	$
lcount:	ds	1	;character counter
latch:	ds	1	;new code for latch
clatch:	ds	1	;current code in latch.
ercnt:	ds	1	;err/r count for retries
sercnt:	ds	1	;seek retry counter
temp:	ds	1	;temporary storage
;
; scratch ram area for bdos use
;
begdat	equ	$		;beginning of data area
dirbf:	ds	128		;scratch directory area

	if not dubsid
all00:	ds	31		;allocation vector 0
chk00:	ds	16		;check vector 0

all01:	ds	31		;allocation vector 1
chk01:	ds	16		;check vector 1
	endif

	if disk3 or disk4 and not dubsid
all02:	ds	31		;allocation vector 2
chk02:	ds	16		;check vector 2
	endif

	if disk4 and not dubsid
all03:	ds	31		;allocation vector 3
chk03:	ds	16		;check vector 3
	endif

	if dubsid
all00:	ds	32		;allocation vector 0
chk00:	ds	32		;check vector 0

all01:	ds	32		;allocation vector 1
chk01:	ds	32		;check vector 1
	endif

	if disk3 or disk4 and dubsid
all02:	ds	32		;allocation vector 2
chk02:	ds	32		;check vector 2
	endif

	if disk4 and dubsid
all03:	ds	32		;allocation vector 3
chk03:	ds	32		;check vector 3
	endif

;
enddat	equ	$		;end of data area 
 db 0
datsiz	equ	$-begdat	;size of data area
 db 0
	end
