DataMuseum.dk

Presents historical artifacts from the history of:

RegneCentralen RC759 "Piccoline"

This is an automatic "excavation" of a thematic subset of
artifacts from Datamuseum.dk's BitArchive.

See our Wiki for more about RegneCentralen RC759 "Piccoline"

Excavated with: AutoArchaeologist - Free & Open Source Software.


top - download

⟦890eeaec4⟧ TextFile

    Length: 39936 (0x9c00)
    Types: TextFile
    Names: »STARTUP.A86«

Derivation

└─⟦fa5b86546⟧ Bits:30002725 SW1609 Digital Research C - CCP/M - Oct 83
    └─ ⟦this⟧ »STARTUP.A86« 

TextFile

; This startup file is actually several files edited together:
; clear.a86, startup.a86, minitsta.a86, minitcmd.a86, minitrel.a86,
; minithea.a86, miniterr.a86.  The include statements and public/extrn
; statements that connect the separate files have been commented out.
;
; The first file, clear.a86, provides the definitions that make model
; independent coding possible.
;
C32	equ	0	; Small code model (use 1 for big model)
D32	equ	0	; Small data model (use 1 for big model)
	nolist
;
;	Stack Frame Offsets
;
     if	C32	;--------------------------------------------------------------
     if	D32	;------------------------------------------------------------ ;
ARG1	equ	8	; Offset from ÆBPÅ of caller argument #1	    ; ;
RAseg	equ	6	; Offset from ÆBPÅ of caller return address segment ; ;
RAoff	equ	4	; Offset from ÆBPÅ of caller return address offset  ; ;
SAVEDS	equ	2	; Offset from ÆBPÅ of caller DS slot		    ; ;
   else		;-----------------------------------------------------------; ;
ARG1	equ	6	; Offset from ÆBPÅ of caller argument #1	    ; ;
RAseg	equ	4	; Offset from ÆBPÅ of caller return address segment ; ;
RAoff	equ	2	; Offset from ÆBPÅ of caller return address offset  ; ;
   endif	;------------------------------------------------------------ ;
     else	; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
     if	D32	;------------------------------------------------------------ ;
ARG1	equ	6	; Offset from ÆBPÅ of caller argument #1	    ; ;
RAoff	equ	4	; Offset from ÆBPÅ of caller return address offset  ; ;
SAVEDS	equ	2	; Offset from ÆBPÅ of caller DS slot		    ; ;
     else	; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; ;
ARG1	equ	4	; Offset from ÆBPÅ of caller argument #1	    ; ;
RAoff	equ	2	; Offset from ÆBPÅ of caller return address offset  ; ;
     endif	;-----------------------------------------------------------; ;
     endif	;--------------------------------------------------------------
SAVEBP	equ	0	; Offset from ÆBPÅ of caller BP slot
SAVESP	equ	-2	; Offset from ÆBPÅ of my own SP slot
OVRAseg	equ	-4	; Offset from ÆBPÅ of my own true return address segment
OVRAoff	equ	-6	; Offset from ÆBPÅ of my own true return address offset
OVIDoff	equ	-8	; Offset from ÆBPÅ of my own overlay index
TEMP8	equ	-16	; Offset from ÆBPÅ of my 8 byte temporary
DISPLAY equ	-18	; Offset from ÆBPÅ of my lexical father frame
ONLINK	equ	-20	; Offset from ÆBPÅ of the previous on-frame
ONHEAD	equ	-22	; Offset from ÆBPÅ of the first on-unit for this frame
	eject
;
; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
; *									      *
; *       		m o v e b y t e s   /   p a d b y t e s		      *
; *									      *
; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
;
codemacro	MOVEBYTES
	db	0d1h			;	shr	cx,1
	db	0e9h
	db	073h			;	jnc	even
	db	001h
	db	0a4h			;	movsb
	db	0f3h			; even: rep	movsw
	db	0a5h
	endm
;
codemacro	PADBYTES
	db	0d1h			;	shr	cx,1
	db	0e9h
	db	073h			;	jnc	even
	db	001h
	db	0aah			;	stosb
	db	0f3h			; even:	rep	stosw
	db	0abh
	endm
;
; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
; *									      *
; *                    p o p r e g s   /   p u s h r e g s		      *
; *									      *
; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
;
codemacro	POPREGS
	db	007h			;	pop	es
	db	05fh			;	pop	di
	db	05eh			;	pop	si
	db	05ah			;	pop	dx
	db	059h			;	pop	cx
	db	05bh			;	pop	bx
	db	058h			;	pop	ax
	db	05dh			;	pop	bp
	db	01fh			;	pop	ds
	endm
;
codemacro	PUSHREGS
	db	01eh			;	push	ds
	db	055h			;	push	bp
	db	08bh			;	mov	bp,sp
	db	0ech
	db	050h			;	push	ax
	db	053h			;	push	bx
	db	051h			;	push	cx
	db	052h			;	push	dx
	db	056h			;	push	si
	db	057h			;	push	di
	db	006h			;	push	es
	endm
	eject
;
; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
; *									      *
; *                   p o p c   /   p u s h c   /   r e t c		      *
; *									      *
; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
;
     if	C32	;--------------------------------------------------------------
;
CALLC	equ	CALLF
JMPC	equ	JMPF
POPC	equ	POP
PUSHC	equ	PUSH
RETC	equ	RETF
;
     else
