|
|
DataMuseum.dkPresents historical artifacts from the history of: RegneCentralen RC759 "Piccoline" |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about RegneCentralen RC759 "Piccoline" Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - download
Length: 39936 (0x9c00)
Types: TextFile
Names: »STARTUP.A86«
└─⟦fa5b86546⟧ Bits:30002725 SW1609 Digital Research C - CCP/M - Oct 83
└─⟦this⟧ »STARTUP.A86«
; 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»