home *** CD-ROM | disk | FTP | other *** search
Text File | 1992-12-09 | 58.2 KB | 1,747 lines |
- small_m = 1
- mach386 = 1
- GOC = 1
- comment %
- **************************************************************************
- *** (c) Copyright 1983 - 1992 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.
-
-
- --------------------------------------------------------------------------
- This initializer supports:
- --------------------------------------------------------------------------
- a. Pharlap's 386 DOS|Extender, run386.
- b. A.I. Architect's (Eclipse) OS/386 DOS extender.
-
- --------------------------------------------------------------------------
- Assembly instructions:
- --------------------------------------------------------------------------
- By default, the code assumes the use of 386asm. If your would like to
- use MASM, you must define USING_MASM later in the defines section.
-
- --------------------------------------------------------------------------
- Differences between Pascal and C run-time initialization:
- --------------------------------------------------------------------------
- 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. USING_MASM. Set this if you are using MASM to assemble this file.
- 2. HC. Set if this is for the High C library; not set otherwise.
- 3. STACK_SIZE. Set this to the size of the stack you want.
- 4. 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.
- 5. 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).
- 6. SG_exists -- Set when IGC environment is possible.
- Unsetting it comments out code dependent on that environment only.
- 7. PL_exists -- Set when PharLap DOS|Extender environment is possible.
- Unsetting it comments out code dependent on that environment only.
- 8. NOWTK -- Set if either the Weitek 1167 will never be present or
- if you never care about it.
- 9. PHAR_LAP_CAN_GROW_HEAP. 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.
- 10. AIA_CAN_GROW_HEAP. For Lahey-linked programs, we assume expansion can
- occur, since such linked programs do not give you all of memory.
-
- --------------------------------------------------------------------------
- Initializer Source Files
- --------------------------------------------------------------------------
-
- Set the appropriate defines in the init.inc module, and then assemble
- init.asm, init_67.asm, and init_87.asm.
-
- init.inc - This file includes definitions used across assembly files
- init.asm - general stuff
- init_67.asm - Weitek coprocessor initialization
- init_87.asm - x87, Cyrix coprocessor initialization
-
- init.h - Include file to access intializer globals, functions from C
- cinit.c - Main initialization routine. Makes calls into init.asm code.
-
- mini-Makefile:
-
- INITOBJS = init.obj init_67.obj init_87.obj cinit.obj
-
- .asm.obj:
- 386asm $@
-
- .c.obj:
- hc386 -c $@
-
- init.obj: init.inc init.asm
-
- init_67.obj: init.inc init_67.asm
-
- init_87.obj: init.inc init_87.asm
-
- cinit.obj: init.h cinit.c
-
- --------------------------------------------------------------------------
- Memory Layout:
- --------------------------------------------------------------------------
-
- High memory +---------------+
- | END OF MEMORY |
- |---------------|
- _heaphi -> | top-of-heap |
- _heaptop -> | ... |
- | 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.
- %
- comment @
- --------------------------------------------------------------------------
- AutoDesk Compatibility
- --------------------------------------------------------------------------
- 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
-
- ;---------------------------------------------------------------------------
- ; Start of program code.
- ;---------------------------------------------------------------------------
- .386p ; Need p to execute "lsl" to determine limit
- ; of data segment.
- .287
- name init
- include init.inc ; defaults moved into init.inc
- ; several assemblies use them.
- ; init.asm, init_67.asm init_87.asm
-
- ; 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
-
- ;--------------------------------------------------------------------------
- ; Fix segment ordering.
- ;--------------------------------------------------------------------------
- ; 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.)
-
- ;-- stack segment ----------------------------------------------------------
- if eWINDOWS
-
- ; stack comes before code in windows
-
- ; Use dword alignment for stack segment in the future.
-
- 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 64K.
- STACK? ends ; MS-DOS loader puts info at the
- ; tail end of the stack during loading.
- endif
-
- ;-- code segment ----------------------------------------------------------
- _TEXT segment dword public 'CODE'
- _TEXT ends
-
- ;-- data segment ----------------------------------------------------------
- _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
-
- ;-- const segment ----------------------------------------------------------
- CONST segment public 'CONST'
- CONST ends
-
- ;-- bss segment ----------------------------------------------------------
- _BSS segment public 'BSS'
- _BSS ends
-
-
- ;-- end bss segment ----------------------------------------------------------
- _EBSS_ segment public 'BSS'
- _ebss equ this byte
- _EBSS_ ends
-
-
- ;-- stack segment ----------------------------------------------------------
- if not eWINDOWS
-
- ; stack comes after BSS 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 ; eUSING_MASM
-
- ; Use dword alignment for stack segment in the future.
-
- ?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.
- ;---------------------------------------------------------------------------
- ; 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:
-
- _MWLTCONV segment common dword 'DATA'
- ltconv_in dw 0 ; length is 2 for line terminator.
- ; zero says allow either char for line term.
- lt1i db 13 ; CR
- lt2i db 10 ; LF
- ; Line termination convention for output; must be length of one or two chars.
- ltconv_out dw 2 ; length is 2 for line terminator.
- lt1o db 13 ; CR
- lt2o db 10 ; LF
- _MWLTCONV ends
-
- ;---------------------------------------------------------------------------
- ; Call on entry segments
- ;---------------------------------------------------------------------------
- ; This segment is used to 'register' functions which must be called
- ; by the start-up routine. Each of the functions to be called
- ; contain the following three segments, of which the first and last
- ; are empty. The central segment contains zero or more pointers to
- ; routines that the initializer must call during startup.
- PUBLIC __mwdfc, __mwdlc
- if eHC
- _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
-
- ;--------------------------------------------------------------------------
- ; Start of data segment.
- ;--------------------------------------------------------------------------
- DSEG segment dword 'DATA'
-
- ;----------------------------------------------------------------------
- ; Public symbol declarations.
- ;----------------------------------------------------------------------
- ; The symbols declared with the defequ or pubnames macros are
- ; prefixed with "_mw". Input and output 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
- if eHC
- pubname argvp
- endif
-
- ; Define input and output descriptors
- ; 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.
- ;----------------------------------------------------------------------
- ; 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.
-
- ;----------------------------------------------------------------------
- ; Initialize the graphics selector.
- ;----------------------------------------------------------------------
- ; The startup code detects the host environment and sets the graphics
- ; selector accordingly. This info is used by GFX.
-
- defequ gsel,dw,0 ; graphics selector
- public _mwgsel ; Pharlap (PL_env) uses 1C
- ; Eclipse (AI_env) uses B8 and B0
-
- ;----------------------------------------------------------------------
- ; Data definitions.
- ;----------------------------------------------------------------------
-
- STDERR equ 2 ; standard error file handle
- _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.
- envptr equ 2CH ; Offset in DOS ctrl block where env address
- ; is located
-
- 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 system heap
- _heaptop dd 0 ; offset to top of previous heap request
- ; (heaptop+1)..(heaphi) is available
-
- osver dd ? ; all 32 bits of os version
- virtbase dd ? ; ptr to allocated memory
- totsize dd ? ; total size of request
- lasthand dw 2 dup (?) ; last handle allocated
-
- ifdef SG_exists
- public _gda
- _gda dd 0 ; Address of gda (softguard only)
- endif ; SG_exists
- endif ; STACK_SIZE
-
- defequ argp,df,? ; Pointer to command arguments
- if eHC
- defequ argvp,df,? ; Address of argv array for C.
- endif ; eHC
-
- even
- if eWINDOWS
- pubname is_p
- if not eHC
- defequ is_p,db,1 ; Is the RTE Pascal or C?
- 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
- db 0dh,0ah,'80x87$'
- 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.
- db 0dh,0ah,'80387$'
-
- _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.
- db 0dh,0ah,'Cyrix EMC87$'
-
- public _mwno87
- _mwno87 dd 0 ; pointer to no87 environment string.
- _mwno87es dw 0,0 ; MUST immediately follow mwno87!!!!!!
-
- savefs dw 0
- 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
-
- return_address equ this byte ; Used to save the return address before the
- return_off dd 0 ; stack is set up. We can then use a jump
- return_seg dw 0 ; instruction to return.
-
- 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?
- public _mwenv
- defequ wind,db,0 ; Are we running under windows?
- defequ printnochipmsg,db,0
- defequ init_ver,db,2 ; Which init is this? (1==LOC,2==GOC)
- Lahey_format_load_file db 0 ; .plx (Phar-Lap linked) by default.
-
- ; is heap expandable?
- CANT_EXPAND = 0
- CAN_EXPAND = 1
- if eWINDOWS
- defequ heap_expansion_enabled,db,CANT_EXPAND
- else
- defequ heap_expansion_enabled,db,CAN_EXPAND
- endif
-
- 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
- align 4
- 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
-
- PSPseg dw 24h ; Pointer to DOS's Program segment prefix: Phar Lap.
- ENVseg dw 2ch ; Pointer to DOS's environment string: Phar Lap.
- DSEG ends
-
- if eDOS
- if eWINDOWS
- DGROUP group _BSS,_DATA,DSEG,_MWIFC,_MWIMC,_MWILC,_MWDFC,_MWDMC,_MWDLC,_MWLTCONV, _MWDFW, _MWDMW, _MWDLW
- else
- if eUSING_MASM
- DGROUP group _BSS,_DATA,DSEG,_MWIFC,_MWIMC,_MWILC,_MWDFC,_MWDMC,_MWDLC,_MWLTCONV,_EBSS_
- else
- DGROUP group _BSS,_DATA,DSEG,_MWIFC,_MWIMC,_MWILC,_MWDFC,_MWDMC,_MWDLC,_MWLTCONV,STACKNAME,_EBSS_
- endif
- endif
- else
- DGROUP group _DATA,DSEG,_MWIFC,_MWIMC,_MWILC,_MWDFC,_MWDMC,_MWDLC,_MWLTCONV,STACKNAME,_EBSS_
- endif
-
- assume_dgroup macro
- if eUSING_FLAT
- assume ds:FLAT
- else
- assume ds:DGROUP
- endif
- endm
-
- ;--------------------------------------------------------------------------
- ; Start of code segment.
- ;--------------------------------------------------------------------------
- ?INIT segment dword 'CODE'
- if not eUSING_FLAT
- CGROUP group ?INIT,_TEXT
- assume cs:CGROUP
- else
- FLAT group ?INIT,_TEXT
- assume cs:FLAT
- endif
-
- ;---------------------------------------------------------------------------
- ; Declare external procedures
- ;---------------------------------------------------------------------------
- ; Extern procs must be defined within current code segment for
- ; correct relocation bits to be generated.
- ; Phar lap assembler won't take next line; it plays according to the rules
- ; (as opposed to Microsoft's assembler):
-
- extrn exit:near
- if eHC
- 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
- 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
-
- 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
-
- ;-------------------------------------------------------------------------
- ; Here begins the execution of a Professional Pascal or High C program.
- ;-------------------------------------------------------------------------
-
- init proc
- publab INIT ; Compiler generates this in upper case.
-
- ; INIT: Initialization code
- ; - set initial stackpointer, framepointer
- ; - jump to _CINIT function to continue initialization.
- assume_dgroup
-
- if eHC
- Small_data_HC = 1
- endif
- SETBLOCK equ 4Ah
-
- jmp Start_init
- public __main
- __main:
- jmp main
-
- 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
-
- Start_init:
-
- 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
- ; determine OS version
- call init_const
-
- if ePL_exists
- 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
-
- 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
-
- if eWINDOWS
- ; 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.
-
- cmp env,SSI_ENV
- jne next0
- 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
- next0:
- endif ; eWINDOWS
-
- ; 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
-
- if eSG_exists
- ; Initialize stack, IGC environemnt.
- ; This code will work for h (highest) and a (append after load)
- ; stk options. esp already setup by vmrun loader.
- cmp env,SG_ENV
- jne short next1
-
- 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 ; bottom of heap
-
- inc eax ; increase size to page boundary
- add eax,4095
- and eax,0fffff000h
- dec eax
- mov _heaptop,eax ; end of previous heap
-
- mov eax,[edx].GDA_HLOD ; get highest load address
- mov ecx,[edx].GDA_HMEM ; get available high memory
- shl ecx,10 ; convert from k to # of bytes
- 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 ; SG_exists
-
- if ePL_exists
- cmp env,PL_ENV
- jne short next2
-
- mov eax,esp
- mov _base,0 ; Start of stack.
- 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,fs
- mov savefs,ax
- and ax,ax ; If fs = 0 (Lahey linker), can't have Weitek.
- sete Lahey_format_load_file
-
- mov ax,ds
- lsl eax,eax ; load segment limit of data segment.
- mov _heaphi,eax ; Top of heap (linear address).
- next2:
- endif ; PL_exists
-
- if eD4G_exists
- cmp env,D4G_ENV ; One doesn't shrink the heap in DOS4G.
- jne short next2a
-
- mov _base,0
- mov _top,esp
- mov _heaphi,esp ; previous top of heap
- mov _heaptop,esp ; top of heap (empty)
- next2a:
- endif
-
- 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.
- @
- movzx eax,word ptr info_sel
- push eax
- push info_off
- call getinitinfo
- add esp,8
- endif
- endif
- extrn _cinit:near
- if eWINDOWS
- mov wind,1
- call _cinit
- db 0cbh ; retf
- else
- jmp _cinit
- endif ; eWINDOWS
- init endp
-
- if eHC
- db 'High C'
- else
- db 'Professional Pascal'
- endif
- db ' Run-time Library Copyright (C) 1983-1992 MetaWare Incorporated.'
-
- ;-------------------------------------------------------------------------------
- ; init_const
- ;-------------------------------------------------------------------------------
- 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
- push ebx
- 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 ebx
- pop eax
-
- epilog
- init_const endp
-
- if eDOS and not eWINDOWS
- ;-------------------------------------------------------------------------------
- ; init_env_area()
- ;-------------------------------------------------------------------------------
- ; Process environment area and parameter strings.
-
- init_env_area proc
- publab init_env_area
- ;assume cs:CGROUP
- assume_dgroup
-
- Parm_string_offset = 80h ; Offset in PSP containing parm
- ; string (len+bytes).
- ; Pop return address off of stack
- pop dword ptr return_off
- ifdef Small_data
- push cs ; 32 bits?
- endif
- pop eax ; Pop dword to maintain
- mov word ptr return_seg,ax ; stack alignment!
-
- cld ; All moves are forward
-
- if eSG_exists
- cmp env,SG_ENV
- jne short next3
-
- ; GDA has pointer to PSP. PSP has env seg, which, shifted left by 4,
- ; yields the 32 bit address of the env.
- 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
- next3:
- endif ; SG_exists
-
- if ePL_exists or eD4G_exists
- cmp env,PL_ENV
- je short next4a
- cmp env,D4G_ENV
- jne next4
- next4a:
- 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
- push eax
- mov al,es:Parm_string_offset ; Length of parm string
- mov arglen,eax
-
- ; In C, the parameter string must be moved to a DS-accessible area
- ; if small-data model.
- if eHC
- ; Move the parm string into the stack so that it can be accessed by
- ; small-data programs with only 16-bit pointers.
- mov ecx,eax ; parameter length
- inc ecx
- add al,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.
- push ds ; Save it.
- push es ; source is es:81h
- pop ds
- push es ; Save es.
- push ss
- pop es ; Dest is ss:di.
- mov esi, offset Parm_string_offset+1
- 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
-
- next4:
- endif ; PL_exists or D4G_exists
-
- more_init2:
-
- if eD4G_exists
- cmp env,D4G_ENV
- je no_change
- endif
-
- if eSG_exists
- cmp env,SG_ENV
- je no_change
- endif
-
- if eAI_exists
- cmp env,AI_ENV
- jne short not_ai2
-
- mov ebx,_top ; Top of stack in bytes
-
- ifndef AIA_CAN_GROW_HEAP
- ; If Lahey format, we must be able to grow.
- cmp Lahey_format_load_file,1
- jne short no_change
- endif
-
- jmp short Free_up
- not_ai2:
- endif ; AI_exists
-
- if ePL_exists
- 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.
- ; See Phar Lap TN #21.
- endif ; ACAD
- jmp short Free_up
- endif ; PHAR_LAP_CAN_GROW_HEAP
- endif ; PL_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
- shl edx,12 ; Future value for heaphi.
- dec edx
-
- cmp env,PL_ENV
- je short No_para
- shl ebx, 8 ; Convert to paragraphs for AIA.
- No_para:
- push ds
- pop es ; Segment to free up.
- mov ah,SETBLOCK ; SETBLOCK to bx paras from psp start.
- call _mwint21
- jc short no_change ; If couldn't get the extra page, oops!
- mov _heaphi,edx
- endif ; PL_exists or AI_exists
-
-
- no_change:
-
- ; find program 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.
- 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
-
- ; All this fuss just to print the NO87 string!
- ifndef no87
- add edi,5
- mov _mwno87,edi
- mov _mwno87es,es ;save pointer and print it later.
- endif ; no87
-
- not1:
- sub ecx,ecx
- dec ecx ; ecx := -1
- 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 ** commented out 18-Jun92 (MJMauro)
- ; 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.
- if eHC
- ; 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 ; eHC
- jmp short _prog_name
- get_pname:
-
- 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:
-
- ; 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.
- mov ax,es
- lsl eax,eax ; load segment limit of env string.
- xor eax,eax
- ; Find length of program name.
- sub ecx,ecx
- dec 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 al,0fch ; only al involved, so use shorter instructions.
- 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 ; Small_data_HC
-
- next5:
- endif ; PL_exists or D4G_exists or AI_exists
-
- _prog_name:
- if eHC
- ; 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
-
- jmp fword ptr return_address
- init_env_area endp
- endif ; eDOS and not eWINDOWS
-
-
-
- ;-------------------------------------------------------------------------------
- ; clear_bss()
- ;-------------------------------------------------------------------------------
- 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
- mov ecx,offset ds:_ebss
- sub ecx,edi
-
- shr ecx,1
- rep stosw
- adc ecx,ecx
- rep stosb ; Could be smarter -- use stosd, but compilcates code
- epilog
- clear_bss endp
-
- ;-------------------------------------------------------------------------------
- ; call_onentry_fcns()
- ;-------------------------------------------------------------------------------
- call_onentry_fcns proc
- publab call_onentry_fcns
- prolog
-
- assume_dgroup
- push ds
- pop es
- mov ax,fs
- mov savefs,ax
- ; ss is already = ds.
-
- ; Clear BSS segment
- if eD4G_exists
- if not eWINDOWS
- call clear_bss
- endif
- endif
-
- ; Here begins new code...C++ initialization is done in C, so we just set up
- ; and call a C routine to do the work.
-
- ; typedef struct {
- ; ulong init_level;
- ; void (*ct)();
- ; ulong reserved;
- ; } ct_elem, *ct_array;
- ; void _mwdo_ctors(ct_array ctors, int ctor_size, ct_array dtors, int dtor_size)
-
-
- mov ebx,offset _MWDFC
- mov ecx,offset _MWDLC
- sub ecx,ebx
- push ecx ; Size of destructor array
- push ebx ; Beginning of destructor array
- mov ebx,offset ds:__mwifc
- mov ecx,offset ds:__mwilc
- sub ecx,ebx
- push ecx ; Size of constructor array.
- push ebx ; Beginning of constructor array
- extrnf _mwdo_ctors
- call _mwdo_ctors
- add esp,10h ; pop 4
-
- ; Set graphics selector _mwgsel according to the environment
- ; and equipment configuration.
- ;
- if ePL_exists
- cmp env,PL_ENV ;Is this Pharlap's environment?
- jne short next10
- mov gsel,1ch ;Pharlap uses 0x1c
- next10:
- endif
-
- if eD4G_exists
- cmp env,D4G_ENV
- jne short next10a
- mov ax, ds
- mov gsel, ds ; use flat
- next10a:
- endif
-
- if eAI_exists
- cmp env,AI_ENV ;OS386?
- jne short next11
- AI_sel:
- mov ah,12h ;OS386 has different selectors
- mov bl,10h ;for color and bw.
- int 10h ;ask the BIOS which it is
- and bh,bh
- jz color
- b_and_w:
- mov gsel,0b0h ;OS386 bw selector is 0xb0
- jmp short selector_is_set
- color:
- mov gsel,0b8h ;OS386 color selector is 0xb8
- jmp short selector_is_set
- next11:
- endif
-
- selector_is_set:
-
- epilog
- call_onentry_fcns endp
-
- ;--------------------------------------------------------------------------
- ; procedure Expand_Heap();
- ;--------------------------------------------------------------------------
- ; The heap manager calls this routine to expand the heap when it
- ; detects a heap overflow. The expansion expands allocates more memory
- ; starting at _heaptop+1, recording the new top-of-heap in _heaptop.
- ; If expansion is required, heaphi is adjusted.
- ; Currently this is implemented only for Phar Lap's DOS|Extender.
-
- expand_heap proc far
-
- publab expand_heap
- prolog
-
- parm386 <<request,dword>>
- parm86 <<request,dword>>
-
- mov eax, request
- mov virtbase,0
- mov ebx,_heaphi ; our upper-bounds
- sub ebx,_heaptop ; space left in heap
- cmp eax,ebx ; is it big enough?
- ja short get_more
-
- mov eax,_heaptop ; compute start of new user heap
- inc eax
- mov virtbase,eax
- dec eax
-
- add eax,request ; compute new heaptop
- mov _heaptop,eax
- jmp return_from_expand
-
- get_more:
- cmp env,D4G_ENV
- jne not_dos4g
-
- ; ***********************
- ; * *
- ; * DOS4G *
- ; * *
- ; ***********************
- mov ebx,request ; user request is multiple of 4k
- 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.
-
- ; Handle comes back in si:di
- mov lasthand,si
- mov lasthand+2,di
-
- mov virtbase,ebx
- mov ecx,request ; amount requested
- 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
-
- 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 ; find top of heap
- lsl eax,eax
- cmp eax,_heaphi ; if different, reset heap
- je grow
-
- mov _heaptop,eax ; reset heap, as non-malloc request
- mov _heaphi,eax ; is blocking our request
- jmp short grow
-
- grow:
- mov eax,_heaptop ; next page starts on next byte
- inc eax ; size = offset + 1
- add eax,request ; add in request
- mov totsize,eax ; save total size for later
-
- shr eax,12 ; convert to pages
- cmp env,AI_ENV
- jne short pages
- shl eax,8 ; convert pages to paragraphs for AI.
-
- pages:
- mov ebx,eax ; prepare for INT 21h
- mov ah,SETBLOCK
- call _mwint21
- jc short return_from_expand
-
- mov eax,_heaptop ; next page starts on next byte
- inc eax ; new user heap will start here
- mov virtbase,eax
-
- mov eax,totsize ; retrieve total size of request
- dec eax ; convert to offset
- mov _heaphi,eax ; update pointers
- mov _heaptop,eax
- endif ; eWINDOWS
-
- return_from_expand:
- mov eax,virtbase
- epilog
- expand_heap endp
-
-
- ;-------------------------------------------------------------------------
- ; procedure set_stack_limits(small,large:Cardinal);
- ;-------------------------------------------------------------------------
- ; Set the two limits.
- ; This is called by the heap manager when the heap begins to creep
- ; into the stack, or when the heap has left the stack area.
- ; Basically, when the heap has used the lower portion of the stack,
- ; the stack margin variables are set to reflect a higher bottom-of-stack
- ; location, so that stack overflow will occur when the stack is within
- ; 256 bytes of the heap.
- ; If the stack precedes the heap, the heap never creeps into the
- ; stack and this procedure will never be called.
-
- Set_stack_limits proc far
- publab set_stack_limits
- return 8
- Set_stack_limits 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.
- xor eax,eax
- mov ax,ds
- return
- getds endp
-
- getcs proc far
- publab getcs ; return cs register.
- xor eax,eax
- mov ax,cs
- return
- getcs endp
- endif
-
- _exit proc near ;force an immediate exit to dos.
- public _exit
- mov eax, esp
- mov al, [eax+4]
- mov ah, 4ch
- call _mwint21
- _exit endp
-
- ; void contract_heap (void *allocated)
- ; memory, starting at *allocated, is returned to the system
- contract_heap proc near
- publab contract_heap
- prolog
-
- parm386 <<loc,dword>>
- parm86 <<loc,dword>>
-
- cmp env,D4G_ENV
- jne not_dos4g2
-
- ; ***********************
- ; * *
- ; * DOS4G *
- ; * *
- ; ***********************
-
- ; return memory to system
- mov si,lasthand
- mov di,lasthand+2
- mov ax,0502h
- int 31h
- jc return_fail
- jmp return_okay
-
- not_dos4g2:
- ; ***********************
- ; * *
- ; * NOT DOS4G *
- ; * *
- ; ***********************
-
- ; return memory to system
- mov eax,loc
- shr eax,12 ; convert to pages
- cmp env,AI_ENV
- jne short pages2
- shl eax,8 ; convert pages to paragraphs for AI.
-
- pages2:
- mov ebx,eax
- mov ah,SETBLOCK
- int 21h
- jc short return_fail
-
- return_okay:
- ; adjust _heaphi
- mov eax,loc
- dec eax
- mov _heaphi,eax ; _heaphi := totsize - 1
-
- ; if _heaptop > _heaphi, then adjust _heaptop
- cmp eax,_heaptop
- jge return_from_contract
- mov _heaptop,eax ; _heaptop := _heaphi
- jmp return_from_contract
-
- return_fail:
- ; adjust _heaptop, as we now have room
- mov eax,loc
- dec eax
- mov _heaptop,eax
-
- return_from_contract:
- epilog
- contract_heap endp
-
- ?INIT ends
- end init
-