;
CALLC	equ	CALL
JMPC	equ	JMP
codemacro	POPC	dst:Ew
	endm
codemacro	POPC	dst:S(ES)
	endm
codemacro	POPC	dst:S(SS,DS)
	endm
codemacro	POPC	dst:Rw
	endm
codemacro	PUSHC	src:Ew
	endm
codemacro	PUSHC	src:S
	endm
codemacro	PUSHC	src:Rw
	endm
RETC	equ	RET
;
     endif	;--------------------------------------------------------------
;
; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
; *									      *
; *                 l d x  /  l e x  /  p o p d  /  p u s h d		      *
; *									      *
; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
;
     if	D32	;--------------------------------------------------------------
;
LDX	equ	LDS
LEX	equ	LES
POPD	equ	POP
PUSHD	equ	PUSH
;
     else
;
LDX	equ	MOV
LEX	equ	MOV
codemacro	POPD	dst:Ew
	endm
codemacro	POPD	dst:S(ES)
	endm
codemacro	POPD	dst:S(SS,DS)
	endm
codemacro	POPD	dst:Rw
	endm
codemacro	PUSHD	src:Ew
	endm
codemacro	PUSHD	src:S
	endm
codemacro	PUSHD	src:Rw
	endm
;
     endif	;--------------------------------------------------------------
	list
	Name			'STARTUP'
	Title			'STARTUP'
	Pagesize		75
;
;	File name:		STARTUP.A86
;
;	Module name:		STARTUP
;
;	Entry parameters:	None.
;
;	Return value:		None.
;
;	Entry point		Arguments	Function
;	-----------		---------	--------
;	m.init			None.		Initialize the Common Language
;						Environment and Runtime (CLEAR).
;
;	Algorithm:		Initialize the stack.
;				Initialize the command name.
;				Relocate the segment references if O/S has not.
;				Initialize the heap.
;				Address the command tail and call _main.
;
;	Source language:	DRI RASM-86
;
;	Target environment:	Intel iAPX-86 processor.
;
;	Authors:		Mike Lehman
;				Herbert Yuen
;				Bill Haygood
;				Craig Franklin
;
;	Date:			83-Apr-25 Monday
;
;	Revision history:
;
;	When		Who		Why and what
;	----		---		------------
;	83-Jul-20	Haygood		Small model conditional assembly code.
;	83-Oct-09	Craig Franklin	Fix bug in medium model.
;	83-Oct-11	Haygood		Use stack. sseg for new LINK86 V1.2.
;	83-Oct-15	Craig Franklin	Use CLI/STI instead of slower PUSHF/POPF.
;	83-Oct-25	Craig Franklin	Initialize zero divide handler.
	eject
; Notes to the user.
;
; Only the most sophisticated user, with a thorough knowledge of the 8086,
; CP/M, RASM86, LINK86, the .CMD file format, and the C calling conventions,
; should attempt to write a startup routine.  These notes will explain how
; this one was written, and why certain things are done in certain ways.
;
; First of all, DRI has a new policy for assembly language routines:  public
; names in them should not conflict with user public names, whether from a
; high level language or assembly language.  This is accomplished by having
; a special in-house version of RASM86 which permits '.' (period) in an
; identifier as any but the first character.  This startup routine uses that
; convention.  When CLEAR, the Common Language Environment And Runtime is
; extended to all DRI languages, all internal (compiler referenced) runtime
; routines will contain a period, to avoid any conflict with a user name.
;
; This being the case, if you try to assemble this startup routine, you will
; get assembly errors.  So you must alter your RASM86 by patching it.  This
; is our way to insure that you really are a sophisticated user who knows what
; you are doing, otherwise you would not go to all this trouble.  Using SID86,
; read in RASM86.CMD.  The, using the SR (search) command, search for "$_?@".
; The byte before these four characters should be a hex 04, and the byte after
; should be a hex 00.  Change the hex 04 to a hex 05.  Change the hex 00 to a
; hex 2E (ASCII period).  Now write RASM86.CMD back out to the disk.  Period is
; now valid for the second and subsequent characters of an identifier.
;
; Now you can assemble this routine, or modify it.
;
; Note that the cseg is named 'cinit.' in lower case with a period in it.
; LINK86 puts this particular cseg FIRST in the .CMD file.  This means that
; if the compiler does not emit a MOD END (module end) record with a starting
; address, and if no assembly routine contains END START, where START is a
; label, then LINK86 will NOT put five bytes of JMPF (or JMP/NOP/NOP) in the
; file to jump to the START address, and control will come to the initializer.
; LINK86 also puts the dseg 'dinit.' first in the data area of the .CMD file.
; You must use the RASM86 $nc option to assemble;  otherwise the names will be
; CINIT. and DINIT., which LINK86 does not treat as special.
;
; This startup routine has been made modular for easy modification.
; There are basically six calls:  initialize the stack, initialize the
; .CMD drive, perform the segment relocation (dummy routine in small model),
; initialize the heap, initialize the zerodivide handler, and call _main which
; parses the command line passed to it, opens the standard files (performing
; I/O redirection), and calls main.
;
; This one startup routine is the common source for all memory models.  For
; example, 'retc' assembles to 'ret' in small model and to 'retf' in large model.
	eject
