home *** CD-ROM | disk | FTP | other *** search
Text File | 1992-12-09 | 60.6 KB | 1,978 lines |
- small_m = 1
- mach386 = 1
- GOC = 0
- .386p ; Need 2 p to execute "lsl" to determine limit of data segment.
- .287
-
- ; If you use Microsoft MASM (5.1) or MASM (6.0), enable one of the following
- ; equates.
- ; If you use MASM, you must also use "bd -mtop init.obj" to convert
- ; the MASM object to a Phar Lap object, if you wish to use the Phar Lap linker.
- ; USING_MASM_51 equ 1
- ; USING_MASM_60 equ 1
-
- ; If you are using masm386 (not masm) to assemble this, with the intent
- ; to link with OS/2 2.0's link386, turn on USING_FLAT. This avoids the use
- ; of DGROUP and CGROUP which OS/2 2.0's linear executable loader cannot
- ; support.
- ; USING_FLAT equ 1
-
- ; If you are assembling for AUTOCAD ADS/ADI libraries:
- ; 386asmp init -nol -twoc -i \hc172\lib\src\ -d ADS
- ; 386asmp init -nol -twoc -i \hc172\lib\src\ -d PADI
-
- name init
- ; (assemble this with "386asm init")
- ;**************************************************************************
- ;*** (c) Copyright 1983 - 1990 MetaWare Incorporated. ***
- ;**************************************************************************
- ;*** You have the same rights to the object form of this program as ***
- ;*** you do to the object code of the library. You may not distribute ***
- ;*** this source, even if modified by you. ***
- ;**************************************************************************
- ;*** The source to this module is provided ***
- ;*** for the convenience of MetaWare Pascal and High C users that need ***
- ;*** to tailor their execution environments. ***
- ;*** The casual user should NOT play with the code. ***
- ;*** This code is subject to change without notice in future releases ***
- ;*** of the compilers. ***
- ;**************************************************************************
- ;*** You must preserve the library copyright notice defined in this ***
- ;*** module if your program uses any portion at all of the run-time ***
- ;*** library (including this initializer or any other supplied run- ***
- ;*** time source). The copyright notice is in the definition of ***
- ;*** the initial stack segment. We recommend it be left right there. ***
- ;*** But you can move it to anywhere you want as long it appears in ***
- ;*** any linked program (.exe or ROM-burned program) using the library.***
- ;**************************************************************************
- ;* *
- ;* MetaWare Pascal or High C Runtime Initialization Module *
- ;* for small model, protected mode 386. *
- ;* *
- ;**************************************************************************
- include model ; Memory model.
-
- ; GROWHEAP.
- ; Dynamic heap expansion.
- ; As an option the run-time system will contract the data area back to
- ; a minimum at start-up, and expand it dynamically.
- ; This is principally useful if you wish to allocate memory separately
- ; from the run-time system using the SETBLOCK (4a) command.
-
- ; Phar Lap's DOS|Extender 1.1t or later can grow the heap dynamically.
- ; For enabling Phar Lap DOS|Extender to grow the heap dynamically,
- ; uncomment the next line.
- PHAR_LAP_CAN_GROW_HEAP equ 1
-
- ; AIA's OS/386 2.0.10 or later can grow the heap dynamically.
- ; For older versions, comment out the next line.
- AIA_CAN_GROW_HEAP equ 1
- ; For Lahey-linked programs, we assume expansion can occur, since such
- ; linked programs do not give you all of memory.
-
- ;-----
- ; The following include file is provided by IGC.
- ; GDA.STR is general data area structure for VM/RUN (X-AM).
- ; Upon entry to target program from VMRUN, EDX --> GDA.
- ; GDA is not useful when solely in the Phar-Lap environment.
- ; Use "gda.h" in the inc/ directory to access the GDA from C:
- ; #include "gda.h"
- ; GDA *gdaptr;
- ;-----
- include gda.str
-
- ; The difference between the Pascal and C run-time initialization
- ; is that in C, the argv array must be allocated and computed.
- ; In Pascal argument processing is handled through a separate argument pacakge.
-
- ; Defines that you can set:
- ; 1. HC. Set if this is for the High C library; not set otherwise.
- ; 2. STACK_SIZE. Set this to the size of the stack you want.
- ; 3. no87. Set this if you know you have no 8087 or 287. It will eliminate
- ; the initialization code for the chip.
- ; Also, it will remove the printing of the "no87" environment variable
- ; if you have an 8087/287 and the no87 variable is set to non-blank string.
- ; (Don't confuse the "no87" define in this assembly from the no87
- ; MS-DOS environment variable. Read the programmer's Guide for more info
- ; on the latter.)
- ; Another reason to set this variable is that you know you're never
- ; going to use an 8087/287, even if you have one. It's especially
- ; useful to remove the printing of the no87 environment variable on
- ; programs for which the 8087/287 processor is irrelevant.
- ; 4. DOS. Set this if this initializer is for MS-DOS (default). Unset it
- ; for embedded applications where DOS doesn't exist. If you unset it,
- ; you won't get argc/argv for C, nor the arg package for Pascal.
- ; It doesn't remove all of the DOS-dependent code -- some of it you must
- ; still rewrite for embedded applications (like how to find the top of
- ; memory). (By "unset" we mean just comment out the line setting it!)
- ; Note that unsetting DOS doesn't remove all DOS-dependent code in
- ; the library. For example, the interrupt handler initialization
- ; uses INT 21h, and so does all I/O. Read the Embedded Applications
- ; section of the Programmer's Guide for more information about how
- ; to change those modules (source is generally provided).
- ; 5. SG_exists -- Set when IGC environment is possible.
- ; Unsetting it comments out code dependent on that environment only.
- ; 6. PL_exists -- Set when PharLap DOS|Extender environment is possible.
- ; Unsetting it comments out code dependent on that environment only.
- ; 7. NOWTK -- Set if either the Weitek 1167 will never be present
- ; -- or if you never care about it.
-
- ifdef WINDOWS
- ;no87 = 1 ; There can be no x87 processor.
- ;NOWTK = 1 ; There can be no Weitek processor.
- PL_weitek = 1 ; Windows uses a pharlap-style weitek setup.
- else
- ifdef ADS
- PL_exists = 1
- PL_weitek = 1
- else
- ifdef PADI
- PL_exists = 1
- PL_weitek = 1
- else
- SG_exists = 1
- PL_exists = 1
- PL_weitek = 1
- D4G_exists = 1
- AI_exists = 1
- endif ; PADI
- endif ; ADS
- endif ; WINDOWS
-
- DOS equ 1 ; Initializer intended for MS-DOS.
- ; no87 equ 1
-
- ; define HC if the initializer is to be for High C.
- HC equ 1
- ; Pascal is assumed otherwise.
-
- ; Now set expression-identifiers so I can say "if this and not that".
- ; E.g., "compute x" defines macro ex to be 1 ifdef x, 0 otherwise.
- compute macro id
- ifdef id
- e&id = not 0
- else
- e&id = 0
- endif
- endm
-
- compute HC ; HC instead of Prof. Pascal.
- compute WINDOWS
- compute PL_exists
- compute AI_exists
- compute SG_exists
- compute D4G_exists
- compute DOS
- compute USING_MASM_51
- compute USING_MASM_60
- compute USING_FLAT
- compute ADS
- compute PADI
-
- if eUSING_MASM_51 or eUSING_MASM_60
- USING_MASM EQU 1
- endif
-
- if eADS or ePADI
- ACAD EQU 1
- endif
-
- compute USING_MASM
-
- comment @
- Modified for AutoLISP and protected mode ADI
-
- Expects to be called at starting address as a subroutine, rather
- than as an executable program from the operating system. Stack
- and segment registers must be correctly set up; and some
- additional information is expected in these registers:
-
- ECX Compatibility-check value. Must be equal to (our
- locally defined symbol) chkval. If it isn't, we assume
- we are erroneously being executed as an independent
- separate program. This won't work, so we exit
- immediately to the system.
-
- DX:ESI Pointer to structure containing initialization information.
- A minimum structure size of 8 bytes is mandatory (12 bytes
- if PADI is set). The first 4 bytes of the structure must
- contain the number of bytes making up the structure. The
- second 4 bytes must contain the initial heapsize of the
- child process, obtained from the loader in AutoCAD. If
- PADI is set, the third 4 bytes must contain the physical
- address of the packet buffer in AutoCAD to be used for
- communication with protected mode ADI drivers. All subsequent
- bytes are the business between AutoCAD and the loaded child
- process and may vary.
-
- The value we return is the argument to exit() which terminates us.
- We preserve no registers, not even SS and SP.
-
- Some protected mode ADI, ADS, and AutoLISP modifications are
- conditioned on the tag ACAD.
-
- Some code for ADS only is included only if the tag ADS is
- predefined (e.g., in the assembler command line).
-
- Code required for AutoCAD protected mode ADI drivers only is included
- by setting PADI in the assembler command line.
- @
-
- minmem equ 4 ; Offset within the structure containing initialization
- ; information to the initial heap size of the child process.
-
- ifdef PADI
- physadr equ 8 ; Offset within the structure containing initialization
- ; information to the physical address of a buffer shared
- ; between AutoCAD and a protected mode ADI driver.
- endif ; PADI
-
-
- ;Memory Layout:
- ;
- ; High memory +---------------+
- ; | END OF MEMORY |
- ; |---------------|
- ; _heaphi -> | top-of-heap |
- ; | ... |
- ; _heaptop -> |- - - - - - - -| <- top of last user heap allocated
- ; | ... | (heaptop+1)..(heaphi) is available
- ; | bottom-of-heap|
- ; _TOP -> |---------------| <- Of size STACK_SIZE, unless there isn't
- ; | stack | <- room, in which case the first heap
- ; | ... | <- allocation will fail.
- ; | end-of-stack |
- ; _BASE -> +---------------+
- ; DATA segments (static variables and named common)
- ; Low memory CODE segments
- ; See the programmer's guide for more information and pictures of
- ; run-time organization with the different memory models.
- ; Stack margin1 is 512 bytes above the true end-of-stack.
- ; Stack margin2 is 256 bytes above the true end-of-stack.
- ; In non-large models, the stack margins go in a reserved area in the data
- ; segment, not in the stack segment. In the large model, since there is
- ; no single data segment, the stack margins go at the tail end of the stack
- ; (at ss:-2 and ss:-4).
- ;
- ; If stack overflow checking is enabled, here is the code that is generated:
- ; For procedures using 256 or less bytes in the stack:
- ; cmp esp,Stack_margin_1
- ; jnb around
- ; int 0
- ; around: ...
- ;
- ; Since Stack_margin_2 is 512 above true e-o-s, such procedures will always
- ; leave at least 256 bytes (512-256) left in the stack.
- ;
- ; For procedures that use more than 256 bytes:
- ; mov eax,esp
- ; sub eax,Stack_margin_2
- ; cmp eax,Amount_to_allocate
- ; jae around
- ; int 0
- ; around: ...
- ;
- ; Since Stack_margin1 is 256 from true end,
- ; such procedures will leave at least 256 bytes in the stack.
- ;
- ; Therefore, stack overflow occurs when less than 256 bytes would be
- ; left AFTER stack allocation.
- ; This permits the run-time environment to do some processing
- ; such as producing a trace or cleaning up.
-
- if eWINDOWS
- STACK_SIZE = 65536
- else
- ifdef ACAD
- STACK_SIZE = 4000h
- else
- STACK_SIZE = 8192
- endif
- endif
-
- ; Margin-big is used for small procedures -- it ensures a bigger margin.
- ; Margin-small is used for large procedures, since we do more accurate
- ; checking for them.
- Stack_margin_big equ 512 ;Free stack bytes before overflow occurs
- Stack_margin_small equ 256
- Stack_reserve equ 4 ;At top, for the above two numbers (large model).
- STDERR equ 2 ;standard error file handle
-
-
- if eWINDOWS
- ; stack comes first for windows
-
- if not eUSING_MASM
-
- ; Use dword alignment for stack segment in the future.
- STACKNAME equ ?STACK
- STACKNAME equ STACK
-
- STACKNAME segment dword stack 'STACK' ; of at least 80 bytes.
- ; Copyright message got moved out of here so that the stack wouldn't
- ; take up space in the .exe file.
- start_of_stack equ this byte
- db STACK_SIZE dup (?) ; The default stack of 8K.
- STACKNAME ends ; MS-DOS loader puts info at the tail end of the stack during loading.
-
- else ; eUSING_MASM
-
- ?STACK segment dword stack 'STACK' ; of at least 80 bytes.
- ; Copyright message got moved out of here so that the stack wouldn't
- ; take up space in the .exe file.
- start_of_stack equ this byte
- db STACK_SIZE dup (?) ; The default stack of 8K.
- ?STACK ends ; MS-DOS loader puts info at the tail end of the stack during loading.
-
- endif ; not eUSING_MASM
- endif ; eWINDOWS
-
- ;The following dummy segment instructs linker to put "code" lowest
- ;Must be made public since the main module also has public code,
- ;and some primitive linkers can't handle segments of the same name
- ;with different privacy attributes. (This does not include Phar Lap's linker.)
- CODE segment dword public 'CODE'
- CODE ends
-
- DATA segment dword public 'DATA'
- pubname stack_limit
- The_stack_margin equ this word
- def stack_limit,dd,0 ; Stack margins.
- dd 0
- DATA ends
-
- if not eWINDOWS
- ; stack comes last if not windows
-
- if not eUSING_MASM
-
- ; Use dword alignment for stack segment in the future.
- STACKNAME equ ?STACK
-
- STACKNAME segment dword stack 'STACK' ; of at least 80 bytes.
- ; Copyright message got moved out of here so that the stack wouldn't
- ; take up space in the .exe file.
- start_of_stack equ this byte
- db STACK_SIZE dup (?) ; The default stack of 8K.
- STACKNAME ends ; MS-DOS loader puts info at the tail end of the stack during loading.
-
- else ; Handle MASM inadequacies.
-
- ?STACK segment dword stack 'STACK' ; of at least 80 bytes.
- ; Copyright message got moved out of here so that the stack wouldn't
- ; take up space in the .exe file.
- start_of_stack equ this byte
- db STACK_SIZE dup (?) ; The default stack of 8K.
- ?STACK ends ; MS-DOS loader puts info at the tail end of the stack during loading.
-
- endif ; not eUSING_MASM
- endif ; not eWINDOWS
-
- ; Line terminator convention.
-
- _MWLTCONV segment common dword 'DATA'
- ; This must be a MetaWare Pascal string: 2 bytes for the length,
- ; then the actual string characters follow.
- ; Even if the string is of length one, leave the length of this
- ; segment at 8 bytes. (leave lt2 present even if not used.)
- ; Line termination convention for input:
- ltconv_in dw 2 ; length is 2 for line terminator.
- lt1i db 13 ; CR
- lt2i db 10 ; LF
- ; Line termination convention for output; may be of any length:
- ltconv_out dw 2 ; length is 2 for line terminator.
- lt1o db 13 ; CR
- lt2o db 10 ; LF
- _MWLTCONV ends
-
- PUBLIC __mwdfc, __mwdlc
- ifdef HC
- _MWIFC segment public word 'DATA'
- if eUSING_MASM_51
- assume cs:_MWIFC ; hushes up MASM 5.1 errors
- endif
- __mwifc label near
- _MWIFC ends
- _MWIMC segment public word 'DATA'
- _MWIMC ends
- _MWILC segment public word 'DATA'
- if eUSING_MASM_51
- assume cs:_MWILC ; hushes up MASM 5.1 errors
- endif
- __mwilc label near
- _MWILC ends
-
- _MWDFC segment public word 'DATA'
- if eUSING_MASM_51
- assume cs:_MWDFC ; hushes up MASM 5.1 errors
- endif
- __mwdfc label near
- _MWDFC ends
-
- _MWDMC segment public word 'DATA'
- _MWDMC ends
-
- _MWDLC segment public word 'DATA'
- if eUSING_MASM_51
- assume cs:_MWDLC ; hushes up MASM 5.1 errors
- endif
- __mwdlc label near
- _MWDLC ends
-
- ; the following for use in windows's adk destructor, previously conflict
- ; with C++ destructor.
- if eWINDOWS
- PUBLIC __mwdfw, __mwdlw
- _MWDFW segment public word 'DATA'
- if eUSING_MASM_51
- assume cs:_MWDFW ; hushes up MASM 5.1 errors
- endif
- __mwdfw label near
- _MWDFW ends
- _MWDMW segment public word 'DATA'
- _MWDMW ends
- _MWDLW segment public word 'DATA'
- if eUSING_MASM_51
- assume cs:_MWDLW ; hushes up MASM 5.1 errors
- endif
- __mwdlw label near
- _MWDLW ends
- endif
-
- endif
-
- ; Define input and output descriptors
-
- DSEG segment dword 'DATA'
- ; These are for Pascal but must be provided in C if we link in
- ; the C initializer with Pascal routines.
- pubnames <input,output>
- pubnames <es,is_286,envp,8087,387,1167>
- pubnames <argp,arglen,prognamep>
- pubnames <CPU,OS,env,wind,printnochipmsg,init_ver>
- pubnames <emc87,heap_expansion_enabled>
- extrn _osmajor:byte,_osminor:byte
- ifdef HC
- pubname argvp
- endif
- ; Pascal file variables Input and Output. They are initialized in Pascal's Finit.p.
- defequ input,dw,0
- defequ output,dw,1
-
- ; Initialize the "host" package that identifies the system we're running on.
- ; See the interface file Host.pf distributed with Professional Pascal or High C
- ; for the enumerated type declaration for the values of CPU and OS.
- defequ CPU,db,8 ;Indicates 386.
- defequ OS,db,0 ;Indicates MSDOS.
-
- _psp equ this byte
- def es,df,0 ;The contents of es prior to invoking program
- ; df is Microsoft's way of saying 48-bit pointer;
- ; Phar Lap uses dp or df.
- escontents equ _psp ; Program segment prefix pointer.
- ifdef STACK_SIZE
- public _top,_base,_psp
- _top dd 0 ; Top of stack (relative to SS).
- _base dd 0 ; Base of stack (relative to DS).
- _heaphi dd 0 ; offset to top of heap
- _heaptop dd 0 ; offset to top of previous heap
- ; (heaptop+1)..(heaphi) is available
- _totsiz dd 0 ; temp work area
- osver dd ?
-
- ifdef SG_exists
- public _gda
- _gda dd 0 ; Address of gda (softguard only)
- endif
-
- endif
- defequ argp,df,? ;Pointer to command arguments
- ifdef HC
- defequ argvp,df,? ; Address of argv array for C.
- endif
-
- even
- if eWINDOWS
- pubname is_p
- if not eHC
- defequ is_p,db,1 ; Is the RTE Pascal or C? Affects whether
- else
- defequ is_p,db,0 ; low-level interface clears errno.
- endif
- endif
- defequ arglen,DD,? ;Length of command argument string
- defequ envp,df,0 ;Pointer to environment string
- defequ is_286,db,0 ;True if this is a 286.
- _8087 equ this word ; Need word to store control word into.
- def 8087,dw,0 ;Set to true if 8087 is present
- temp dw 0
- _387 equ this word ; Need word to store control word into.
- def 387,dw,0 ;Set to true if 80387 is present.
- _1167 equ this word
- def 1167,dw,0 ; True if 1167 is present.
- _emc87 equ this word
- def emc87,dw,0 ; Set to true if emc87 is present.
- Null_pname db 0 ; Null prog name for < DOS 3.0.
- ; Prognamep is initialized to a 32-bit pointer to a 0-byte in case
- ; we can't obtain the program name.
- defequ prognamep,dd,Null_pname ;Pointer to program name
- prognamep_seg dw 0
- SG_ENV = 1
- PL_ENV = 2
- AI_ENV = 3
- SSI_ENV= 4
- D4G_ENV= 5
- defequ env,db,0 ; Which environment are we in? SG/PL/AI?
- defequ wind,db,0 ; Are we running under windows?
- defequ printnochipmsg,db,0 ; Are we running under windows?
- defequ init_ver,db,1 ; Which version of init is this? (1==LOC, 2==GOC)
- Lahey_format_load_file db 0 ; .plx (Phar-Lap linked) by default.
- CANT_EXPAND = 0
- CAN_EXPAND = 1
-
- if eWINDOWS
- defequ heap_expansion_enabled,db,CANT_EXPAND
- else
- defequ heap_expansion_enabled,db,CAN_EXPAND
- endif
-
- PSPseg dw 24h ; Pointer to DOS's Program segment prefix: Phar Lap.
- ENVseg dw 2ch ; Pointer to DOS's environment string: Phar Lap.
-
- ifdef ACAD
- chkval equ 1234 ; magic interface-compatibility code
- ifdef ADS ; Avoid excess globals for ADS
- info_off equ ads_info_off
- info_sel equ ads_info_sel
- else
- public brkflg,stkflg
- endif ; ADS
- public info_off,info_sel
- ifdef PADI
- public cbufadr
- cbufadr dd 0 ; ptr to common pg between ACAD & PADI
- phys_adr dd 0 ; physical address of common page
- endif ; PADI
- brkflg dd 0 ; set nonzero for Control C
- stkflg dd 0 ; set nonzero for stack overflow
- interr db "Incompatible program interface",0Dh,0Ah,"$"
- rtnaddr df 0 ; Caller's return address.
- info_off dd 0 ; Offset of initialization info struct
- info_sel dw 0 ; Selector of initialization info struct
- min_mem dd 0 ; initial driver heap size
- endif ; ACAD
-
- DSEG ends
- envptr equ 2CH ;Offset in DOS ctrl block where env address is located
- ;
- if eDOS
- if eWINDOWS
- DGROUP group DATA,DSEG,_MWLTCONV,_MWIFC,_MWIMC,_MWILC,_MWDFC,_MWDMC,_MWDLC,_MW87_USED1,_MW387_USED1,_MW1167_USED1
- DGROUP group DATA,_MWDFW,_MWDMW,_MWDLW
- else
- if eUSING_MASM
- DGROUP group DATA,DSEG,_MWLTCONV,_MWIFC,_MWIMC,_MWILC,_MWDFC,_MWDMC,_MWDLC,_MW87_USED1,_MW387_USED1,_MW1167_USED1,?STACK
- else
- DGROUP group DATA,DSEG,_MWLTCONV,_MWIFC,_MWIMC,_MWILC,_MWDFC,_MWDMC,_MWDLC,_MW87_USED1,_MW387_USED1,_MW1167_USED1,STACKNAME
- endif
- endif
- else
- DGROUP group DATA,DSEG,_MWIFC,_MWIMC,_MWILC,_MWDFC,_MWDMC,_MWDLC,_MWLTCONV,STACKNAME
- endif
-
- assume_dgroup macro
- if eUSING_FLAT
- assume ds:FLAT
- else
- assume ds:DGROUP
- endif
- endm
-
- ?INIT segment dword 'CODE'
- if not eUSING_FLAT
- CGROUP group ?INIT,CODE
- assume cs:CGROUP
- else
- FLAT group ?INIT,CODE
- assume cs:FLAT
- endif
-
- ; Extern procs must be defined within current code segment for
- ; correct relocation bits to be generated.
- extrn _mwfinit:near
- ; Phar lap assembler won't take next line; it plays according to the rules (as opposed to Microsoft's assembler):
- ;extequ finit,near ;Pascal file system initialization.
- extequ cfinit,near ;C file system initialization.
- extequ halt,near ; Halt intrinsic.
- ifdef HC
- extrn main:near ; Main program entry point
- extequ set_up_args,near ; Routine to compute argv pointers.
- else
- extequ main,near ;Main program entry point
- ;extequ init_interrupts,near ; initialize interrupt handling.
- endif
-
- ifdef ACAD
- ifdef ADS
- getinitinfo equ adsi_getinitinfo
- map_phys_mem equ ads_map_phys_mem
- endif ; ADS
- ifndef PADI
- extrn getinitinfo:near ; initialize child process loaded by AutoCAD
- endif ; !PADI
- extrn map_phys_mem:near ; allows 3rd party to install a routine to map
- ; physical memory between the stack and heap
- endif ; ACAD
-
- ; Where are the stack margins defined? Top of stack or in data segment?
- if not eUSING_FLAT
- Stack_margin_big_place equ dword ptr DGROUP:The_stack_margin
- Stack_margin_small_place equ dword ptr DGROUP:The_stack_margin+Word_size
- else
- Stack_margin_big_place equ dword ptr The_stack_margin
- Stack_margin_small_place equ dword ptr The_stack_margin+Word_size
- endif
- ;
- ; DOS|Extender environment discovery code obtained from Phar Lap:
-
- ;**************************************************************************
- ;* Here begins the execution of a Professional Pascal or High C program. *
- ;**************************************************************************
-
- INIT PROC FAR
- publab INIT ; Compiler generates this in upper case.
- genesis:
- assume_dgroup
-
- jmp short Discover_environment
-
- ; We jump to the rest of the initialization and jump back so that
- ; when debugging we can easily see the call to main as the first call.
-
- Init_return:
-
- ifdef ACAD
- ifndef PADI
- Comment @
- Take information from a structure in AutoCAD, pointed to by
- info_sel:info_off, and store it for use by routines in the
- program loaded by AutoCAD to which this module is linked.
- @
- movsx eax,word ptr info_sel
- push eax
- push info_off
- call getinitinfo
- add esp,8
- endif
- endif
-
- ; In C, Argc/Argv values have been pushed on the stack by the time we get here.
-
- pcall main ;call main program
- ; compiler generates defn of MAIN
- ; in a main program.
- Quit:
- ; In C, return the value returned by main to the system.
- ; In Pascal, return 0. To return a value in Pascal, use Halt(retcode).
- ifndef HC
- sub eax,eax
- endif
- push eax
- pcall halt
- ifdef SG_exists
- ; Next 2 lines TEMPORARY for IGC only.
- xor eax,eax ; We shouldn't get here.
- call _mwint21
- endif
- ifndef HC
- ; Supply a dummy version of "call_onexit_fcns" for Pascal.
- ; Cost: 1 byte here & 3 or 5 bytes for the call in term.p.
- ; Benefits: term.p is the same for Pascal and C.
- publab call_onexit_fcns
- return
- endif
- publab restore_interrupts ; For now, don't bother w/^C.
- return
-
- ifdef ACAD
- comment @
- For applications which are called as a subroutine from AutoCAD
- (namely AutoLISP), here is the ultimate exit point which returns
- back to AutoCAD.
- @
- ifndef ADS ; Take care with public names in ADS
- public exit_to_acad
- endif
- exit_to_acad:
- jmp rtnaddr ; Return to AutoCAD
- endif ; ACAD
-
-
- ifdef HC
- db 'High C'
- else
- db 'Professional Pascal'
- endif
- db ' Run-time Library Copyright (C) 1983-1990 MetaWare Incorporated.'
-
- Discover_environment:
-
- ifdef ACAD
- cmp ecx,chkval ; Proper chkval argument?
- je m00
- mov edx,offset interr ; "Incompatible program interface"
- mov ah,9
- int 21h ; Print the message.
- mov ax,4C01h
- int 21h ; Exit to DOS.
- m00:
- mov info_off,esi ; offset of initialization info struct
- mov info_sel,dx ; selector of info struct
- mov es,dx
- mov eax,es:[esi].minmem
- mov min_mem,eax ; initial heap size of driver
- ifdef PADI
- mov eax,es:[esi].physadr
- mov phys_adr,eax ; phys addr of pg w/ PADI packet buffer
- endif ; PADI
- mov ax,ds
- mov es,ax
- pop dword ptr rtnaddr ; Save return address, offset
- pop ax
- mov word ptr rtnaddr+4,ax ; and segment.
- endif ; ACAD
-
- ; default assumptions
- if eWINDOWS
- mov env,SSI_ENV
- else
- if ePL_exists
-
- ; determine OS version
- call init_const
-
- mov env,PL_ENV
- endif
-
- ; DOS|Extender environment discovery code obtained from Phar Lap:
- if eSG_exists
- ; IGC: eax = abcdabcd. Also, code segment is privilege level 3
- ; (= 43 hex).
- cmp al,0cdh ; eax = abcdabcd for IGC.
- jne short not_sg
- cmp ah,0abh
- jne short not_sg
- ; Flaw: If we are in non-protected mode and get this far,
- ; the cmp eax will have 16 bits too much constant, and will
- ; cause the initializer to bomb. It is unlikely that ax=abcd
- ; yet eax <> abcdabcd. --fixed with shift sequence.
- ;;; cmp eax,0abcdabcdh ; Now try 386 instruction.
- shr eax,8
- cmp ah,0cdh
- jne short not_sg
- shr eax,8
- cmp ah,0abh
- jne short not_sg
- mov env,SG_ENV
- mov _gda,edx
- jmp short Initialize_everything
- not_sg:
- endif ; SG_exists
-
- if eD4G_exists
- ; Magic code to figure out if this is Rational's 32-bit DOS extender.
-
- ; jmp force_rational
- mov dx,78h
- mov ax,0ff00h
- call _mwint21
- cmp eax, 4734ffffh ; 4G
- jne short not_d4g
-
- force_rational:
- mov env,D4G_ENV
- mov ax, es
- mov PSPseg, ax
- mov bx,2Ch
- mov ax,es:[bx]
- mov ENVseg, ax
- not_d4g:
- endif ; D4G_exists
-
- if eAI_exists
- cmp env,D4G_ENV
- je short not_ai
- cmp env,SSI_ENV
- je short not_ai
- mov eax,osver
- shr eax,16
- cmp ax,'DX'
- je short not_ai
- mov env,AI_ENV
- not_ai:
- endif ; AI_exists
- endif ; eWINDOWS
-
- ifdef WINDOWS
- ; Incoming registers:
- ; esi: initial amount of heap provided by loader, at tail end of DGROUP.
- ; ebx: pointer to argument strings.
- ; edi: pointer to program name.
- ; environ:
- ; ax:0:
- ; (db 'var=value',0)*
- ; (db 0)+ ; possibly some 0 padding for expansion later
- ; ax:edi:
- ; db 'progname',0 ; fully-expanded (drive & path)
- ; ax:ebx:
- ; db 'invoke name',0 ; the invocation prog name.
- ; db 'arguments',0 ; 1 or more arguments.
- ; db 0
- ; handle-table:
- ; dd count
- ; (db type, dd handle)*
- ; type = 0 unused; 1 session; 2 file.
-
- mov wind,1 ; Set the flag to say we are under windows
-
- mov word ptr envp+Word_size,ax ; Offset is already 0.
- ; mov envp,0 ; This is already 0.
-
- mov word ptr argp+Word_size,ax ; Offset of arguments.
- mov dword ptr argp,ebx ; Will be adjusted to skip prog name later.
-
- mov word ptr prognamep+Word_size,ax
- mov dword ptr prognamep,edi ; Save prog name offset.
-
- ; initialize heap
- mov _base,0
- mov ax,ds
- lsl eax,eax ; Find total space.
- mov _heaphi,eax ; End of heap.
-
- mov _top,esi ; heap starts here
- mov eax,esi
- inc eax ; increase size to page boundary
- add eax,4095
- and eax,0fffff000h
- dec eax
- mov _heaptop,eax ; and this is where heap really starts
- endif ; WINDOWS
-
- L1:
-
- ;INIT: Initialization code
- ; - set initial stackpointer, framepointer
- ; - calls FINIT and CFINIT to initialize file support
- ; - call MAIN to invoke user's program
- ; - call FTERM to close all open files
- ;
- ; Unneeded defn of DGROUP, since DS is fixed.
- ;dsgroup dw DGROUP
-
- ; Shorter than mov reg,-1
- getminus1 macro reg
- sub reg,reg
- dec reg
- endm
-
- ifdef HC
- Small_data_HC = 1
- endif
- SETBLOCK equ 4Ah
-
- Initialize_everything:
- sub ebp,ebp ;Initialize stack frame pointer
- ; Make sure stack is mod 4 in case it's not.
- and esp,0fffffffch ; Drop extra bytes. Oh well.
- assume_dgroup
-
- ; For the 386 we own all of memory. Size up memory and inform the
- ; heap manager.
-
- mov Stack_margin_big_place,Stack_margin_big
- mov Stack_margin_small_place,Stack_margin_small
- add Stack_margin_big_place,offset start_of_stack
- add Stack_margin_small_place,offset start_of_stack
-
- ifdef SG_exists
- cmp env,SG_ENV
- jne short next1
- ; Initialize stack, IGC environemnt.
- ; This code will work for h (highest) and a (append after load) stk options.
- ; esp already setup by vmrun loader.
- mov eax,esp ;get stack pointer
- mov ecx,[edx].GDA_STKSZ ;get stack size, kbytes
- shl ecx,10 ;convert from k to # of bytes
- sub eax,ecx ;calculate base of stack addr
- mov _base,eax ; stack base
- mov eax,[edx].GDA_HLOD ;get highest load address
- mov _top,eax ; top of stack
- inc eax ; increase size to page boundary
- add eax,4095
- and eax,0fffff000h
- dec eax
- mov _heaptop,eax ; previous top of heap
-
- mov ecx,[edx].GDA_HMEM ;get available high memory
- shl ecx,10 ;convert from k to # of bytes
- dec ecx
- add eax,ecx ;calculate heap top addr
- mov _heaphi,eax ;top of heap
- ; Free memory below 640K for subsequent use by EXEC.
- mov ebx,[edx].GDA_TLOW ; Subtract highest used low address.
- sub ebx,[edx].GDA_PSPA ; Subtract lowest used low address.
- shr ebx,4 ; Convert to paragraphs.
- inc ebx ; Safety?
- mov ah,SETBLOCK ; SETBLOCK to bx paragraphs from psp start.
- call _mwint21
- test byte ptr [edx].GDA_ENV,GDA_WEITEK
- setne byte ptr _1167
- next1:
- endif
- if ePL_exists or eAI_exists
- cmp env,PL_ENV
- je next2a
- cmp env,AI_ENV
- je next2a
- jmp next2
- next2a:
- mov _base,0 ; Start of stack.
- lea eax,32[esp] ; eax = start of heap + some padding for safety.
- mov _top,eax
- inc eax ; increase size to page boundary
- add eax,4095
- and eax,0fffff000h
- dec eax
- mov _heaptop,eax ; end of previous heap
-
- mov ax,ds
- lsl eax,eax ; load segment limit of data segment.
- mov _heaphi,eax ; Top of heap (linear address).
- next2:
- endif
-
- ;*******************************************************************************
- ; Remainder of initialization, independent of where stack lies.
- ;*******************************************************************************
-
- ;*******************************************************************************
- ; Deal with 8087/287
- ; Discover whether 8087/287 exists unless no8087 has been set.
- ;*******************************************************************************
-
- ifdef no87
- mov byte ptr _8087,0
- else
-
- ; Initialize floating point: check for existence of 8087/287.
- ; We have to do this here so that we can avoid printing out the contents
- ; of NO87 if the machine doesn't have an 8087.
- fninit ;initialize 8087 if one exists
- xor eax,eax ;Initialize 8087 flag to zero.
- mov temp,ax
- sub ecx,ecx ; One byte shorter than mov ecx,15.
- mov cl,15
- ; mov ecx,15 ; Set ch := 0 on first try.
- waste1: loop waste1
- fnstcw temp ; Store cntl word
- ; We used to just test for non-zero on 8087 systems; but that
- ; didn't work for 287s. Even if no 287, IBM ATs returned
- ; garbage as the control word.
- mov cl,15
- waste2: loop waste2
- and temp,00f3fh
- cmp temp,0033fh ; Processor status after initialization.
- jne short no_8087
- fnstsw temp
- mov cl,15
- waste3: loop waste3
- test temp,0b8bfh
- jnz short no_8087
- fldcw cs:fp_init_cw_emc ;load control word
- ; EMC 87 will leave on the upper bit in the control word:
- fstcw temp
- test byte ptr temp+1,80h ; EMC part there?
- jz short not_EMC
- mov byte ptr _387,1 ; EMC also looks like a 387.
- ; We load the normal control word in case someone else stores
- ; it and expects the top bit to be off.
- fldcw cs:fp_init_cw ;load normal control word
- mov byte ptr _emc87,1 ;Say that it's present.
- ; Now fall through to the code that will determine it's also a 387 clone.
- not_EMC:
- mov byte ptr _8087,1 ;Set to TRUE unless he requested to ignore the chip.
- fld1
- fldz
- fdiv ; get infinity
- fld st ; Duplicate TOS.
- fchs
- fcompp ; compare negative infinity with infinity.
- fstsw ax
- fwait
- sahf
- je short no_8087 ; 387 says -inf <> +inf. 87/287 says they're equal.
- mov byte ptr _387,1
- no_8087:
- endif ; no87
-
- ifndef NOWTK
- ifdef DOS
- ;*******************************************************************************
- ; Deal with Weitek 1167
- ; Pharlap uses fs:; IGC uses ffc0_0000.
- ; AIA with PharLap linker uses fs:
- ; AIA with Lahey linker uses selector F8h we must load fs explicitly.
- ;*******************************************************************************
-
- ; Early versions of the emc87 will hang if given weitek code.
- cmp byte ptr _emc87,1
- je Skip_all_weitek_processing
- ; No weitek with DOS4G
- cmp env,D4G_ENV
- je Skip_all_weitek_processing
- seg_ldctx macro
- ;pop fs:[0c000h]
- ; Until the assembler will allow address mode override, inline code a 1-byte-shorter move:
- db 67h,64h,8fh,06h,00,0c0h
- endm
- seg_stctx macro
- db 67h,64h,0a1h,00h,0c4h ; store context to eax.
- endm
- flat_ldctx macro
- pop ds:[0ffc0c000h]
- endm
- flat_stctx macro
- pop ds:[0ffc0c400h]
- endm
-
- ; For windows, we have to look for the chip, and set up fs if
- ; it is there. A selector value for fs is put at ss:0 by the
- ; windows startup code. We just move this selector into fs.
- cmp _mwwind,1
- jne start_test
- int 11h ; get bios equipment list
- and eax,01000000h ; bit 24 set if weitek exists
- jz Skip_all_weitek_processing
- mov fs,ss:0
-
- start_test:
-
- push 03ff0000h ; truncate (1ff = round to nearest).
- push 30000000h ;
- push 0a0000000h ; 1165 accum timer
- push 64000000h ; 1164 accum timer
- push 16000000h ; 1164/1165 flowthrough timer, 16 mhz
- push 98000000h ; 20 mhz part init
- push 56000000h ; 20 mhz part
- push 0b8000000h ; test speed of chip.
-
- ; ldctx 1600_0000 1164/1165 flowthrough timer.
- ; ldctx 6400_0000 1164 accumulate timer.
- ; ldctx a000_0000 1165 accumulate timer.
- ; ldctx 3000_0000 reserved mode bits.
- ; ldctx 01ff_0000 rounding modes/exception mask.
- ifdef SG_exists
- cmp env,SG_ENV
- jne short next3
- cmp byte ptr _1167,1
- jne No_weitek
- flat_ldctx ; for test.
- flat_stctx ; store context to eax.
- and ah,80h
- jnz short _20MHZ_part_flat
- pop eax ; Delete 20 mhz init stuff.
- pop eax
- flat_ldctx
- jmp short common_1167_flat
- _20MHZ_part_flat:
- flat_ldctx
- flat_ldctx
- pop eax ; Kill the 16 mhz init.
- common_1167_flat:
- flat_ldctx
- flat_ldctx
- flat_ldctx
- flat_ldctx
- flat_ldctx
- next3:
- endif ; SG_exists
-
- ifdef PL_weitek
- ; Check that fs <> ds. If so, Weitek installed at fs:.
- cmp env,PL_ENV
- je start_wtk
- cmp env,AI_ENV
- je start_wtk
- cmp wind,1
- je start_wtk
- add esp,8*4 ; Get rid of the junk.
- jmp next4
- start_wtk:
- mov ax,fs
- mov bx,ds
- cmp ax,bx
- je short NW1
- and ax,ax ; If fs = 0 this was linked with Lahey linker.
- sete Lahey_format_load_file
- jne short go_ahead; if this isn't Lahey we are already (fs = weitek)
- mov ax, 0F8h ; test the f8 selector to see if it exists
- lar bx, ax
- jnz short NW1 ; if no then OS386 does not find a Weitek
- test bh, 80h
- jz short NW1 ; if f8 exists but present bit is not set
- ; os386 does not find weitek
- mov fs, ax
- go_ahead:
- mov _1167,1
- ; Until the assembler will allow address mode override, inline code a 1-byte-shorter move:
- seg_ldctx ; load ctx b8_000_000
- seg_stctx ; store context to eax.
- and ah,80h
- jnz short _20MHZ_part
- pop eax ; Delete 20 mhz init stuff.
- pop eax
- seg_ldctx
- jmp short common_1167
- NW1: jmp short No_weitek
- _20MHZ_part:
- seg_ldctx
- seg_ldctx
- pop eax ; Kill the 16 mhz init.
- common_1167:
- seg_ldctx
- seg_ldctx
- seg_ldctx
- seg_ldctx
- next4:
- endif ; PL_weitek
- jmp Finish_weitek
- No_weitek:
- add esp,8*4 ; Get rid of the junk.
-
- Skip_all_weitek_processing:
- Finish_weitek:
-
- endif ; DOS
- endif ; NOWTK
-
- ifdef DOS
- ;*******************************************************************************
- ; Process environment area and parameter strings.
- ;*******************************************************************************
- Parm_string_offset = 80h ; Offset in PSP containing parm string (len+bytes).
- ifdef SG_exists
-
- cmp env,SG_ENV
- jne short PL_PSP
- ; GDA has pointer to PSP. PSP has env seg, which, shifted left by 4,
- ; yields the 32 bit address of the env.
- cld ;All moves are forward
- mov edi,[edx].GDA_PSPA ; Get flat PSP address.
- mov word ptr argp+Word_size,ds
- mov dword ptr _psp,edi
- mov word ptr _psp+Word_size,ds
- lea eax,Parm_string_offset[edi] ; eax = pso+edi.
- xor ebx,ebx
- mov bl,[eax] ; Get length of parm string.
- mov arglen,ebx
- inc eax
- mov dword ptr argp,eax ; Addr of parm string.
- mov bx,envptr[edi] ; Get segment address of environment pointer.
- shl ebx,4 ; Convert to 32-bit flat address.
- mov dword ptr envp,ebx
- mov word ptr envp+Word_size,ds ; Fill out 48-bit address
- jmp more_init2
- PL_PSP:
- endif
-
- if ePL_exists or eD4G_exists or eAI_exists
- cmp env,PL_ENV
- je short next5a
- cmp env,AI_ENV
- je short next5a
- cmp env,D4G_ENV
- jne next5
- next5a:
- cmp Lahey_format_load_file,1
- je short ES_points_to_PSP_already
- mov ax,PSPseg
- mov bx,cs
- arpl ax,bx
- mov es,ax ;Load es with psp address.
-
- ; Load environment segment into cx.
- mov cx,ENVseg
- arpl cx,bx
- jmp short more
-
- ES_points_to_PSP_already:
- ; Load environment segment into cx.
- mov cx,es:02ch
- mov ax,es
- more:
- mov word ptr _psp+Word_size,ax ; Construct 48-bit psp address.
- mov word ptr escontents+Word_size,ax ;No displacement
- mov word ptr envp+Word_size,cx ; Environment segment.
- xor eax,eax
- mov al,es:Parm_string_offset ;Length of parm string
- mov arglen,eax
- mov esi,Parm_string_offset+1
-
- ; In C, the parameter string must be moved to a DS-accessible area
- ; if small-data model.
- ifdef HC
- ; Move the parm string into the stack so that it can be accessed by
- ; small-data programs with only 16-bit pointers.
- add eax,3
- and al,0fch ; Make sure eax is multiple of 4.
- sub esp,eax ; Length of parm string.
- mov edi,esp ; Move the parameter string here.
- mov dword ptr argp,edi ; Save address of args.
- push edx ; Allow byte for parm string overwrite by C arg processor.
- ; but make stack word-aligned for efficiency.
- mov ecx,eax ; parameter length
- push ds ; Save it.
- push es ; source is es:esi
- pop ds
- push es ; Save es.
- push ss
- pop es ; Dest is ss:di.
- ; mov esi,Parm_string_offset+1 ; Set up earlier.
- rep movsb ; es:di := parm string.
- pop es
- pop ds
- else ; not eHC
- ; Large-data or Pascal model; just store the address of the parms.
- mov ax,word ptr escontents+Word_size
- mov word ptr argp+Word_size,ax
- mov dword ptr argp,Parm_string_offset+1 ; Addr of parm string.
- endif ; eHC
- next5:
- endif ; ePL_exists
-
- more_init2:
-
- if not eWINDOWS
- cmp env,D4G_ENV ; One doesn't shrink the heap in DOS4G.
- jne short not_D4G2
-
- mov eax,_top
- mov _heaptop,eax ; previous top of heap
- mov _heaphi,eax ; top of heap (empty)
- jmp no_change
-
- not_D4G2:
-
- if ePL_exists
- cmp env,PL_ENV
- jne next6
- ifndef PHAR_LAP_CAN_GROW_HEAP
- jmp short no_change
- else
- ; Now free all of the heap, so that we allocate more only when necessary.
- ifdef ACAD
-
- ifdef PADI
- mov ebx,_top ; Get top of stack
- add ebx,4095 ; Round it up a page
- shr ebx,12 ; Get number of pages
- push ebx ; Store for later use
- push ds
- pop es
- mov ah,SETBLOCK ; Set PADI memory size to smallest #
- int 21h ; of pages ecompassing top of stack
-
- mov ebx,phys_adr ; Get phys addr of pg w/ packet buffer
- mov eax,250Ah
- mov ecx,1
- int 21h ; Map pg w/ pkt buf to end of new PADI
- ; memory block, above top of stack
- mov cbufadr,eax ; Store mapped offset as ptr to buf
-
- call map_phys_mem ; allow 3rd party a chance to map in
- ; phys mem (returns # of pgs mapped)
- pop ebx ; Get # of pgs to top of stack
- inc ebx ; Add 1 for page mapped to end of seg
- add ebx,eax ; Add add'l pgs mapped by 3rd party
- shl ebx,12 ; Get bottom of heap, in bytes
- dec ebx
- mov _heaptop,ebx
- and ebx, 0fffffffch
- mov _top,ebx ; Assumption made _top is heap bottom
- else ; PADI
- mov ebx,_top ; Get top of stack
- add ebx,4095 ; Round it up a page
- shr ebx,12 ; Get number of pages
- push ebx ; Store for later use
- push ds
- pop es
- mov ah,SETBLOCK ; Set memory size to smallest #
- int 21h ; of pages ecompassing top of stack
-
- call map_phys_mem ; Allow 3rd party a chance to map in
- ; phys mem (returns # of pgs mapped)
- pop ebx ; Get # of pgs to top of stack
- or eax,eax ; Any pages mapped?
- jz no_map
- add ebx,eax ; If so, add it in
- shl ebx,12 ; Get bottom of heap, in bytes
- dec ebx
- mov _heaptop,ebx
- and ebx, 0fffffffch
- mov _top,ebx ; Assumption made _top is heap bottom
- no_map:
- endif ; PADI
-
- mov ebx,min_mem ; Initial size of heap
- else ; ACAD
- mov ax,4
- mov es,ax
- mov ebx,es:[5ch] ; Initial size of heap: load image size in bytes.
- endif ; ACAD
- ; See Phar Lap TN #21.
- jmp short Free_up
- endif
- next6:
- endif ; PL_exists
-
- if eAI_exists
- cmp env,AI_ENV
- jne short next7
- mov ebx,_top ;top of stack in bytes
- ifndef AIA_CAN_GROW_HEAP
- cmp Lahey_format_load_file,1
- jne short no_change
- ; If Lahey format, we must be able to grow.
- endif
- next7:
- endif ; AI_exists
-
- if ePL_exists or eAI_exists
- Free_up:
- add ebx,4095 ; Round up to pages.
- shr ebx,12 ; Convert to 4K pages.
-
- ifdef ACAD
- ifdef PADI
- ; Initial heap size, set up in min_mem above with a minimum
- ; heap value that comes from the loader in AutoCAD, does not
- ; account for the extra page added on as a result of the page
- ; mapping done above to obtain access to a buffer common with
- ; AutoCAD. Therefore, the number of pages for the initial
- ; heap size is increased by one.
-
- inc ebx
-
- endif ; PADI
-
- ; Any additional pages mapped onto the segment as a result of
- ; calling map_phys_mem() above is added here.
-
- add ebx,eax ; Add add'l pgs mapped by 3rd party
- endif ; ACAD
-
- inc ebx ; Add 1 page for initial heap.
-
- mov edx,ebx ; compute heaphi
- shl edx,12
- dec edx
-
- cmp env,PL_ENV
- je short No_para
- shl ebx, 8 ; Convert pages to paragraphs for AIA.
- cmp Lahey_format_load_file,1
- jne short No_para ; if AI_ENV and PL linker skip to allocation
- ; else must be AI_ENV and Lahey Linker so
- ; we must grow the parent segment first
- ; call grow_parent_segment
- No_para:
- push ds
- pop es ; Segment to free up.
- mov ah,SETBLOCK ; SETBLOCK to bx paragraphs from psp start.
- int 21h
- jc short no_change ; If couldn't get the extra page, oops!
- mov _heaphi,edx
- no_change:
- endif ; PL_exists or AI_exists
-
- doesnt_want_8087 macro
- ; All this fuss just to print the NO87 string!
- ifndef no87
- push eax
- push edi ; We're going to clobber these.
- cmp _8087,0
- je short no_print; No 87 exists on this machine; don't bother to print.
- cmp wind,1
- je short no_print
- mov _8087,0 ; Set false.
- add edi,5
- mov esi,edi ; Copy for later.
- mov al,' '
- repe scasb
- dec edi
- cmp byte ptr es:[edi],0 ; Did we get to end of string?
- je short no_print
- mov edi,esi ; Now print the message, one character at a time.
- again: mov dl,es:[edi]
- and dl,dl
- je short end_of_string
- mov ah,6 ; Direct Console I/O.
- call _mwint21 ; Print character.
- inc edi
- jmp again
- end_of_string:
- mov dl,0dh ; \r\n.
- mov ah,6
- call _mwint21 ; Print character.
- mov dl,0ah
- mov ah,6
- call _mwint21 ; Print character.
- no_print:
- pop edi
- pop eax
- endif ; no87
- endm
-
- Find_prog_name:
- ; -- Format of DOS environment: VVV 3.x only VVV
- ; -- t1 nul t2 nul t3 nul ... tn nul nul x x program-name nul
- ; Go to end of environment string to get program name for DOS 3.0.
- ; While we're doing so, see if he said "NO87=" something, in which case,
- ; mimicking Microsoft's emulator, we print the string (unless it's
- ; nothing but blanks), and disable use
- ; of the 80287 if the combination emulation/80287 library is linked in.
- les edi,envp ; Pointer to environment area.
- cmp byte ptr es:[edi],0 ; No environment?
- je no_environment_at_all
- xor eax,eax ; search for 0 byte.
- Scan_again:
- cmp dword ptr es:[edi],'78ON' ; NO87
- jne short not1
- cmp byte ptr es:4[edi],'=' ; =
- jne short not1
- doesnt_want_8087 ; Macro back-substituted here.
- not1: getminus1 ecx ; Search lotsa bytes.
- repnz scasb ; Search for 0.
- ; We MUST have found the 0 byte; we're positioned at the byte after.
- cmp byte ptr es:[edi],0 ; Two 0 bytes in a row?
- jne Scan_again ; Nope, keep going.
-
- ; Now we've found the environment area end. +3 bytes later is the prog name.
- add edi,3 ; Move to program name.
- cmp _osmajor,3 ; Program name supplied by OS?
- jb short NO_PNAME_AVAIL
- cmp env,SG_ENV
- jne short get_pname
- cmp env,AI_ENV
- je short get_pname
- ; IGC: pname is addressable.
- mov dword ptr prognamep,edi
- mov word ptr prognamep+Word_size,ds
- jmp short _prog_name
-
- NO_PNAME_AVAIL:
- ; No program name. Supply the null string.
- ifdef HC
- ; Allocate the null byte on the stack right after the parms.
- xor edx,edx
- push edx ; Null byte(s).
- mov dword ptr prognamep,esp ; Pointer to the program name.
- endif
- jmp short _prog_name
-
- get_pname:
- if ePL_exists or eAI_exists
- cmp env,PL_ENV
- je next8a
- cmp env,AI_ENV
- je next8a
- jmp next8
- next8a:
-
- ; In small-data C, the program name must be moved into the DS group.
- ifdef Small_data_HC ; Move the program name to the stack.
- xor eax,eax
- ; Find length of program name.
- getminus1 ecx
- mov ebx,edi ; Save starting address of name.
- repnz scasb
- sub edi,ebx ; Length of name (including 0 trailer).
- lea eax,3[edi] ; Add some space on stack...
- and eax,0fffch ; Ensure mod 4 for nice value for SP.
- sub esp,eax ; Allocate space for name.
- mov dword ptr prognamep,esp ; Where the name will be put.
- mov ecx,edi ; Length of name
- mov esi,ebx ; Name is stored here.
- mov edi,esp ; Copy to here.
- push ds
- mov ds,word ptr envp+Word_size
- push ss
- pop es
- rep movsb
- pop ds
- else
- ; Non-small data case: just record the address.
- mov dword ptr prognamep,edi
- mov word ptr prognamep+Word_size,es
- endif
- next8:
- endif
-
- no_environment_at_all:
- _prog_name:
-
- ifdef HC
- ; Now allocate the space for the argv pointers. One for the program name
- ; and one for each argument. Although we don't know how many arguments there
- ; are, there can be at most 1 for every two characters of the environment
- ; string.
- mov eax,arglen
- inc eax
- shr eax,1 ; Max arg ptrs for parameters
- inc eax ; Count the program name.
- inc eax ; ANSI requires argv[argc] = null pointer.
- shl eax,2 ; Multiply by pointer size
- sub esp,eax ; Now allocate it.
- mov dword ptr argvp,esp ; sp is here.
- endif ; HC
-
- endif ; DOS
-
- ;call file and user initialization, call main program
-
- assume_dgroup
- push ds
- pop es
- ; ss is already = ds.
- ; Since this is in Pascal, we must initialize ds first!
- ; call init_interrupts
-
- ; Phar lap asssembler won't take:
- ; pcall finit ;initialize Pascal file system.
-
- mov ebx,offset ds:__mwifc
- mov ecx,offset ds:__mwilc
- sub ecx,ebx
- mustcall: or ecx,ecx
- jz mustdone
- mov edi,[ebx]
- add ebx,4
- sub ecx,4
- ifndef Small_code
- mov esi,[ebx]
- add ebx,2
- sub ecx,2
- endif
- or edi,edi
- jz mustcall
- push ebx
- push ecx
- ifdef Small_code
- call edi
- else
- push edi
- push esi
- mov ebx,sp
- call dword ptr [ebx]
- pop ecx
- pop ecx
- endif
- pop ecx
- pop ebx
- jmp mustcall
-
- mustdone:
-
- pcall _mwfinit ;initialize Pascal file system.
- pcall cfinit ;initialize C file system.
- if eHC and not eWINDOWS
- ; In preparation for calling main, push addr of argv.
-
- ifndef Small_data
- push word ptr Argvp+2 ; push segment
- endif ; Small_data
- push dword ptr argvp ; Push offset.
- sub eax,eax ; In case he supplies dummy routine: argc = 0.
- pcall set_up_args ; Find argv values by scanning argument string.
- push eax ; Push computed ArgC.
- endif ; HC and not WINDOWS
-
- ifdef DOS
- ; Now check if he used the 1167, but it doesn't exist.
- _MW1167_USED1 segment common byte 'DATA'
- magic6 dw 1 dup(?) ; Not initialized.
- offoops6 dd 1 dup(?) ; Not initialized.
- oopsptr6 dd 1 dup(?) ; Not initialized.
- _MW1167_USED1 ends
- cmp byte ptr _1167,1
- je short OK3 ; If 8087 there, no further checking needed.
- cmp magic6,0abcdh
- jne short OK3
- mov eax,oopsptr6
- cmp eax,offoops6
- jne short OK3
- mov edx,oopsptr6
- jmp short more_message
- OK3:
- ; Now check if he used the Cyrix EMC 87, but it doesn't exist.
- _MWEMC_USED1 segment common byte 'DATA'
- magic7 dw 1 dup(?) ; Not initialized.
- offoops7 dd 1 dup(?) ; Not initialized.
- oopsptr7 dd 1 dup(?) ; Not initialized.
- _MWEMC_USED1 ends
- DGROUP group _MWEMC_USED1 ; Helps multiseg links.
- cmp byte ptr _emc87,1
- je short OK4 ; If 8087 there, no further checking needed.
- if not eUSING_FLAT
- cmp DGROUP:magic7,0abcdh
- jne short OK4
- mov eax,DGROUP:oopsptr7
- cmp eax,DGROUP:offoops7
- jne short OK4
- mov edx,DGROUP:oopsptr7
- else
- cmp magic7,0abcdh
- jne short OK4
- mov eax,oopsptr7
- cmp eax,offoops7
- jne short OK4
- mov edx,oopsptr7
- endif
- jmp short more_message
- OK4:
- ; Now check if he used the 8087, but it doesn't exist.
- ; Here is how we determine if he dragged in fltused from the library:
- ; magic will have a "magic" value, and offoops will have the offset of
- ; the "oops" message. If _mw87_used is not hauled in, magic and offoops
- ; will be 0 when using all linkers under MS-DOS; on the Intel linkers
- ; they wil be garbage and WE HOPE THAT the fields won't accidentally
- ; look correct. This is not foolproof, therefore, with linkers that don't
- ; zero out unitialized memory, but it is much
- ; cheaper than checking in the RTL for the 8087 presence for each 8087
- ; operator invoked. I WISH OMF provided a "segment length"
- ; fixup; then this could be made foolproof.
- _MW87_USED1 segment common byte 'DATA'
- magic dw 1 dup(?) ; Not initialized.
- offoops dd 1 dup(?) ; Not initialized.
- oopsptr dd 1 dup(?) ; Not initialized.
- _MW87_USED1 ends
-
- cmp byte ptr _8087,1
- je short OK ; If 8087 there, no further checking needed.
- cmp magic,0abcdh
- jne short OK
- mov eax,oopsptr
- cmp eax,offoops
- jne short OK
- mov edx,oopsptr
- more_message:
- cmp wind,1
- je windchipmsg
- mov ah,9
- call _mwint21
- jmp Quit
- OK: ; Did he require 387, and is it here?
- _MW387_USED1 segment common byte 'DATA'
- magic3 dw 1 dup(?) ; Not initialized.
- _MW387_USED1 ends
- cmp byte ptr _387,1
- je short OK2
- cmp magic3,0abcdh
- jne short OK2
- cmp wind,1
- je windchipmsg
- ; He used it, but it's not present.
- mov edx,cs:oops3ptr
- mov ah,9
- call _mwint21
- mov edx,oopsptr
- add edx,10 ; Skip past "8087/80287".
- jmp more_message
-
- windchipmsg:
- mov printnochipmsg,1
- jmp OK2
-
- _387msg db '80387','$'
- oops3ptr dd offset _387msg
-
- OK2:
-
- endif
-
- if eWINDOWS
- extrn _cinit:near
- call _cinit
- db 0cbh
-
- else
- jmp Init_return
- endif
-
- fp_init_cw dw 03FFH ; For initializing 8087/287.
- fp_init_cw_emc dw 83FFH ; For initializing EMC 87.
- ; The 8000 is for testing presence of EMC 87 part.
- assume es:nothing
- endif
- INIT endp
-
- init_const proc
- publab init_const
- prolog
- assume_dgroup
- ; initialize constants ... may be called from init,
- ; or from WINDOWS environment initializer
-
- ; determine DOS version number
- push eax
- xor eax,eax
- mov ah,30h ; Get DOS version number
- call _mwint21
- mov word ptr _osmajor,ax ; Moves minor (AH) and major (AL).
- mov osver,eax ; also save full version locally
- pop eax
-
- epilog
- init_const endp
-
- if AIA_CAN_GROW_HEAP
- grow_parent_segment proc near
- push ebx ; save regs that get altered
- push edi
- push es
-
- push ebx ; save paras - we need BX for OS386 call
- push edx ; this int 21 trashes edx
- mov ax, 0ED00h ; get info on segment which is to be grown
- mov bx, ds
- call _mwint21
- pop edx ; restore edx
- pop ebx ; DI now contains parent segment for DGROUP
-
- mov es, di ; now shrink this segment to paras in EBX
- mov ah, SETBLOCK
- call _mwint21
-
- pop es
- pop edi ; restore regs
- pop ebx
- ret
- grow_parent_segment endp
- endif
-
- if eWINDOWS
-
- clear_bss proc
- publab clear_bss
- prolog eax,ecx,edi
-
- assume_dgroup
-
- extrn _edata:near
- extrn _end:near
-
- xor eax,eax
- mov edi,offset ds:_edata
- mov ecx,offset ds:_end
- sub ecx,edi
-
- shr ecx,1
- rep stosw
- adc ecx,ecx
- rep stosb
- epilog
- clear_bss endp
-
- call_onentry_fcns proc
- publab call_onentry_fcns
- extrn _init_environ:near
- call _init_environ
- return
- call_onentry_fcns endp
-
- endif
-
- expand_heap proc far
-
- ; The heap manager calls this routine to request memory from the heap.
- ; The expansion expands allocates more memory starting at _heaphi.
- ; Record the new top-of-heap in _heaphi.
-
- heap_info struc
- request dd ? ; size, in bytes, of request
- allocated dd ? ; size, in bytes, of allocated memory
- virtbase dd ? ; ptr to allocated memory
- heap_info ends
-
- publab expand_heap
- prolog
- mov edx,8[ebp]
- mov [edx].allocated,0 ; assume we're not successful
-
- mov eax,[edx].request ; round request up to nearest page
- add eax,4095
- and eax,0fffff000h
- mov [edx].request,eax
-
- mov ebx,_heaphi ; our upper-bounds
- sub ebx,_heaptop ; space left in heap
- cmp eax,ebx ; is it big enough?
- jg short get_more
-
- mov [edx].allocated,ebx ; we've got room!!
- mov eax,_heaptop ; compute start of new user heap
- inc eax
- mov [edx].virtbase,eax
- dec eax ; compute new heaptop
- add eax,ebx
- mov _heaptop,eax
- jmp return_from_expand
-
- get_more:
- if eD4G_exists
- cmp env,D4G_ENV
- jne not_dos4g
-
- ; ***********************
- ; * *
- ; * DOS4G *
- ; * *
- ; ***********************
- mov ebx,[edx].request ; 64k minimum
- cmp ebx,0ffffh
- jg short whole_chunk
- mov ebx,010000h
-
- whole_chunk:
- mov [edx].request,ebx ; Total we ask for in the int31.
- shrd ecx,ebx,16
- shr ecx,16
- shr ebx,16
- mov ax,0501h
- int 31h
- jc return_from_expand
-
- ; Answer comes back in bx:cx.
- shl ebx,16
- mov bx,cx ; Form 32-bit address in ebx.
- mov [edx].virtbase,ebx
- mov ecx,[edx].request ; amount requested
- mov [edx].allocated,ecx ; is amount allocated
- add ecx,ebx ; add virtual base
- mov _heaptop,ecx ; user top of heap
- mov _heaphi,ecx ; same as system top of heap
-
- jmp return_from_expand
- endif ; D4G_exists
-
- not_dos4g:
- ; ***********************
- ; * *
- ; * NOT DOS4G *
- ; * *
- ; ***********************
-
- ; Has the user shut off heap expansion?
- cmp heap_expansion_enabled,CANT_EXPAND
- je return_from_expand
- cmp env,PL_ENV
-
- ifndef PHAR_LAP_CAN_GROW_HEAP
- je return_from_expand ; Must have release >= 1.1t.
- else
- je short Can_grow
- endif
-
- ifndef AIA_CAN_GROW_HEAP
- ; If Lahey format, we must be able to grow.
- cmp Lahey_format_load_file,1
- jne short return_from_expand
- else
- cmp env,AI_ENV
- jne return_from_expand
- endif
-
- Can_grow:
- if not eWINDOWS
- mov ax,ds ; see if heaphi has changed
- lsl eax,eax
- cmp _heaphi,eax
- je short heap_ok
- mov _heaptop,eax ; reset pointers if it has
- mov _heaphi,eax
-
- heap_ok:
- mov eax,_heaptop ; next page starts on next byte
- inc eax
- mov [edx].virtbase,eax ; new user heap will start here
-
- inc eax ; size = offset + 1
- add eax,[edx].request ; add in request
- mov _totsiz,eax ; save totalsize
-
- shr eax,12 ; convert to pages
- cmp env,AI_ENV
- jne short pages
- shl eax,8 ; convert pages to paragraphs for AI.
-
- ; if AI_ENV and PL linker skip to allocation
- ; else must be AI_ENV and Lahey Linker so
- ; we must grow the parent segment first
- cmp Lahey_format_load_file,1
- jne short pages
- call grow_parent_segment
-
- pages:
- mov ebx,eax ; prepare for INT 21h
- mov ah,SETBLOCK
- call _mwint21
- jc short return_from_expand
-
- mov eax,[edx].request ; amount requested
- mov [edx].allocated,eax ; is amount allocated
-
- mov eax,_totsiz ; retrieve total size
- dec eax ; convert to offset
- mov _heaphi,eax ; update pointers
- mov _heaptop,eax
- endif
-
- return_from_expand:
- epilog 4
- expand_heap endp
-
- ;
- ;**************************************************************************
- ; function ss: Cardinal; {Returns paragraph address of stack segment
- ;**************************************************************************
- ;
- ssx proc far
- publab ss
- mov ax,ss
- return
- ssx endp
-
- ;**************************************************************************
- ; function Getds: Cardinal; -- Returns ds register.
- ;**************************************************************************
- ; This function may actually no longer be needed.
-
- ifdef Small_data
- getds proc far
- publab getds ; return ds register.
- mov ax,ds
- return
- getds endp
- endif
-
- dos_exit proc far
- publab dos_exit
- mov al,8[ebp]
- mov ah,4ch
- call _mwint21
- dos_exit endp
-
- ?INIT ends
- end genesis
-