515 lines
11 KiB
NASM
515 lines
11 KiB
NASM
PAGE 56,132
|
|
title entx - Common Pascal/FORTRAN Initialization module
|
|
|
|
;---------------------------------------------------------------------------
|
|
;
|
|
; Microsoft MS-DOS/Windows/XENIX Pascal/FORTRAN Initialization
|
|
; Version 3.30 (C) Copyright 1984 Microsoft Corporation
|
|
;
|
|
; BEGXQQ is called (indirectly) from the C runtime startup routine.
|
|
; It performs initialization of the Pascal and FORTRAN runtime
|
|
; systems. Note that if it is called again, BEGXQQ simply returns.
|
|
;
|
|
; ENDXQQ is called (again, indirectly) from the C startup routine,
|
|
; just before it terminates the user's program. ENDXQQ also ignores
|
|
; all but its first invocation.
|
|
;
|
|
; Revision History
|
|
;
|
|
; 06/14/84 Allen Akin
|
|
; First version, cribbed from previous
|
|
; versions of ENTX and MS-C startup routines
|
|
; 07/12/84 Allen Akin
|
|
; Modified initializer scheme to allow
|
|
; arbitrary numbers of initializers
|
|
; 11/07/84 Gordon Whitten
|
|
; Moved DOSXQQ to RTIM6.ASM
|
|
; 11/21/84 Greg Whitten
|
|
; 11/28/84 set up new stack checking
|
|
; 11/29/84 set up newer stack checking
|
|
; 12/04/84 Allen Akin
|
|
; Added calls to old-style escape
|
|
; initializers (BEGOQQ and ENDOQQ)
|
|
; for compatibility with earlier
|
|
; releases.
|
|
; 12/04/84 Added floating-point exception handler
|
|
; for XENIX.
|
|
;---------------------------------------------------------------------------
|
|
|
|
|
|
?DF = 1
|
|
include pasrun.inc
|
|
|
|
page
|
|
include sysi.inc
|
|
|
|
page
|
|
; Special segments used in this module
|
|
|
|
; CreateSeg name, logname,align, combine,class, group
|
|
CreateSeg _TEXT, code, byte, public, CODE
|
|
CreateSeg _DATA, data, word, public, DATA, DGROUP
|
|
ifndef WINDOWS
|
|
CreateSeg STACK, STACK, word, stack, STACK, DGROUP
|
|
endif
|
|
|
|
CreateSeg XIB, xibeg, word, public, DATA, DGROUP
|
|
CreateSeg XI, xiseg, word, public, DATA, DGROUP
|
|
CreateSeg XIE, xiend, word, public, DATA, DGROUP
|
|
|
|
CreateSeg XCB, xcbeg, word, public, DATA, DGROUP
|
|
CreateSeg XC, xcseg, word, public, DATA, DGROUP
|
|
CreateSeg XCE, xcend, word, public, DATA, DGROUP
|
|
|
|
CreateSeg P1IB, pf1ibeg,word, public, DATA, DGROUP
|
|
CreateSeg P1I, pf1iseg,word, public, DATA, DGROUP
|
|
CreateSeg P1IE, pf1iend,word, public, DATA, DGROUP
|
|
|
|
CreateSeg P2IB, pf2ibeg,word, public, DATA, DGROUP
|
|
CreateSeg P2I, pf2iseg,word, public, DATA, DGROUP
|
|
CreateSeg P2IE, pf2iend,word, public, DATA, DGROUP
|
|
|
|
CreateSeg P3IB, pf3ibeg,word, public, DATA, DGROUP
|
|
CreateSeg P3I, pf3iseg,word, public, DATA, DGROUP
|
|
CreateSeg P3IE, pf3iend,word, public, DATA, DGROUP
|
|
|
|
CreateSeg P1CB, pf1cbeg,word, public, DATA, DGROUP
|
|
CreateSeg P1C, pf1cseg,word, public, DATA, DGROUP
|
|
CreateSeg P1CE, pf1cend,word, public, DATA, DGROUP
|
|
|
|
CreateSeg P2CB, pf2cbeg,word, public, DATA, DGROUP
|
|
CreateSeg P2C, pf2cseg,word, public, DATA, DGROUP
|
|
CreateSeg P2CE, pf2cend,word, public, DATA, DGROUP
|
|
|
|
CreateSeg P3CB, pf3cbeg,word, public, DATA, DGROUP
|
|
CreateSeg P3C, pf3cseg,word, public, DATA, DGROUP
|
|
CreateSeg P3CE, pf3cend,word, public, DATA, DGROUP
|
|
|
|
DefGrp DGROUP
|
|
|
|
page
|
|
; System resident public data
|
|
|
|
; these could be communal variables and off in some other segment
|
|
|
|
externDP ___argv ; arg pointer set by C startup
|
|
externW ___argc ; arg count set by C startup
|
|
|
|
sBegin data
|
|
assumes ds,data
|
|
|
|
ifdef MSD
|
|
externW __psp ; program segment prefix paragraph #
|
|
endif
|
|
|
|
externCP __aaltstkovr ; alternate stack overflow handler
|
|
|
|
globalW STKBQQ,0 ; stack top - set by main program
|
|
|
|
globalW CSXEQQ,0 ; pointer to source context list
|
|
globalW CLNEQQ,0 ; last line number encountered
|
|
|
|
globalW PNUXQQ,0 ; pointer to unit initialization list
|
|
|
|
globalW HDRFQQ,0 ; Unit F open file list header
|
|
globalW HDRVQQ,0 ; Unit V open file list header
|
|
|
|
globalW RESEQQ,0 ; machine error context, stack pointer
|
|
|
|
globalW REFEQQ,0 ; machine error context, frame pointer
|
|
globalW REPEQQ,0 ; machine error context, program offset
|
|
globalW RECEQQ,0 ; machine error context, program segment
|
|
globalW UPCX87,0 ; offset address of 8087 error context
|
|
|
|
globalW DGRMQQ,0 ; segment of DGROUP
|
|
|
|
globalW DOSEQQ,0 ; DOS return code
|
|
|
|
globalDP AGVXQQ,0 ; pointer to argument vector
|
|
globalW AGCXQQ,0 ; count of argument
|
|
globalW CURXQQ,1 ; index of argument currently in use
|
|
|
|
globalW RETLQQ,0 ; return address storage, used by pocket code
|
|
|
|
ifdef MSD
|
|
globalW CESXQQ,0 ; segment for arg string under DOS
|
|
endif
|
|
|
|
sEnd
|
|
|
|
page
|
|
; Local data:
|
|
|
|
sBegin data
|
|
|
|
staticW BEGX_CALLED,0 ; non-zero iff BEGXQQ has been called
|
|
staticW ENDX_CALLED,0 ; non-zero iff ENDXQQ has been called
|
|
|
|
sEnd
|
|
|
|
page
|
|
; C Runtime initialization segment:
|
|
|
|
sBegin xiseg
|
|
|
|
StaticCP begx,BEGXQQ ; General Pascal/FORTRAN initialization
|
|
|
|
sEnd
|
|
|
|
|
|
|
|
; C Runtime termination segment:
|
|
|
|
sBegin xcseg
|
|
|
|
StaticCP endx,PFTERM ; General Pascal/FORTRAN termination
|
|
|
|
sEnd
|
|
|
|
page
|
|
; Pascal/Fortran initialization segments:
|
|
|
|
sBegin pf1ibeg ; Unit U initialization level
|
|
uuibeg label dword
|
|
sEnd
|
|
|
|
; initializer addresses appear in pf1iseg, here in the middle...
|
|
|
|
sBegin pf1iend
|
|
uuiend label dword
|
|
sEnd
|
|
|
|
|
|
|
|
sBegin pf2ibeg ; User initialization level
|
|
uoibeg label dword
|
|
sEnd
|
|
|
|
; user initializer addresses appear in pf2iseg, here in the middle...
|
|
|
|
sBegin pf2iend
|
|
uoiend label dword
|
|
sEnd
|
|
|
|
|
|
|
|
sBegin pf3ibeg ; Unit F/V initialization level
|
|
ufibeg label dword
|
|
sEnd
|
|
|
|
; unit F/V initializer addresses appear in pf3iseg, here in the middle...
|
|
|
|
sBegin pf3iend
|
|
ufiend label dword
|
|
sEnd
|
|
|
|
page
|
|
; Pascal/FORTRAN termination segments:
|
|
|
|
sBegin pf1cbeg ; Unit U termination level
|
|
uucbeg label dword
|
|
sEnd
|
|
|
|
; unit U cleanup addresses appear in pf1cseg, here in the middle...
|
|
|
|
sBegin pf1cend
|
|
uucend label dword
|
|
sEnd
|
|
|
|
|
|
|
|
sBegin pf2cbeg ; User termination level
|
|
uocbeg label dword
|
|
sEnd
|
|
|
|
; user cleanup addresses appear in pf2cseg, here in the middle...
|
|
|
|
sBegin pf2cend
|
|
uocend label dword
|
|
sEnd
|
|
|
|
|
|
|
|
sBegin pf3cbeg ; Unit F/V termination level
|
|
ufcbeg label dword
|
|
sEnd
|
|
|
|
; unit F/V cleanup addresses appear in pf3cseg, here in the middle...
|
|
|
|
sBegin pf3cend
|
|
ufcend label dword
|
|
sEnd
|
|
|
|
page
|
|
; BEGXQQ - Common FORTRAN/Pascal Initialization Code
|
|
|
|
externP SOWGQQ
|
|
externP BEGOQQ ; escape initializer, old-style
|
|
externP ENDOQQ ; escape terminator, old-style
|
|
|
|
if XENIXRUNTIME
|
|
externP _signal ; XENIX exception-handling routine
|
|
externP XFPEQQ ; Pascal/FORTRAN exception vectoring routine
|
|
endif
|
|
|
|
sBegin code
|
|
assumes cs,code
|
|
assumes ds,dgroup
|
|
|
|
cProc BEGXQQ,<PUBLIC,FAR>
|
|
cBegin
|
|
cmp BEGX_CALLED,0 ; have we been called before?
|
|
jne breturn ; if so, just return
|
|
|
|
inc BEGX_CALLED ; prevent further calls
|
|
|
|
mov ax,seg SOWGQQ ; __chkstk escape for
|
|
mov word ptr [__aaltstkovr+2],ax ; P/F stack overflow
|
|
mov ax,offset SOWGQQ
|
|
mov word ptr [__aaltstkovr],ax
|
|
|
|
mov ax,seg ___argv ; prepare to address ___argv, which may be far
|
|
mov es,ax
|
|
mov ax,word ptr es:___argv ; copy C's argv pointer into Pascal's
|
|
mov word ptr AGVXQQ,ax
|
|
if SizeD
|
|
mov ax,word ptr es:___argv+2
|
|
mov word ptr AGVXQQ+2,ax
|
|
endif
|
|
|
|
mov ax,seg ___argc
|
|
mov es,ax
|
|
mov ax,es:___argc ; copy C's arg count into Pascal's
|
|
mov AGCXQQ,ax
|
|
|
|
ifdef MSD
|
|
mov ax,__psp ; get program segment prefix pp. address
|
|
mov CESXQQ,ax ; save it away for use by Pascal
|
|
endif
|
|
|
|
init1: ; perform first-level initializations,
|
|
; including unit U
|
|
mov bx,offset DGROUP:uuibeg
|
|
init1_1:
|
|
cmp bx,offset DGROUP:uuiend
|
|
jae init2
|
|
push bx
|
|
push si
|
|
push di
|
|
if SizeC
|
|
call dword ptr [bx]
|
|
else
|
|
call word ptr [bx]
|
|
endif
|
|
pop di
|
|
pop si
|
|
pop bx
|
|
if SizeC
|
|
add bx,4
|
|
else
|
|
add bx,2
|
|
endif
|
|
jmp init1_1
|
|
|
|
init2: ; perform second-level initializations
|
|
; including unit O and old-style escape
|
|
; initializers
|
|
if XENIXRUNTIME
|
|
mov ax,SEG fpe_handler
|
|
push ax
|
|
mov ax,OFFSET fpe_handler
|
|
push ax
|
|
mov ax,08H ; SIGFPE
|
|
push ax
|
|
call _signal ; set up to catch floating-point exceptions
|
|
add sp,6
|
|
endif
|
|
|
|
call BEGOQQ
|
|
|
|
mov bx,offset DGROUP:uoibeg
|
|
init2_1:
|
|
cmp bx,offset DGROUP:uoiend
|
|
jae init3
|
|
push bx
|
|
push si
|
|
push di
|
|
if SizeC
|
|
call dword ptr [bx]
|
|
else
|
|
call word ptr [bx]
|
|
endif
|
|
pop di
|
|
pop si
|
|
pop bx
|
|
if SizeC
|
|
add bx,4
|
|
else
|
|
add bx,2
|
|
endif
|
|
jmp init2_1
|
|
|
|
init3: ; perform third-level initializations
|
|
; including units F and V
|
|
mov bx,offset DGROUP:ufibeg
|
|
init3_1:
|
|
cmp bx,offset DGROUP:ufiend
|
|
jae initlast
|
|
push bx
|
|
push si
|
|
push di
|
|
if SizeC
|
|
call dword ptr [bx]
|
|
else
|
|
call word ptr [bx]
|
|
endif
|
|
pop di
|
|
pop si
|
|
pop bx
|
|
if SizeC
|
|
add bx,4
|
|
else
|
|
add bx,2
|
|
endif
|
|
jmp init3_1
|
|
|
|
initlast:
|
|
|
|
breturn: ; return -- all done.
|
|
cEnd
|
|
|
|
if XENIXRUNTIME
|
|
page
|
|
; fpe_handler - Floating-point exception handler for XENIX
|
|
|
|
; For the present, this routine just calls XFPEQQ (the FORTRAN/Pascal
|
|
; floating-point exception handler for XENIX). We go through this
|
|
; intermediate routine to keep the stack consistent; if we were to vector
|
|
; directly to XFPEQQ, this would not necessarily be done for us.
|
|
;
|
|
; In the future, this routine may disappear or at least fudge the stack
|
|
; to provide a little better context information for debugging.
|
|
|
|
cProc fpe_handler,<FAR>
|
|
cBegin
|
|
call XFPEQQ
|
|
cEnd
|
|
|
|
endif
|
|
|
|
sEnd
|
|
|
|
page
|
|
; ENDXQQ - Explicitly terminate Pascal or FORTRAN program
|
|
|
|
ExternP _exit ; C exit
|
|
|
|
sBegin code
|
|
assumes cs,code
|
|
assumes ds,dgroup
|
|
|
|
cProc ENDXQQ,<PUBLIC,FAR>
|
|
cBegin
|
|
ccall _exit,DOSEQQ ; exit, returning code in DOSEQQ
|
|
cEnd
|
|
|
|
sEnd
|
|
|
|
page
|
|
; PFTERM - common Pascal/FORTRAN termination
|
|
|
|
sBegin code
|
|
assumes cs,code
|
|
assumes ds,dgroup
|
|
|
|
cProc PFTERM,<FAR>
|
|
cBegin
|
|
cmp ENDX_CALLED,0 ; have we been called before?
|
|
jne ereturn ; if so, just return
|
|
|
|
inc ENDX_CALLED ; prevent further calls
|
|
|
|
term3: ; perform third-level terminations,
|
|
; including units F and V
|
|
mov bx,offset DGROUP:ufcbeg
|
|
term3_1:
|
|
cmp bx,offset DGROUP:ufcend
|
|
jae term2
|
|
push bx
|
|
push si
|
|
push di
|
|
if SizeC
|
|
call dword ptr [bx]
|
|
else
|
|
call word ptr [bx]
|
|
endif
|
|
pop di
|
|
pop si
|
|
pop bx
|
|
if SizeC
|
|
add bx,4
|
|
else
|
|
add bx,2
|
|
endif
|
|
jmp term3_1
|
|
|
|
term2: ; perform second-level terminations,
|
|
; including unit O and old-style
|
|
; escape terminator
|
|
mov bx,offset DGROUP:uocbeg
|
|
term2_1:
|
|
cmp bx,offset DGROUP:uocend
|
|
jae term1
|
|
push bx
|
|
push si
|
|
push di
|
|
if SizeC
|
|
call dword ptr [bx]
|
|
else
|
|
call word ptr [bx]
|
|
endif
|
|
pop di
|
|
pop si
|
|
pop bx
|
|
if SizeC
|
|
add bx,4
|
|
else
|
|
add bx,2
|
|
endif
|
|
jmp term2_1
|
|
|
|
term1:
|
|
call ENDOQQ
|
|
; perform first-level terminations,
|
|
; including unit U
|
|
mov bx,offset DGROUP:uucbeg
|
|
term1_1:
|
|
cmp bx,offset DGROUP:uucend
|
|
jae termlast
|
|
push bx
|
|
push si
|
|
push di
|
|
if SizeC
|
|
call dword ptr [bx]
|
|
else
|
|
call word ptr [bx]
|
|
endif
|
|
pop di
|
|
pop si
|
|
pop bx
|
|
if SizeC
|
|
add bx,4
|
|
else
|
|
add bx,2
|
|
endif
|
|
jmp term1_1
|
|
|
|
termlast:
|
|
|
|
ereturn: ; return -- all done.
|
|
cEnd
|
|
|
|
sEnd
|
|
|
|
end
|