;	include	CLEAR			; Include CLEAR definitions.
;
     if C32 eq 0;--------------------------------------------------------------
CGROUP	GROUP	cinit.							      ;
     endif	;--------------------------------------------------------------
;
cinit.   cseg
;
;	extrn	m.init.stack:near
;	extrn	m.init.cmd:near
;	extrn	m.init.reloc:near
;	extrn	m.init.heap:near
;	extrn	m.init.hardware.error:near
	extrn	_main:far
	extrn	main:far
;
	public  m.init
	public	_exit
	public	m.init.error
	public	m.error
	public	m.init.run	; Dummy entry point
	public	_v_reloc_8087	; Dummy entry point
;
m.init: call	m.init.stack	; Initialize the stack.
	call	m.init.cmd	; Find .CMD drive for overlay manager.
	call	m.init.reloc	; Eliminate the R command
	call	m.init.heap	; Initialize the heap.
	call	m.init.hardware.error	; Initialize the zero divide handler.
				; Note: must do them in the above order.
				; heap must follow reloc, some versions of
				; reloc must follow os, and stack must be first.
				; Calls are short, because segment relocation
				; may not be done until m.init.reloc finishes.
				; Calls can be short because all four call
				; targets use cinit. cseg in them.
				;
        mov     si,80h          ; Offset of command line
        lodsb			; AL = length of command line.
        xor     ah,ah
        push    ax
	pushd	ds		; Push DS if D32 (large data model)
        push    si
if D32
	mov	ss:.0,ds	; Needed for large model and overlay manager.
endif
        callc   _main
	jmps	_exit		; Return to CP/M.
;
	jmpc	main		; For debugging.
;
m.init.error:			; Near call followed by fatal error message.
	pop	dx
	push	cs
	push	dx
;
m.error:			; Far call followed by fatal error message.
	pop	dx		; DS:DX -> error message text.
	pop	ds
	mov	cl,9		; BDOS function 9 will print a message.
	int	224		; Call BDOS to print the error message.
;
_exit:	xor	cx,cx
	int	224		; Make sure to exit to O/S.
;
m.init.run:			; Dummy entry point.  Remove to use old LINK86.
	ret
;
_v_reloc_8087:			; Dummy entry point until Fortran 77.
	retc
;
;	end
;	Name			'MINITSTACK'
	Title			'M.INIT.STACK'
	Pagesize		75
;
;	File name:		MINITSTA.A86
;
;	Module name:		M.INIT.STACK
;
;	Entry parameters:	None.
;
;	Return value:		None.
;
;	Entry point		Arguments	Function
;	-----------		---------	--------
;
;	m.init.stack		None.		Initialize the CLEAR stack.
;
;	_salloc			int n		Allocate n bytes on the stack.
;
;	Algorithm:		With interrupts disabled (to allow for the
;				defective versions of the 8088), set SS:SP, SL.
;
;				Small model:	Set SS = DS.  Set SP from .6,
;						the top of the DGROUP.
;						SL. = HP. in minithea.a86.
;
;				Large model:	Set SS:SP from the base page.
;						SL. is assembled in.
;				
;
;	Source language:	DRI RASM-86
;
;	Target environment:	Intel iAPX-286 processor.
;
;	Author:			Bill Haygood
;
;	Date:			83-Apr-25 Monday
;
;	Revision history:
;
;	When		Who		Why and what
;	----		---		------------
;	83-May-05	Craig Franklin	Allow RETF from .CMD to OS.
;	83-May-05	Craig Franklin	Ignore stack size in BX.
;	83-Jun-14	Craig Franklin	Delete reference to m.term.
;	83-Jul-20	Haygood		Small model conditional assembly code.
;	83-Oct-09	Craig Franklin	Fix bug in medium model.
;	83-Oct-11	Haygood		Use stack. sseg for new LINK86 V1.2.
;	83-Oct-15	Craig Franklin	Use CLI/STI instead of slower PUSHF/POPF.
;	83-Oct-22	Craig Franklin	Add _salloc.
	eject
;	include	clear			; Get CLEAR definitions.
;
     if C32 eq 0;--------------------------------------------------------------
CGROUP	GROUP	cinit.							      ;
     endif	;--------------------------------------------------------------
;
cinit.	cseg
;
;	extrn	m.init.error: near
;
	public	m.init.stack, _salloc
;
; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
; *									      *
; *                          M . I N I T . S T A C K			      *
; *									      *
; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
;
m.init.stack:
	pop	ax			; Pop m.init return address.
	pop	cx			; Pop system return address (this is a
	pop	dx			; 32-bit address even in small model!).
;
;	Disable interrupts to set SS:SP.  (Early 8088 chips will fail if not.)
;
	sub	bx,bx			; BX = 0
     if	D32	;--------------------------------------------------------------
	cli				; Disable interrupts.
	mov	ss,15hÆbxÅ		; Setup stack segment register.
	mov	sp,12hÆbxÅ		; Set stack offset.
					; SL. is already set by assembly.
	sti				; Enable interrupts.
     else
	push	ds			; SS = DS
	cli				; Disable interrupts.
	pop	ss
	mov	sp,6ÆbxÅ		; Initialize SP from base page.
					; SL. is defined equ HP. in minithea.a86
	sti				; Enable interrupts.
     endif	;--------------------------------------------------------------
	inc	sp			; Use all available allocated memory.
	and	sp,0fffeh		; Align for iAPX-286 speed.
	eject
;
;	Now construct the first stack frame.
;
	push	dx			; Push system return address (this is a
	push	cx			; 32-bit address even in small model!).
	push	bx			; No previous stack frame.
	mov	bp,sp			; Establish the first stack frame.
	lea	dx,-8ÆbpÅ		; First stack frame is 8 words long.
	push	dx			; Set SAVESP
	push	bx			; Set ENLINK = 0 (no previous environment)
	push	bx			; Set ONLINK = 0 (no previous on frame)
	push	bx			; Set ONFRAME = 0 (no on units in frame)
	push	ax			; Push m.init return address
     if	D32	;--------------------------------------------------------------
	mov	ss:.0,ds		; For large model to load for big model
     endif	;--------------------------------------------------------------
	ret				; Return.
;
; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
; *									      *
; *                         _ s a l l o c				      *
; *									      *
; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
;
_salloc:				; Allocate N bytes on the stack.
	pop	bx			; Pop return address.
	popd	cx
	pop	dx			; Pop N.
	inc	dx			; Round N to even.
	and	dl,0feh
     if	D32	;--------------------------------------------------------------
	mov	ax,seg SL.
	mov	es,ax
	mov	ax,dx			; AX = N.
	add	ax,es:SL.		; AX = SL. + N
     else	; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
	mov	ax,dx			; AX = N.
	add	ax,SL.			; AX = SL. + N
     endif	;--------------------------------------------------------------
	cmp	ax,sp			; Would stack overflow?
	jbe	stackok			; No.
	call	m.init.error		; Yes, fatal error.
	db	'Stack overflow$'
;
stackok:
	sub	sp,dx			; Allocate N bytes.
	mov	ax,sp			; SS:AX -> N bytes on stack.
	push	dx			; Push N.
	pushd	cx			; Push return address
	push	bx
     if	D32	;--------------------------------------------------------------
	mov	bx,ss			; BX = SS for large model.
     endif	;--------------------------------------------------------------
	retc				; Return BX:AX -> N bytes on stack.
	eject
     if	D32	;--------------------------------------------------------------
;
; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
; *									      *
; *                                  D A T A				      *
; *									      *
; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
;
	dseg
;
	public	SL.
;
SL.		dw	14		; Stack limit. Bias of 14 is for string routines.
;
; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
; *									      *
; *               S T A C K   S T O R A G E   A L L O C A T I O N	      *
; *									      *
; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
;
;
stack.	sseg	word			; stack. is special to LINK86	      ;	
					; It causes .CMD MAX of 32K and	      ;
					; .CMD MIN of 2K or total sseg size,  ;
					; whichever is greater.
;									      ;
OSDS	dw	0			; DS from O/S			      ;
	public	ONFRAME							      ;
;									      ;
ONFRAME	dw	0							      ;
	dw	seg ONFRAME						      ;

     else	; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
	dseg
	extrn	SL.:word
     endif	;--------------------------------------------------------------
;
;	end
;	Name			'MINITCMD'
	Title			'M.INIT.CMD'
	Pagesize 75
;
;	File name:		MINITCMD.A86
;
;	Module name:		MINITCMD
;
;	Arguments:		None.
;
;	Return value:		_cmd_drive_bin		.CMD drive in binary
;				_cmd_drive_asc		.CMD drive in ASCII
;
;	Function:		To determine the .CMD file drive.
;
;	Algorithm:		Look at location 50h in the base page.
;				If it is non-zero, it is the binary .CMD drive.
;				If it is zero, get the current drive from BDOS.
;				In either case, add 'A' to get the ASCII drive.
;
;	Source language:	DRI RASM-86
;
;	Target environment:	Intel iAPX-286 processor.
;
;	Author:			Craig Franklin
;
;	Date:			83-Oct-16 Sunday
;
;	Revision history:
;
;	When		Who		Why and what
;	----		---		------------
	eject
;	include	clear			; Get CLEAR definitions.
;
curdrive	equ	25		; BDOS call to return current drive.
;
     if C32 eq 0;--------------------------------------------------------------
CGROUP	GROUP	cinit.							      ;
     endif	;--------------------------------------------------------------
;
cinit.	cseg
;
; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
; *									      *
; *                             m . i n i t . c m d			      *
; *									      *
; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
;
	public	m.init.cmd
;
m.init.cmd:
;
	mov	al,.50h			; AL = CMD drive number (1 to 20)
	dec	al			; AL = 0 to 19.
	jns	m.init.cmd.drive	; CMD drive was 0 (current drive)
	mov	cl,curdrive
	int	224
;
m.init.cmd.drive:
	mov	_cmd_drive_bin,al	; Store drive in binary.
	add	al,'A'			; Convert it to ASCII.
	mov	_cmd_drive_asc,al	; Store drive in ASCII.
	ret				; Return.
;
; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
; *									      *
; *                                  D A T A				      *
; *									      *
; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
;
; The data items are declared in this peculiar way to be accessible from C.
;
DGROUP		GROUP	_CMD_DRIVE_BIN,_CMD_DRIVE_ASC
;
_CMD_DRIVE_BIN	dseg	common
		public	_cmd_drive_bin
_cmd_drive_bin	db	0
;
_CMD_DRIVE_ASC	dseg	common
		public	_cmd_drive_asc
_cmd_drive_asc	db	0
;
;	end
;	Name			'MINITRELOC'
	Title			'M.INIT.RELOC'
	Pagesize 		75
;
;	File name:		MINITREL.A86
;
;	Module name:		MINITRELOC
;
;	Entry parameters:	Stack exists.  DS:0 -> base page.
;
;	Return value:		None.
;
;	Errors:			Must use R command or LINK86 V1.2 with this O/S
;
;	Entry point		Arguments
;	-----------		---------
;	m.init.reloc		None.
;
;	m.init.reloc.buffer	Pointer to null terminated relocation buffer.
;
;	_v_reloc_segs		Pointer to null terminated relocation buffer.
;				Pointer to array of 8 overlay segment bases.
;				Byte containing valid target relocation groups.
;
;	Function:		Relocate segment references in a program/overlay.
;				WARNING: program must be linked by LINK86 V1.2.
;
;	Source language:	DRI RASM-86
;
;	Target environment:	Intel iAPX-286 processor.
;
;	Author:			Bill Haygood
;
;	Date:			83-Apr-21 Thursday
;
;	Revision history:
;
;	When		Who		Why and what
;	----		---		------------
;	83-Jul-19	Haygood		Small model conditional assembly code.
;	83-Jul-30	Craig Franklin	Emit warning if unable to relocate.
;	83-Aug-11	Craig Franklin	Add C callable entry point for vcode.
;	83-Aug-30	Craig Franklin	Correctly relocate within an overlay.
;	83-Sep-3	Craig Franklin	Use new Link86 Aux Group 4 relocation.
;	83-Sep-13	Craig Franklin	Repackage for C runtime.
;	83-Sep-23	Craig Franklin	Optimize, compensate for LINK86 bug.
;	83-Sep-28	Craig Franklin	Add medium model to small and large.
;	83-Sep-29	Craig Franklin	Save SI and DI for caller REG variables.
;	83-Oct-15	Craig Franklin	Relocate only when loading a segment.
;	83-Oct-18	Craig Franklin	Add entry point for m.init.run to call.
	eject
;	include	clear			; Get CLEAR definitions.
;
cinit.	cseg
;
	public	m.init.reloc
;
;	extrn	m.init.run:	near
;	extrn	m.init.error:	near
;
; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
; *									      *
; *                       O F F S E T S   F R O M   B P			      *
; *									      *
; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
;
sidi		equ	-4		; Space to save SI and DI.
loadsegs	equ	-6		; Mask of segments to relocate.
overbases	equ	loadsegs -16	; 8 group bases from overlay header.
rootbases	equ	overbases-16	; 8 group bases from program base page.
;
; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
; *									      *
; *                          m . i n i t . r e l o c			      *
; *									      *
; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
;
if (C32 eq 0) and (D32 eq 0)
;
m.init.reloc:
	ret				; Small model -- no seg references.
     else	; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
;
	public	m.init.reloc.buffer	; Called only by m.init.run
	eject
; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
; *									      *
; *                          m . i n i t . r e l o c			      *
; *									      *
; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
;
m.init.reloc:
	mov	cx,seg m.init.reloc	; Get a relocatable segment reference.
	jcxz	need_relocation		; Relocation done already ?
	ret				; Yes, return to caller.
;
need_relocation:
	mov	cx,.45			; CX = Aux Group 4 base address.
	jcxz	old_LINK86		; If 0, must be LINK86 before V1.2
;
;	Relocate the root using Aux Group 4
;
	push	ds			; Save caller DS.
	mov	ds,.45			; DS:SI-> AUX GROUP 4
	sub	si,si
	call	m.init.reloc.buffer	; Relocate the root.
	pop	ds			; Restore caller DS.
	ret				; Return to caller.
;
old_LINK86:
	call	m.init.run		; Last resort: try to open .CMD file
	ret
;
;	Apply a relocation buffer to the root
;
m.init.reloc.buffer:
	push	bp			; Save caller BP.
	mov	bp,sp			; Create new stack frame.
	mov	ax,-1			; AX = ffffh = relocate all segments.
	push	ax			; Pretend to save SI and DI
	push	ax			; to synchronize with _v_reloc_segs.
	push	ax			; Push loadsegs.
	call	pushbase		; Push the group start addresses.
	call	reloc.buffer		; Do it all in only one call.
	mov	sp,bp			; Reset SP.
	pop	bp			; Restore caller BP.
	ret
;
; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
; *									      *
; *                               _ v_ r e l o c			      *
; *									      *
; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
;
BUFFER		equ	ARG1		; Offset from ÆBPÅ of buffer address.
OVERBASE	equ	BUFFER  +2+2*D32; Offset from ÆBPÅ of overlay bases.
LOADSEGS	equ	OVERBASE+2+2*D32; Offset from ÆBPÅ of valid targets.
;
	public	_v_reloc_segs
;
_v_reloc_segs:
	pushd	ds			; Save caller DS
	push	bp			; Save caller BP
	mov	bp,sp			; Address argument.
	push	si			; Save caller SI.
	push	di			; Save caller DI.
	push	word ptr LOADSEGSÆbpÅ	; Push loadsegs for reloc.buffer.
;
;	Push the overlay group start addresses
;
	ldx	si,OVERBASEÆbpÅ		; DS:SI -> overlay bases from caller.
;if D32		;--------------------------------------------------------------
	push	ss			; ES:DI -> stack frame overlay bases.
	pop	es			; TEMPORARY UNTIL ES = SS always
;endif		;--------------------------------------------------------------
	sub	sp,16			; Allocate space
	mov	di,sp			; Allocate space
	mov	cx,8			; 8 groups
	rep	movsw
;
;	Relocate the buffer
;
	ldx	si,BUFFERÆbpÅ		; DS:SI -> relocation buffer
	call	reloc.buffer		; Process the relocation buffer
	lea	sp,0-4ÆbpÅ		; Reset SP.
	pop	di			; Restore caller DI.
	pop	si			; Restore caller SI.
	pop	bp			; Restore caller BP.
	popd	ds			; Restore caller DS.
	retc
	eject
; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
; *									      *
; *	Subroutine to push the base page group start addresses		      *
; *									      *
; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
;
pushbase:
	pop	ax			; AX = return address.
	mov	bx,si			; BX = caller SI.
	mov	dx,ds			; DX = caller DS.
if D32
	mov	ds,ss:.0		; DS = original DS from O/S
else
	push	ss			; DS = SS
	pop	ds
endif
	mov	si,45			; .45, .39, .33, .27, .21, .15, .9, .3
	mov	cx,8			; Push 8 base addresses.
;
pushloop:
	push	word ptr ÆsiÅ		; Push the base.
	sub	si,6			; Locate next base.
	loop	pushloop		; Loop.
;
	mov	si,bx			; SI = caller SI.
	mov	ds,dx			; DS = caller DS.
	push	ax			; Push caller return address
	ret
	eject
;
; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
; *									      *
; *         P R O C E S S   O N E   R E L O C A T I O N   B U F F E R	      *
; *									      *
; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
;
;	Register usage:
;
;	(AX)	Temporary.
;	(BX)	Byte offset in paragraph.
;	(CX)	Shift count.
;	(DX)	Segment base to add to memory.
;	(DI)	Tempor▶e1◀ry.
;	(BP)	Frame pointer to address loadsegs byte and two base tables
;	(DS:SI)	Relocation buffer entry.
;	(ES:BX)	Memory word to relocate.
;
reloc.buffer:
	pop	di			; DI = caller return address.
	call	pushbase		; Push the root base addresses.
	push	di			; Push caller return address.
	push	si			; Save caller SI.
	sub	ax,ax			; AX = 0 (for first LODSB).
	sub	cx,cx			; CX = 0.
	jmps	reloc.element.into	; Jump into loop.
;
reloc.element.loop:
;
;	Set DX = source group base
;
	sub	al,11h			; Convert 1-8/1-8 to 0-7/0-7.
	mov	di,ax			; DI = AX.
	and	di,0007h		; DI = source group number (0-7).
	add	di,di			; DI = source group number * 2.
	mov	dx,rootbasesÆdi+bpÅ	; DX = source group base.
;
;	Set DI = target group base
;
	and	al,70h			; AX = target group number * 16.
	shr	al,1			; AX = target group number *  8.
	shr	al,1			; AX = target group number *  4.
	shr	al,1			; AX = target group number *  2.
	mov	di,ax			; DI = target group number *  2.
	mov	di,overbasesÆdi+bpÅ	; DI = target group base.
;
;	Set BL = byte with a 1 bit in it for the target group
;
	shr	al,1			; AX = target group number *  1.
	mov	cl,al			; CX = target group number.
	mov	bl,1			; BL = 1 for shift
	shl	bl,cl			; BL = mask with 1 for target segment
;
;	Compute address of memory word to add DX to
;
	lodsw				; AX = paragraph offset of memory word
	add	di,ax			; DI = segment base of memory word
	mov	es,di			; ES = DI
	sub	ax,ax			; Clear AX for LODSB.
	lodsb				; AL = byte offset of memory word
	test	bl,loadsegsÆbpÅ		; OK to relocate target segment?
	jz	reloc.element.into	; No.
	mov	bx,ax			; BX = byte offset
	add	es:ÆbxÅ,dx		; Relocate memory word.
;
reloc.element.into:
	lodsb				; AL = group number
	test	al,0f0h			; End of buffer or fixup list ?
	jnz	reloc.element.loop	; No.
;
	sub	ax,ax			; Assume return false (done).
	pop	bx			; BX = input SI
	sub	si,bx			; SI = number of bytes processed.
	sub	si,129			; Full buffer processed?
	jnz	reloc.element.return	; No,  return 0 (last buffer).
	inc	ax			; Yes, return 1 (more to come).
;
reloc.element.return:
if	D32 eq 0;--------------------------------------------------------------
	push	ss			; Reset ES = SS for small model.
	pop	es
endif		;--------------------------------------------------------------
	ret				; Return.
;
endif	;----------------------------------------------------------------------
;
;	end
;	Name			'MINITHEAP'
	Title			'M.INIT.HEAP'
	Pagesize 75
;
;	File name:		MINITHEA.A86
;
;	Module name:		MINITHEAP
;
;	Entry point		Arguments		Function
;	-----------		---------		--------
;
;	m.init.heap		None.			Initialize the heap.
;
;	nbrk			None			Return the remaining
;							heap size in bytes.
;							Return (long)(HL.-HP.)
;
;	sbrk			int n			Extend the heap n bytes.
;							If HP. + n <= HL.,
;							set HP. = HP. + n
;
;	brk			char *p			If HP. <= p <= HL.,
;							set HP. = p
;
;	Algorithm:	
;
;		m.init.heap:
;
;			Large:	Set HP. to point to ESEG.
;				Set HL. to point to HP. + size of ESEG.
;
;			Small:	Set HP. to point to the heap at the bottom of
;			the free area.  The stack is located at the top of the
;			free area.  Equivalence HL. and SL., the stack limit.
;
;		nbrk:	Set R = HP. - HL., if D32 set R *= 16, return R.
;
;		sbrk:	Round request r to bytes or paragraphs, set R = P = HP.,
;			set P = P+r, if P <= HL., set HP. = R and return R.
;
;		brk:	Compare pointer argument P to HP. and HL.
;			If P >= HP. and P <= HL., set HP. = P, and
;			return 0 (success), else return -1 (failure).
;
;		In all of the above routines, HP. and HL. are one word
;		pointers into the heap whose units are paragraphs.
;		When sbrk returns the old HP., it is converted to a
;		pointer with offset 0 in the large model.
;		This is so the caller can use a full 64K byte offset with it.
;
;	Source language:	DRI RASM-86
;
;	Target environment:	Intel iAPX-286 processor.
;
;	Author:			Herbert Yuen and Bill Haygood
;
;	Date:			83-Apr-11 Monday
;
;	Revision history:
;
;	When		Who		Why and what
;	----		---		------------
;	06-Jul-83	Craig Franklin	Add sbrk, brk entry points
;					to correct 3 bugs in C versions.
;	83-Jul-19	Haygood		Small model conditional assembly code.
;	83-Oct-11	Haygood		Use heap. eseg for new LINK86 V1.2.
;	83-Oct-11	Craig Franklin	Change retc to ret for C.  Add nbrk.
	eject
;	include	clear			; Get CLEAR definitions.
;
     if	D32 eq 0;--------------------------------------------------------------
slack	equ	256			; Allow for additional stack.
     endif	;--------------------------------------------------------------
;
cinit.	cseg
;
	public	m.init.heap, nbrk, sbrk, brk
;
; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
; *									      *
; *                           m . i n i t . h e a p			      *
; *									      *
; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
;
m.init.heap:
     if	D32	;--------------------------------------------------------------
	mov	ax,.0ch			; AX = low word  of Extra Segment offset
	mov	dh,.0eh			; DH = high byte of Extra Segment offset.
	add	ax,15			; Convert offset to paragraphs.
	jnc	m.init.heap.nc		; Jump if not 64K boundary.
	inc	dh			; 64K boundary.  Increment high order.
;
m.init.heap.nc:
	and	al,0f0h			; Round bytes to paragraphs.
	mov	cl,4			; CL = 4
	shr	ax,cl			; Convert to paragraph number.
	shl	dh,cl			; Convert to paragraph number.
	add	ah,dh			; AX = paragraph number of heap size
	add	ax,HP.			; AX = paragraph number of heap limit
	mov	HL.,ax			; Set heap limit
     else
	push	ds			; ES = DS
	pop	es
	mov	ax,?MEMRY		; Set up heap for brk().
	mov	HP.,ax
     endif	;--------------------------------------------------------------
	ret
	eject
;
; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
; *									      *
; *                                  n b r k				      *
; *									      *
; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
;
nbrk:
     if	D32	;--------------------------------------------------------------
	mov	ax,seg HP.		; AX = seg HP.
	mov	es,ax			; Set ES = seg HP.
	mov	ax,es:HL.		; AX = heap limit.
	sub	ax,es:HP.		; AX = heap size = heap limit - heap base.
	mov	bx,16
	mul	bx			; Convert paragraphs to long int bytes.
	mov	bx,dx			; In AX/BX.
	retc				; Return.
     else	; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
	mov	ax,sp			; AX = heap limit.
	sub	ax,slack		; Allow for additional stack.
	sub	ax,HP.
	sub	bx,bx			; Return long int bytes.
	retc				; Return.
     endif	;--------------------------------------------------------------
;
; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
; *									      *
; *                                  s b r k				      *
; *									      *
; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
;
sbrk:
     if	D32	;--------------------------------------------------------------
	mov	bx,sp			; Address argument
	mov	dx,ss:2+2*C32ÆbxÅ	; Get allocation size in bytes.
	add	dx,15			; Round up to next paragraph.
	and	dl,0f0h
	mov	cl,4			; CL = 4
	shr	dx,cl			; Convert bytes to paragraphs
	push	ds			; Save caller DS (large model)
	mov	bx,seg HP.		; BX = DS of HP.
	mov	ds,bx			; Set DS
	mov	bx,HP.			; BX = old heap pointer (in paragraphs)
	sub	ax,ax			; BX:AX = old HP.:0 = pointer to area
	add	dx,bx			; DX = new heap pointer (in paragraphs)
	cmp	dx,HL.			; Will it fit ?
	ja	xbrk.fail		; No.  Fail.
	mov	HP.,dx			; Update HP.
	pop	ds			; Restore original DS.
	retc				; Return BX:AX = old HP.:0.
;
xbrk.fail:				; Set AX = -1 (failure) and return.
	mov	ax,-1			; AX = -1
	mov	bx,ax
	pop	ds			; Restore original DS.
	retc				; Return.
;
     else
	mov	bx,sp			; BX = SP
	mov	bx,ss:2+2*C32ÆbxÅ	; Get argument.
	inc	bx			; Round up to even byte boundary.
	and	bl,0feh
	mov	ax,HP.			; Get current heap pointer.
	add	bx,ax			; Did wrap around occur ?
	jc	xbrk.fail		; Yes.
	jmps	xbrk
;
xbrk.fail:				; Set AX = -1 (failure) and return.
	mov	ax,-1			; AX = -1
	ret				; Return.
     endif	;--------------------------------------------------------------
	eject
;
; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
; *									      *
; *				     b r k				      *
; *									      *
; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
;
brk:
     if	D32	;--------------------------------------------------------------
	mov	bx,sp			; BX = SP
	push	ds			; Save caller DS (large model)
	mov	ax,ss:2+2*C32ÆbxÅ	; AX = pointer offset
	mov	bx,ss:4+2*C32ÆbxÅ	; BX = pointer segment
	add	ax,15			; Round AX from bytes to paragraphs
	jnc	brk.ok			; Carry ?
	add	bx,1000h		; Yes, add 64K bytes to segment.
;
brk.ok:
	mov	cl,4			; CL = 4
	shr	ax,cl
	add	ax,bx			; And add in segment
	cmp	ax,HP.			; Below current heap pointer?
	jb	xbrk.fail		; Yes.  Fail.
	cmp	ax,HL.			; Above heap limit?
	ja	xbrk.fail		; Yes.  Fail.
	mov	HP.,ax			; Reset heap pointer
	sub	ax,ax			; Succeed.
	pop	ds			; Restore caller DS
     else
	mov	bx,sp
	mov	bx,ss:2+2*C32ÆbxÅ	; Get parameter - brk address.
	sub	ax,ax			; AX = 0 for success
;
xbrk:
	mov	cx,sp			; CX = SP
	sub	cx,slack		; Allow for additional stack.
	cmp	bx,cx			; Below stack pointer ?
	jae	xbrk.fail		; No.
	cmp	bx,HP.			; Above heap pointer ?
	jb	xbrk.fail		; No.
	mov	HP.,bx			; Set new heap pointer.
     endif	;--------------------------------------------------------------
	retc				; Return.
	eject
;
; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
; *									      *
; *                                  D A T A				      *
; *									      *
; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
;
	dseg
;
     if	D32	;--------------------------------------------------------------
HP.	dw	seg ES.			; Heap pointer in paragraphs.	      ;
HL.	dw	0			; Heap limit in paragraphs.	      ;
;					; (Set by m.init.heap.)		      ;
;
; heap. is special to LINK86:  it sets .CMD MAX to 32K and .CMD MIN to 2k or
; eseg total, whichever is larger.
;
heap.	eseg								      ;
;									      ;
ES.	rw	0							      ;
     else	; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
	public	?MEMRY, HP., SL.					      ;
?MEMRY	rw	1			; Initialized by LINK86.	      ;
HP.	rw	1			; Heap pointer in bytes.	      ;
SL.	equ	HP.			; Is also stack limit in bytes.	      ;
     endif	;--------------------------------------------------------------
;
;	end
;	Name			'MINITERROR'
	Title			'M.INIT.ERROR'
	Pagesize 75
;
;	File name:		MINITER.A86
;
;	Module name:		MINITERROR
;
;	Entry parameters:	None.
;
;	Return value:		None.
;
;	Entry point		Arguments
;	-----------		---------
;
;	m.init.hardware.error	None.
;
;	Function:		To initialize the runtime system integer zero
;				divide error handler.
;
;	Algorithm:		Place the vector to the integer zero divide
;				handler in absolute location 0:0.
;
;	Source language:	DRI RASM-86
;
;	Target environment:	Intel iAPX-286 processor.
;
;	Author:			Bill Haygood
;
;	Date:			83-Apr-07 Thursday
;
;	Revision history:
;
;	When		Who		Why and what
;	----		---		------------
;	83-Jul-20	Haygood		Small model conditional assembly code.
;	83-Oct-25	Craig Franklin	Abort with error message.
	eject
;	include	clear			; Get CLEAR definitions.
;
     if C32 eq 0;--------------------------------------------------------------
CGROUP	GROUP	cinit.							      ;
     endif	;--------------------------------------------------------------
;
cinit.	cseg
;
;	extrn	m.init.error: near
;
	public	m.init.hardware.error
;
; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
; *									      *
; *                   m . i n i t . h a r d w a r e . e r r o r		      *
; *									      *
; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
;
;	Initialize the zero divide vector.
;
m.init.hardware.error:
	push	ds			; Save original DS.
	sub	bx,bx			; BX -> offset 0
	mov	ds,bx			; DS = 0
	mov	ÆbxÅ,offset zerodiv	; Store the zero divide handler pointer
	mov	2ÆbxÅ,cs		;	at hardware locations 0 and 2.
	pop	ds			; Restore original DS.
	ret				; Return.
;
; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
; *									      *
; *                               z e r o d i v				      *
; *									      *
; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
;
;	Integer zero divide handler.
;
zerodiv:
	call	m.init.error		; Fatal error
	db	'Zero divide error$'
;
	end
«eof»