home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 7 / 07.iso / c / c220 / 4.ddi / LIB / SRC / INIT.ASM < prev    next >
Encoding:
Assembly Source File  |  1990-12-16  |  43.9 KB  |  1,360 lines

  1. .386p    ; Need p to execute "lsl" to determine limit of data segment.
  2. .287
  3.  
  4. ; Here define USING_MASM if you are using Microsoft MASM 5.1 to assemble this.
  5. ; If you use MASM, you must also use "bd -mtop init.obj" to convert
  6. ; the MASM object to a Phar Lap object, if you wish to use the Phar Lap linker.
  7. ; USING_MASM equ 1
  8.  
  9.     name    init
  10. ; (assemble this with "386asm init")
  11. ;**************************************************************************
  12. ;***  (c) Copyright 1983 - 1990            MetaWare Incorporated.    ***
  13. ;**************************************************************************
  14. ;***  You have the same rights to the object form of this program as    ***
  15. ;***  you do to the object code of the library.  You may not distribute ***
  16. ;***  this source, even if modified by you.                ***
  17. ;**************************************************************************
  18. ;***  The source to this module is provided                ***
  19. ;***  for the convenience of MetaWare Pascal and High C users that need ***
  20. ;***  to tailor their execution environments.                ***
  21. ;***  The casual user should NOT play with the code.            ***
  22. ;***  This code is subject to change without notice in future releases    ***
  23. ;***  of the compilers.                         ***
  24. ;**************************************************************************
  25. ;***  You must preserve the library copyright notice defined in this    ***
  26. ;***  module if your program uses any portion at all of the run-time    ***
  27. ;***  library (including this initializer or any other supplied run-    ***
  28. ;***  time source).  The copyright notice is in the definition of    ***
  29. ;***  the initial stack segment.  We recommend it be left right there.    ***
  30. ;***  But you can move it to anywhere you want as long it appears in    ***
  31. ;***  any linked program (.exe or ROM-burned program) using the library.***
  32. ;**************************************************************************
  33. ;*                                      *
  34. ;*    MetaWare Pascal or High C Runtime Initialization Module       *
  35. ;*             for small model, protected mode 386.             *
  36. ;*                                      *
  37. ;**************************************************************************
  38.     include model    ; Memory model.
  39.  
  40. ; GROWHEAP.
  41. ; Dynamic heap expansion.
  42. ; As an option the run-time system will contract the data area back to
  43. ; a minimum at start-up, and expand it dynamically.
  44. ; This is principally useful if you wish to allocate memory separately
  45. ; from the run-time system using the SETBLOCK (4a) command.
  46.  
  47. ; Phar Lap's DOS|Extender 1.1t or later can grow the heap dynamically.
  48. ; For enabling Phar Lap DOS|Extender to grow the heap dynamically,
  49. ; uncomment the next line.
  50. PHAR_LAP_CAN_GROW_HEAP equ 1
  51.  
  52. ; AIA's OS/386 2.0.10 or later can grow the heap dynamically.
  53. ; For older versions, comment out the next line.
  54. AIA_CAN_GROW_HEAP equ 1
  55. ; For Lahey-linked programs, we assume expansion can occur, since such
  56. ; linked programs do not give you all of memory.
  57.  
  58. ;-----
  59. ;    The following include file is provided by IGC. 
  60. ;    GDA.STR is general data area structure for VM/RUN (X-AM).
  61. ;    Upon entry to target program from VMRUN, EDX --> GDA.
  62. ;       GDA is not useful when solely in the Phar-Lap environment.
  63. ;    Use "gda.h" in the inc/ directory to access the GDA from C:
  64. ;        #include "gda.h"
  65. ;        GDA *gdaptr;
  66. ;-----
  67.     include gda.str
  68.  
  69. ; The difference between the Pascal and C run-time initialization
  70. ; is that in C, the argv array must be allocated and computed.
  71. ; In Pascal argument processing is handled through a separate argument pacakge.
  72.  
  73. ; Defines that you can set:
  74. ; 1. HC.  Set if this is for the High C library; not set otherwise.
  75. ; 2. STACK_SIZE.  Set this to the size of the stack you want.
  76. ; 3. no87.  Set this if you know you have no 8087 or 287.  It will eliminate
  77. ;    the initialization code for the chip.
  78. ;    Also, it will remove the printing of the "no87" environment variable
  79. ;    if you have an 8087/287 and the no87 variable is set to non-blank string.
  80. ;    (Don't confuse the "no87" define in this assembly from the no87
  81. ;    MS-DOS environment variable.  Read the programmer's Guide for more info
  82. ;    on the latter.)
  83. ;    Another reason to set this variable is that you know you're never
  84. ;    going to use an 8087/287, even if you have one.  It's especially
  85. ;    useful to remove the printing of the no87 environment variable on
  86. ;    programs for which the 8087/287 processor is irrelevant.
  87. ; 4. DOS.   Set this if this initializer is for MS-DOS (default).  Unset it
  88. ;    for embedded applications where DOS doesn't exist.  If you unset it,
  89. ;    you won't get argc/argv for C, nor the arg package for Pascal.
  90. ;    It doesn't remove all of the DOS-dependent code -- some of it you must
  91. ;    still rewrite for embedded applications (like how to find the top of
  92. ;    memory).  (By "unset" we mean just comment out the line setting it!)
  93. ;    Note that unsetting DOS doesn't remove all DOS-dependent code in
  94. ;    the library.  For example, the interrupt handler initialization
  95. ;    uses INT 21h, and so does all I/O.  Read the Embedded Applications
  96. ;    section of the Programmer's Guide for more information about how
  97. ;    to change those modules (source is generally provided).
  98. ; 5. IGC_exists  -- Set when IGC environment is possible.
  99. ;    Unsetting it comments out code dependent on that environment only.
  100. ; 6. PL_exists    -- Set when PharLap DOS|Extender environment is possible.
  101. ;    Unsetting it comments out code dependent on that environment only.
  102. ; 7. NOWTK    -- Set if either the Weitek 1167 will never be present
  103. ;        -- or if you never care about it.
  104. ; 8. XOS -- New 32-bit OS, unreleased.
  105.  
  106. ; XOS = 1
  107. ifdef   XOS
  108. no87    = 1    ; There can be no x87 processor.
  109. NOWTK = 1    ; There can be no Weitek processor.
  110. else
  111. IGC_exists = 1
  112. PL_exists = 1
  113. endif
  114.  
  115. DOS equ 1    ; Initializer intended for MS-DOS.
  116. ; no87 equ 1
  117.  
  118. ; define HC if the initializer is to be for High C.
  119.   HC      equ      1
  120. ; Pascal is assumed otherwise.
  121.  
  122. ; Now set expression-identifiers so I can say "if this and not that".
  123. ; E.g., "compute x" defines macro ex to be 1 ifdef x, 0 otherwise.
  124. compute    macro    id
  125. ifdef    id
  126.     e&id = not 0
  127. else
  128.     e&id = 0
  129. endif
  130.     endm
  131.  
  132. compute HC    ; HC instead of Prof. Pascal.
  133. compute XOS
  134. compute PL_exists
  135. compute DOS
  136.  
  137. ;Memory Layout:
  138. ;
  139. ; High memory    +---------------+
  140. ;        | END OF MEMORY | 
  141. ;               |---------------|
  142. ;        | top-of-heap    |
  143. ;        |   ...     |
  144. ;        | bottom-of-heap|
  145. ;  _TOP  ->    |---------------|  <- Of size STACK_SIZE, unless there isn't
  146. ;        |   stack    |  <- room, in which case the first heap
  147. ;        |   ...     |  <- allocation will fail.
  148. ;        | end-of-stack    |
  149. ;  _BASE ->    +---------------+
  150. ;        DATA   segments   (static variables and named common)
  151. ; Low memory    CODE   segments
  152. ; See the programmer's guide for more information and pictures of
  153. ; run-time organization with the different memory models.
  154. ; Stack margin1 is 512 bytes above the true end-of-stack.
  155. ; Stack margin2 is 256 bytes above the true end-of-stack.
  156. ; In non-large models, the stack margins go in a reserved area in the data
  157. ; segment, not in the stack segment.  In the large model, since there is
  158. ; no single data segment, the stack margins go at the tail end of the stack
  159. ; (at ss:-2 and ss:-4).
  160. ;
  161. ; If stack overflow checking is enabled, here is the code that is generated:
  162. ;    For procedures using 256 or less bytes in the stack:
  163. ;        cmp    esp,Stack_margin_1
  164. ;        jnb    around
  165. ;        int    0
  166. ;    around: ...
  167. ;
  168. ;    Since Stack_margin_2 is 512 above true e-o-s, such procedures will always
  169. ;    leave at least 256 bytes (512-256) left in the stack.
  170. ;
  171. ;    For procedures that use more than 256 bytes:
  172. ;        mov    eax,esp
  173. ;        sub    eax,Stack_margin_2
  174. ;        cmp    eax,Amount_to_allocate
  175. ;        jae    around
  176. ;        int    0
  177. ;    around: ...
  178. ;
  179. ;    Since Stack_margin1 is 256 from true end,
  180. ;    such procedures will leave at least 256 bytes in the stack.
  181. ;
  182. ;    Therefore, stack overflow occurs when less than 256 bytes would be
  183. ;    left AFTER stack allocation.
  184. ;    This permits the run-time environment to do some processing
  185. ;    such as producing a trace or cleaning up.
  186.  
  187. STACK_SIZE = 8192       ; default size for stack.
  188.  
  189. ; Margin-big is used for small procedures -- it ensures a bigger margin.
  190. ; Margin-small is used for large procedures, since we do more accurate
  191. ; checking for them.
  192. Stack_margin_big    equ    512        ;Free stack bytes before overflow occurs
  193. Stack_margin_small    equ    256
  194. Stack_reserve    equ    4    ;At top, for the above two numbers (large model).
  195. STDERR        equ    2    ;standard error file handle
  196.  
  197.  
  198. ;The following dummy segment instructs linker to put "code" lowest
  199. ;Must be made public since the main module also has public code,
  200. ;and some primitive linkers can't handle segments of the same name
  201. ;with different privacy attributes.  (This does not include Phar Lap's linker.)
  202. CODE    segment dword public 'CODE' 
  203. CODE    ends
  204.  
  205. DATA    segment dword public 'DATA' 
  206.     pubname stack_limit
  207. The_stack_margin equ this word
  208. def    stack_limit,dd,0    ; Stack margins.
  209.     dd    0
  210. DATA    ends
  211.  
  212. ; Use dword alignment for stack segment in the future.
  213. STACKNAME equ ?STACK
  214. if    eXOS
  215. STACKNAME equ STACK
  216. endif
  217.  
  218. STACKNAME segment  dword stack  'STACK'    ; of at least 80 bytes.
  219. ; Copyright message got moved out of here so that the stack wouldn't
  220. ; take up space in the .exe file.
  221. start_of_stack equ this byte
  222.     db      STACK_SIZE dup (?)    ; The default stack of 8K.
  223. STACKNAME ends    ; MS-DOS loader puts info at the tail end of the stack during loading.
  224.  
  225. ;  Line terminator convention.
  226.  
  227. _MWLTCONV    segment common dword 'DATA'  
  228. ; This must be a MetaWare Pascal string:  2 bytes for the length,
  229. ; then the actual string characters follow.
  230. ; Even if the string is of length one, leave the length of this
  231. ; segment at 8 bytes. (leave lt2 present even if not used.)
  232. ; Line termination convention for input:
  233. ltconv_in    dw    2    ; length is 2 for line terminator.
  234. lt1i        db    13    ; CR
  235. lt2i        db    10    ; LF
  236. ; Line termination convention for output; may be of any length:
  237. ltconv_out    dw    2    ; length is 2 for line terminator.
  238. lt1o        db    13    ; CR
  239. lt2o        db    10    ; LF
  240. _MWLTCONV    ends
  241.  
  242. ifdef    HC
  243. _mwinitfrstcall    segment    public word 'DATA'
  244. _mwinitfrstcall    ends
  245. _mwinitmustcall    segment    public word 'DATA'
  246. _mwinitmustcall    ends
  247. _mwinitlastcall    segment    public word 'DATA'
  248. _mwinitlastcall    ends
  249. endif
  250.  
  251. ; Define input and output descriptors
  252.  
  253. dseg    segment dword 'DATA'
  254.     ; These are for Pascal but must be provided in C if we link in
  255.     ; the C initializer with Pascal routines.
  256.     pubnames <input,output>
  257.     pubnames <es,is_286,envp,8087,387,1167>
  258.     pubnames <argp,arglen,prognamep>
  259.     pubnames <CPU,OS,env>
  260.     pubnames <emc87,heap_expansion_enabled>
  261.     extrn     _osmajor:byte,_osminor:byte
  262. ifdef    HC
  263.     pubname argvp
  264. endif
  265. ; Pascal file variables Input and Output.  They are initialized in Pascal's Finit.p.
  266. defequ    input,dw,0
  267. defequ    output,dw,1
  268.  
  269. ; Initialize the "host" package that identifies the system we're running on.
  270. ; See the interface file Host.pf distributed with Professional Pascal or High C
  271. ; for the enumerated type declaration for the values of CPU and OS.
  272. defequ    CPU,db,8        ;Indicates 386. 
  273. defequ    OS,db,0     ;Indicates MSDOS.
  274.  
  275. _psp    equ    this byte
  276. def    es,df,0 ;The contents of es prior to invoking program
  277.         ; df is Microsoft's way of saying 48-bit pointer;
  278.         ; Phar Lap uses dp or df.
  279. escontents equ _psp             ; Program segment prefix pointer.
  280. ifdef    STACK_SIZE
  281.     public    _top,_base,_psp
  282. _top    dd    0        ; Top of stack (relative to SS).
  283. _base    dd    0        ; Base of stack (relative to DS).
  284. _heaphi dd    0
  285. ifdef    IGC_exists
  286.     public  _gda  
  287. _gda    dd      0               ; Address of gda (softguard only)  
  288. endif
  289. endif
  290. defequ    argp,df,?    ;Pointer to command arguments
  291. ifdef HC
  292. defequ    argvp,df,?     ; Address of argv array for C.
  293. endif
  294.  
  295.     even
  296. if    eXOS    
  297.     pubname is_p
  298. if      not eHC     
  299. defequ  is_p,db,1      ; Is the RTE Pascal or C?  Affects whether
  300. else
  301. defequ  is_p,db,0      ; low-level interface clears errno.
  302. endif
  303. endif
  304. defequ    arglen,DD,?    ;Length of command argument string
  305. defequ    envp,df,0    ;Pointer to environment string
  306. defequ    is_286,db,0    ;True if this is a 286.
  307. _8087    equ    this word    ; Need word to store control word into.
  308. def    8087,dw,0    ;Set to true if 8087 is present
  309. temp    dw    0
  310. _387    equ    this word    ; Need word to store control word into.
  311. def    387,dw,0    ;Set to true if 80387 is present.
  312. _1167    equ    this word
  313. def    1167,dw,0    ; True if 1167 is present.
  314. _emc87    equ    this word
  315. def    emc87,dw,0    ; Set to true if emc87 is present.
  316. Null_pname db    0    ; Null prog name for < DOS 3.0.
  317. ; Prognamep is initialized to a 32-bit pointer to a 0-byte in case
  318. ; we can't obtain the program name.
  319. defequ    prognamep,dd,Null_pname  ;Pointer to program name
  320.     prognamep_seg dw 0
  321. SG_ENV = 1
  322. PL_ENV = 2
  323. AI_ENV = 3
  324. XOS_ENV= 4
  325. defequ    env,db,0      ; Which environment are we in?  SG/PL/AI?
  326. cur_pages dd 0    ; Current # pages allocated: Phar Lap.
  327. Lahey_format_load_file db 0    ; .plx (Phar-Lap linked) by default.
  328. CANT_EXPAND = 0
  329. CAN_EXPAND = 1
  330. defequ    heap_expansion_enabled,db,CAN_EXPAND      ; Is heap expandable? 
  331.  
  332. dseg    ends
  333. envptr    equ 2CH     ;Offset in DOS ctrl block where env address is located
  334. ;
  335. if       eDOS
  336.   if    not eXOS
  337.   ; We can't put _MWEMCUSED1 in the group dcln because of the 132-character line limitation of the assembler.
  338. DGROUP  group DATA,_MWLTCONV,_mwinitfrstcall,_mwinitmustcall,_mwinitlastcall,dseg,_MW87_USED1,_MW387_USED1,_MW1167_USED1,STACKNAME
  339.   else
  340.     ; XOS doesn't want the stack DGROUPed.
  341. DGROUP  group DATA,_MWLTCONV,_mwinitfrstcall,_mwinitmustcall,_mwinitlastcall,dseg,_MW87_USED1,_MW387_USED1,_MW1167_USED1
  342.   endif
  343. else
  344. DGROUP  group DATA,_MWLTCONV,dseg,STACKNAME
  345. endif
  346.  
  347. ?init    segment dword 'CODE'
  348. CGROUP    group    ?init,CODE
  349.     assume cs:CGROUP
  350.     
  351. ; Extern procs must be defined within current code segment for
  352. ; correct relocation bits to be generated. 
  353. extrn    _mwfinit:near
  354. ; Phar lap assembler won't take next line; it plays according to the rules (as opposed to Microsoft's assembler): 
  355. ;extequ    finit,near    ;Pascal file system initialization.
  356. extequ    cfinit,near ;C file system initialization.
  357. extequ    halt,near    ; Halt intrinsic.
  358. ifdef    HC
  359. extrn    main:near    ; Main program entry point
  360. extequ    set_up_args,near ; Routine to compute argv pointers.
  361. else
  362. extequ    main,near    ;Main program entry point
  363. ;extequ    init_interrupts,near    ; initialize interrupt handling.
  364. endif
  365.  
  366. ; Where are the stack margins defined?    Top of stack or in data segment?
  367. Stack_margin_big_place        equ    dword ptr DGROUP:The_stack_margin
  368. Stack_margin_small_place    equ    dword ptr DGROUP:The_stack_margin+Word_size
  369. ;
  370. ; DOS|Extender environment discovery code obtained from Phar Lap: 
  371.  
  372. ;**************************************************************************
  373. ;*  Here begins the execution of a Professional Pascal or High C program. *
  374. ;**************************************************************************
  375.  
  376. INIT    PROC    FAR
  377.     publab    INIT    ; Compiler generates this in upper case.
  378. genesis:
  379.     assume  ds:DGROUP
  380.  
  381.           jmp    short Discover_environment
  382.  
  383. ; We jump to the rest of the initialization and jump back so that
  384. ; when debugging we can easily see the call to main as the first call.
  385.  
  386. Init_return:
  387.     ; In C, Argc/Argv values have been pushed on the stack by the time we get here.
  388.     pcall    main        ;call main program
  389.                 ; compiler generates defn of MAIN
  390.                 ; in a main program.
  391. Quit:                
  392.     ; In C, return the value returned by main to the system.
  393.     ; In Pascal, return 0.  To return a value in Pascal, use Halt(retcode).
  394. ifndef    HC
  395.     sub    eax,eax
  396. endif    
  397.     push    eax
  398.     pcall    halt
  399. ifdef    IGC_exists
  400. ; Next 2 lines TEMPORARY for IGC only.
  401.     xor    eax,eax         ; We shouldn't get here.
  402.     int    21h    
  403. endif   
  404. ifndef HC
  405.     ; Supply a dummy version of "call_onexit_fcns" for Pascal.
  406.     ; Cost:  1 byte here & 3 or 5 bytes for the call in term.p.
  407.     ; Benefits:  term.p is the same for Pascal and C.
  408.     publab    call_onexit_fcns
  409.     return
  410. endif
  411.     publab    restore_interrupts    ; For now, don't bother w/^C.
  412.     return
  413.  
  414. ifdef HC
  415.     db    'High C'
  416. else
  417.     db    'Professional Pascal'
  418. endif
  419.     db    ' Run-time Library Copyright (C) 1983-1990 MetaWare Incorporated.'
  420.  
  421. Discover_environment:
  422. ifdef    IGC_exists
  423. ; IGC: eax = abcdabcd.  Also, code segment is privilege level 3
  424. ; (= 43 hex).
  425.         cmp     al,0cdh         ; eax = abcdabcd for IGC.
  426.         jne    short not_sg
  427.         cmp    ah,0abh 
  428.         jne    short not_sg
  429.         ; Flaw: If we are in non-protected mode and get this far,
  430.         ; the cmp eax will have 16 bits too much constant, and will
  431.         ; cause the initializer to bomb.  It is unlikely that ax=abcd
  432.         ; yet eax <> abcdabcd.
  433.         cmp    eax,0abcdabcdh    ; Now try 386 instruction.
  434.         jne    short not_sg
  435.         mov     env,SG_ENV
  436.         mov     _gda,edx
  437.         jmp    short Initialize_everything
  438. endif   
  439. if    eXOS
  440.     mov    env,XOS_ENV
  441. else    
  442. not_sg: mov     env,PL_ENV
  443. endif
  444.  
  445. ;INIT: Initialization code
  446. ; - set initial stackpointer, framepointer
  447. ; - calls FINIT and CFINIT to initialize file support
  448. ; - call  MAIN to invoke user's program
  449. ; - call  FTERM to close all open files
  450. ;
  451. ; Unneeded defn of DGROUP, since DS is fixed.
  452. ;dsgroup dw    DGROUP
  453.  
  454. ; Shorter than mov reg,-1
  455. getminus1 macro    reg
  456.     sub    reg,reg
  457.     dec    reg
  458.     endm
  459.  
  460. ifdef    HC
  461. Small_data_HC = 1
  462. endif
  463. SETBLOCK equ 4Ah
  464.  
  465. ; XOS environment start:
  466. ; Incoming registers:
  467. ; esi: initial amount of heap provided by loader, at tail end of DGROUP.
  468. ; ebx: pointer to argument strings.
  469. ; edi: pointer to program name.
  470. ; environ:
  471. ; ax:0:
  472. ;      (db 'var=value',0)*
  473. ;      (db 0)+      ; possibly some 0 padding for expansion later
  474. ; ax:edi:
  475. ;    db 'progname',0 ; fully-expanded (drive & path)
  476. ; ax:ebx:
  477. ;    db 'invoke name',0   ; the invocation prog name.
  478. ;    db 'arguments',0     ; 1 or more arguments.
  479. ;    db 0
  480. ; handle-table:
  481. ;    dd count
  482. ;    (db type, dd handle)*
  483. ;        type = 0 unused; 1 session; 2 file.
  484.  
  485. Initialize_everything:
  486.     sub    ebp,ebp     ;Initialize stack frame pointer
  487.     ; Make sure stack is mod 4 in case it's not.
  488.     and     esp,0fffffffch  ; Drop extra bytes.  Oh well.
  489.     assume    ds:DGROUP
  490.  
  491. if      eXOS
  492.         mov     word ptr envp+Word_size,ax    ; Offset is already 0.
  493.         ; mov    envp,0        ; This is already 0.
  494.         
  495.         mov    word ptr argp+Word_size,ax    ; Offset of arguments.
  496.         mov    dword ptr argp,ebx        ; Will be adjusted to skip prog name later.
  497.         
  498.         mov    word ptr prognamep+Word_size,ax
  499.         mov     dword ptr prognamep,edi   ; Save prog name offset.
  500.         
  501.         mov    ax,ds
  502.         lsl    eax,eax        ; Find total space.
  503.         mov    _heaphi,eax    ; End of heap.
  504.         sub    eax,esi        ; Start of heap.
  505.         mov    _top,eax
  506.         
  507. endif
  508.    
  509. ; For the 386 we own all of memory.  Size up memory and inform the
  510. ; heap manager.
  511.  
  512.     mov    Stack_margin_big_place,Stack_margin_big
  513.     mov    Stack_margin_small_place,Stack_margin_small
  514.     add    Stack_margin_big_place,offset start_of_stack
  515.     add    Stack_margin_small_place,offset start_of_stack
  516. ifdef  IGC_exists
  517.     cmp     env,SG_ENV
  518.     je    short SG_STACK
  519. endif   
  520. ifdef  PL_exists
  521.     mov    _base,0        ; Start of stack.
  522.     lea     eax,32[esp]     ; eax = start of heap + some padding for safety.
  523.     mov    _top,eax
  524.     mov    ax,ds
  525.     lsl    eax,eax        ; load segment limit of data segment.
  526.     mov    _heaphi,eax    ; Top of heap (linear address).
  527. endif   
  528. ifdef    IGC_exists
  529.     jmp    short more_init1
  530.     
  531. SG_STACK:
  532. ; Initialize stack, IGC environemnt.
  533. ; This code will work for h (highest) and a (append after load) stk options.  
  534. ; esp already setup by vmrun loader.
  535.     mov    eax,esp     ;get stack pointer
  536.     mov    ecx,[edx].GDA_STKSZ    ;get stack size, kbytes
  537.     shl    ecx,10        ;convert from k to # of bytes
  538.     sub    eax,ecx     ;calculate base of stack addr
  539.     mov    _base,eax    ;stack base
  540.     mov    eax,[edx].GDA_HLOD    ;get highest load address
  541.     mov    _top,eax    ;bottom of heap
  542.     mov    ecx,[edx].GDA_HMEM    ;get available high memory
  543.     shl    ecx,10        ;convert from k to # of bytes
  544.     add    eax,ecx     ;calculate heap top addr
  545.     mov    _heaphi,eax    ;top of heap
  546. ; Free memory below 640K for subsequent use by EXEC.
  547.     mov    ebx,[edx].GDA_TLOW    ; Subtract highest used low address.
  548.     sub    ebx,[edx].GDA_PSPA      ; Subtract lowest used low address. 
  549.     shr    ebx,4            ; Convert to paragraphs.
  550.     inc    ebx            ; Safety?
  551.     mov    ah,SETBLOCK         ; SETBLOCK to bx paragraphs from psp start.
  552.     int    21h
  553.     test    byte ptr [edx].GDA_ENV,GDA_WEITEK
  554.     setne   byte ptr _1167
  555. endif
  556.  
  557. more_init1:
  558. ;*******************************************************************************
  559. ; Remainder of initialization, independent of where stack lies.
  560. ;*******************************************************************************
  561.  
  562. ;*******************************************************************************
  563. ; Deal with 8087/287
  564. ; Discover whether 8087/287 exists unless no8087 has been set.
  565. ;*******************************************************************************
  566.  
  567. ifdef    no87
  568.     mov    byte ptr _8087,0
  569. else
  570. ; Initialize floating point:  check for existence of 8087/287.
  571. ; We have to do this here so that we can avoid printing out the contents
  572. ; of NO87 if the machine doesn't have an 8087.
  573.     fninit            ;initialize 8087 if one exists
  574.     xor    eax,eax        ;Initialize 8087 flag to zero.
  575.     mov    temp,ax
  576.     sub    ecx,ecx         ; One byte shorter than mov ecx,15.
  577.     mov    cl,15
  578. ;       mov    ecx,15        ; Set ch := 0 on first try.
  579. waste1: loop    waste1
  580.     fnstcw    temp         ; Store cntl word
  581.     ; We used to just test for non-zero on 8087 systems; but that
  582.     ; didn't work for 287s.  Even if no 287, IBM ATs returned
  583.     ; garbage as the control word.
  584.     mov    cl,15
  585. waste2: loop    waste2
  586.     and    temp,00f3fh
  587.     cmp    temp,0033fh    ; Processor status after initialization.
  588.     jne    short no_8087
  589.     fnstsw    temp
  590.     mov    cl,15
  591. waste3: loop    waste3
  592.     test    temp,0b8bfh
  593.     jnz    short no_8087
  594.     fldcw    cs:fp_init_cw_emc    ;load control word
  595.     ; EMC 87 will leave on the upper bit in the control word:
  596.     fstcw    temp
  597.     test    byte ptr temp+1,80h    ; EMC part there?
  598.     jz    short not_EMC
  599.     mov    byte ptr _387,1    ; EMC also looks like a 387.
  600.     ; We load the normal control word in case someone else stores
  601.     ; it and expects the top bit to be off.
  602.     fldcw    cs:fp_init_cw        ;load normal control word
  603.     mov    byte ptr _emc87,1    ;Say that it's present.
  604.     ; Now fall through to the code that will determine it's also a 387 clone.
  605. not_EMC:
  606.     mov    byte ptr _8087,1 ;Set to TRUE unless he requested to ignore the chip.
  607.         fld1
  608.         fldz
  609.         fdiv    ; get infinity
  610.         fld    st      ; Duplicate TOS.
  611.         fchs
  612.         fcompp    ; compare negative infinity with infinity.
  613.         fstsw    ax  
  614.         fwait
  615.         sahf
  616.         je    short no_8087 ; 387 says -inf <> +inf.  87/287 says they're equal.
  617.         mov     byte ptr _387,1
  618. no_8087:
  619. endif
  620.  
  621. ifndef    NOWTK
  622. ifdef    DOS
  623. ;*******************************************************************************
  624. ; Deal with Weitek 1167
  625. ; Pharlap uses fs:; IGC uses ffc0_0000.
  626. ; AIA with PharLap linker uses fs:
  627. ; AIA with Lahey linker uses selector F8h we must load fs explicitly.
  628. ;*******************************************************************************
  629.         ; Early versions of the emc87 will hang if given weitek code.
  630.     cmp    byte ptr _emc87,1
  631.     je    Skip_all_weitek_processing
  632. seg_ldctx macro
  633.     ;pop    fs:[0c000h]
  634.     ; Until the assembler will allow address mode override, inline code a 1-byte-shorter move:
  635.     db    67h,64h,8fh,06h,00,0c0h
  636.     endm
  637. seg_stctx macro
  638.     db    67h,64h,0a1h,00h,0c4h    ; store context to eax.
  639.     endm
  640. flat_ldctx macro
  641.     pop    ds:[0ffc0c000h]
  642.     endm
  643. flat_stctx macro
  644.     pop    ds:[0ffc0c400h]
  645.     endm
  646.     
  647.         push     03ff0000h      ; truncate (1ff = round to nearest).
  648.         push     30000000h      ; 
  649.         push    0a0000000h      ; 1165 accum timer
  650.         push     64000000h      ; 1164 accum timer
  651.     push     16000000h      ; 1164/1165 flowthrough timer, 16 mhz
  652.     push     98000000h    ; 20 mhz part init
  653.     push     56000000h    ; 20 mhz part
  654.     push    0b8000000h    ; test speed of chip.
  655.     
  656.     ; ldctx 1600_0000 1164/1165 flowthrough timer.
  657.     ; ldctx 6400_0000 1164 accumulate timer.
  658.     ; ldctx a000_0000 1165 accumulate timer.
  659.     ; ldctx 3000_0000 reserved mode bits.
  660.     ; ldctx 01ff_0000 rounding modes/exception mask.
  661. ifdef    IGC_exists
  662.     cmp    env,SG_ENV
  663.     je    short SG_weitek
  664. endif   
  665. ifdef    PL_exists
  666.     ; Check that fs <> ds.  If so, Weitek installed at fs:.
  667.     mov    ax,fs
  668.     mov    bx,ds
  669.     cmp    ax,bx
  670.     je    short NW1
  671.     and    ax,ax    ; If fs = 0 this was linked with Lahey linker.
  672.     sete    Lahey_format_load_file
  673.         jne     short go_ahead; if this isn't Lahey we are already (fs = weitek)
  674.         mov     ax, 0F8h     ; test the f8 selector to see if it exists
  675.         lar     bx, ax
  676.         jnz     short NW1    ; if no then OS386 does not find a Weitek
  677.         test    bh, 80h
  678.         jz    short NW1    ; if f8 exists but present bit is not set
  679.                      ; os386 does not find weitek    
  680.         mov     fs, ax
  681. go_ahead:
  682.     mov    _1167,1
  683.     ; Until the assembler will allow address mode override, inline code a 1-byte-shorter move:
  684.     seg_ldctx ;    load ctx b8_000_000
  685.     seg_stctx ;    store context to eax.
  686.     and     ah,80h
  687.     jnz    short _20MHZ_part
  688.     pop    eax     ; Delete 20 mhz init stuff.
  689.     pop    eax
  690.     seg_ldctx
  691.     jmp    short common_1167
  692. NW1:    jmp    short No_weitek    
  693. _20MHZ_part:
  694.     seg_ldctx
  695.     seg_ldctx
  696.     pop    eax    ; Kill the 16 mhz init.
  697. common_1167:    
  698.     seg_ldctx
  699.     seg_ldctx
  700.     seg_ldctx
  701.     seg_ldctx
  702.     jmp    short Finish_weitek
  703. endif   
  704. SG_weitek:
  705. ifdef    IGC_exists
  706.     cmp     byte ptr _1167,1
  707.     jne     short No_weitek
  708.     flat_ldctx ; for test.
  709.     flat_stctx ;    store context to eax.
  710.     and     ah,80h
  711.     jnz    short _20MHZ_part_flat
  712.     pop    eax     ; Delete 20 mhz init stuff.
  713.     pop    eax
  714.     flat_ldctx
  715.     jmp    short common_1167_flat
  716. _20MHZ_part_flat:
  717.     flat_ldctx
  718.     flat_ldctx
  719.     pop    eax    ; Kill the 16 mhz init.
  720. common_1167_flat:
  721.     flat_ldctx
  722.     flat_ldctx
  723.     flat_ldctx
  724.     flat_ldctx
  725.     flat_ldctx
  726.     jmp    short Finish_weitek
  727. endif    
  728. No_weitek:      
  729.     add    esp,8*4 ; Get rid of the junk.
  730. Finish_weitek:
  731. Skip_all_weitek_processing:
  732. endif
  733. endif
  734.  
  735. ifdef    DOS
  736. ;*******************************************************************************
  737. ; Process environment area and parameter strings.
  738. ;*******************************************************************************
  739. Parm_string_offset = 80h        ; Offset in PSP containing parm string (len+bytes).
  740. ifdef  IGC_exists
  741.     cld            ;All moves are forward
  742.     
  743.         cmp     env,PL_ENV
  744.         je    short PL_PSP
  745. ; GDA has pointer to PSP.  PSP has env seg, which, shifted left by 4,
  746. ; yields the 32 bit address of the env.
  747.     mov     edi,[edx].GDA_PSPA    ; Get flat PSP address.
  748.     mov    word ptr argp+Word_size,ds
  749.     mov     dword ptr _psp,edi
  750.     mov    word ptr _psp+Word_size,ds
  751.     lea     eax,Parm_string_offset[edi]     ; eax = pso+edi.
  752.     xor     ebx,ebx
  753.     mov    bl,[eax]       ; Get length of parm string.
  754.     mov    arglen,ebx
  755.     inc    eax
  756.     mov     dword ptr argp,eax    ; Addr of parm string.
  757.     mov    bx,envptr[edi]    ; Get segment address of environment pointer.
  758.     shl    ebx,4           ; Convert to 32-bit flat address.
  759.     mov    dword ptr envp,ebx
  760.     mov    word ptr envp+Word_size,ds    ; Fill out 48-bit address
  761.     jmp    short more_init2
  762. PL_PSP: 
  763. endif
  764.  
  765. if    ePL_exists or eXOS
  766. if    ePL_exists
  767. PSPseg    equ    24h     ; Pointer to DOS's Program segment prefix: Phar Lap.
  768. ENVseg    equ    2ch     ; Pointer to DOS's environment string: Phar Lap.
  769.     cmp    Lahey_format_load_file,1
  770.     je      short ES_points_to_PSP_already
  771.     mov    ax,PSPseg
  772.     mov    bx,cs
  773.     arpl    ax,bx
  774.     mov    es,ax        ;Load es with psp address.
  775.     ; Load environment segment into cx.
  776.         mov    cx,ENVseg
  777.         arpl    cx,bx
  778.         jmp     short more 
  779. ES_points_to_PSP_already:
  780.     ; Load environment segment into cx.
  781.     mov     cx,es:02ch
  782.     mov     ax,es
  783. more:
  784.     mov    word ptr _psp+Word_size,ax      ; Construct 48-bit psp address.
  785.         mov    word ptr escontents+Word_size,ax    ;No displacement
  786.         mov    word ptr envp+Word_size,cx    ; Environment segment.
  787.         xor    eax,eax
  788.     mov    al,es:Parm_string_offset ;Length of parm string
  789.     mov    arglen,eax
  790.     mov    esi,Parm_string_offset+1
  791. endif
  792. if    eXOS
  793. ;    Compute arglen.  First skip over the useless invocation name.
  794.     les     edi,argp
  795.     getminus1 ecx
  796.     xor    eax,eax
  797.     repnz   scasb   ; Search for 0.
  798.     ; edi now points to the byte afterwards; it must point to the
  799.     ; argument string.
  800.     mov    dword ptr argp,edi    ; Points to command-line arguments.
  801.     mov    esi,edi        ; Save for what comes next in HC.
  802.     mov    ebx,edi        ; Start pointer
  803.     repnz    scasb        ; Look for terminating 0.
  804.     sub    edi,ebx        ; arglen; includes the 0.
  805.     dec    edi
  806.     mov    arglen,edi    ; Length of arugment string.
  807.     mov    eax,edi        ; For what comes next.
  808. endif
  809.  
  810. ; In C, the parameter string must be moved to a DS-accessible area
  811. ; if small-data model.
  812. ifdef    HC
  813. ; Move the parm string into the stack so that it can be accessed by
  814. ; small-data programs with only 16-bit pointers.
  815.     add    eax,3
  816.     and    al,0fch    ; Make sure eax is multiple of 4.
  817.     sub    esp,eax    ; Length of parm string.
  818.     mov    edi,esp    ; Move the parameter string here.
  819.     mov    dword ptr argp,edi ; Save address of args.
  820.     push    edx    ; Allow byte for parm string overwrite by C arg processor.
  821.             ; but make stack word-aligned for efficiency.
  822.     mov    ecx,eax    ; parameter length
  823.     push    ds    ; Save it.
  824.     push    es    ; source is es:esi
  825.     pop    ds
  826.     push    es    ; Save es.
  827.     push    ss
  828.     pop    es    ; Dest is ss:di.
  829. ;    mov    esi,Parm_string_offset+1    ; Set up earlier.
  830.     rep    movsb    ; es:di := parm string.
  831.     pop    es
  832.     pop    ds
  833. else
  834. ; Large-data or Pascal model; just store the address of the parms.
  835. if      not eXOS
  836.     mov    ax,word ptr escontents+Word_size
  837.     mov    word ptr argp+Word_size,ax    
  838.     mov    dword ptr argp,Parm_string_offset+1    ; Addr of parm string.    
  839. endif   
  840. endif   
  841. endif
  842.  
  843. more_init2:
  844.  
  845. if    not eXOS
  846. ; In DOS 3.0 and higher, the program name is stored at the end of the
  847. ; environment variable area, terminated by a 0 byte.
  848. ; We need to discover DOS version to see if we should get the pname.
  849.     sub    eax,eax
  850.     mov    ah,30h        ; Get DOS version number
  851.     int    21h
  852.     mov    word ptr _osmajor,ax    ; Moves minor (AH) and major (AL).
  853.     cmp    env,SG_ENV
  854.     je    short no_change
  855.     shr    eax,16
  856.     cmp     ax,'DX'
  857.     jne        short to_ai       ; by default this must be AIA's OS386
  858. ; Phar Lap.
  859. ifndef    PHAR_LAP_CAN_GROW_HEAP    
  860.     jmp     short no_change
  861. else     
  862.     ; Now free all of the heap, so that we allocate more only when necessary.
  863.     mov    ax,4
  864.     mov    es,ax
  865.     mov    ebx,es:[5ch]        ; Initial size of heap: load image size in bytes.
  866.                                     ; See Phar Lap TN #21.
  867.     jmp     short Free_up           
  868. endif    
  869. to_ai:
  870.         mov     env,AI_ENV
  871.     mov    ebx, _top        ;top of stack in bytes
  872. ifndef  AIA_CAN_GROW_HEAP
  873.     cmp    Lahey_format_load_file,1
  874.     jne     short no_change
  875.     ; If Lahey format, we must be able to grow.
  876. endif
  877. Free_up:
  878.     add    ebx,4095        ; Round up to pages.
  879.     shr     ebx,12                  ; Convert to 4K pages.
  880.     inc    ebx              ; Add 1 page for initial heap.
  881.     mov    cur_pages, ebx
  882.     mov    edx, ebx
  883.     shl    edx,12                  ; Future value for heaphi.
  884.     cmp    env,PL_ENV
  885.     je     short No_para
  886.     shl    ebx, 8            ; Convert pages to paragraphs for AIA.
  887.     cmp    Lahey_format_load_file,1
  888.     jne     short No_para     ; if AI_ENV and PL linker skip to allocation
  889.                                   ; else must be AI_ENV and Lahey Linker so 
  890.                                   ; we must grow the parent segment first
  891.     call    grow_parent_segment
  892. No_para:    
  893.     push    ds
  894.     pop     es                      ; Segment to free up.
  895.     mov    ah,SETBLOCK         ; SETBLOCK to bx paragraphs from psp start.
  896.     int    21h
  897.     jc    short no_change         ; If couldn't get the extra page, oops!
  898.     mov    _heaphi,edx
  899. no_change:
  900. endif
  901.  
  902. doesnt_want_8087 macro
  903. ; All this fuss just to print the NO87 string!
  904. ifndef    no87
  905.     push    eax
  906.     push    edi    ; We're going to clobber these.
  907.     cmp    _8087,0
  908.     je    short no_print; No 87 exists on this machine; don't bother to print.
  909.     mov    _8087,0 ; Set false.
  910.     add    edi,5
  911.     mov    esi,edi    ; Copy for later.
  912.     mov    al,' '
  913.     repe    scasb
  914.     dec    edi
  915.     cmp    byte ptr es:[edi],0     ; Did we get to end of string?
  916.     je    short no_print
  917.     mov    edi,esi    ; Now print the message, one character at a time.
  918. again:    mov    dl,es:[edi]
  919.     and    dl,dl
  920.     je    short end_of_string
  921.     mov    ah,6    ; Direct Console I/O.
  922.     int    21h    ; Print character.
  923.     inc    edi
  924.     jmp    again
  925. end_of_string:
  926.     mov    dl,0dh    ; \r\n.
  927.     mov    ah,6
  928.     int    21h    ; Print character.
  929.     mov    dl,0ah
  930.     mov    ah,6
  931.     int    21h    ; Print character.
  932. no_print:
  933.     pop    edi
  934.     pop    eax
  935. endif    ; no87
  936.     endm
  937.  
  938. Find_prog_name:
  939. ;     -- Format of DOS environment:         VVV 3.x only VVV
  940. ;     -- t1 nul t2 nul t3 nul ... tn nul nul x x program-name nul
  941. ; Go to end of environment string to get program name for DOS 3.0.
  942. ; While we're doing so, see if he said "NO87=" something, in which case,
  943. ; mimicking Microsoft's emulator, we print the string (unless it's
  944. ; nothing but blanks), and disable use
  945. ; of the 80287 if the combination emulation/80287 library is linked in.
  946.     les    edi,envp    ; Pointer to environment area.
  947.     cmp     byte ptr es:[edi],0    ; No environment?
  948.     je      no_environment_at_all
  949.     xor    eax,eax        ; search for 0 byte.
  950. Scan_again:
  951.     cmp    dword ptr es:[edi],'78ON'   ; NO87
  952.     jne    short not1
  953.     cmp    byte ptr es:4[edi],'='   ; =
  954.     jne    short not1
  955.     doesnt_want_8087    ; Macro back-substituted here.
  956. not1:    getminus1 ecx           ; Search lotsa bytes.
  957.         repnz    scasb        ; Search for 0.
  958. ; We MUST have found the 0 byte; we're positioned at the byte after.
  959.     cmp    byte ptr es:[edi],0    ; Two 0 bytes in a row?
  960.     jne    Scan_again    ; Nope, keep going.
  961. if    not eXOS
  962. ; Now we've found the environment area end.  +3 bytes later is the prog name.
  963.     add    edi,3        ; Move to program name.
  964.     cmp    _osmajor,3    ; Program name supplied by OS?
  965.     jb      short NO_PNAME_AVAIL
  966.     cmp     env,SG_ENV
  967.     jne     short get_pname
  968.     cmp     env,AI_ENV
  969.     je      short get_pname
  970.     ; IGC: pname is addressable.
  971.     mov    dword ptr prognamep,edi
  972.     mov    word ptr prognamep+Word_size,ds
  973.     jmp    short _prog_name
  974.  
  975. NO_PNAME_AVAIL:
  976. ; No program name.  Supply the null string.
  977. ifdef    HC
  978. ; Allocate the null byte on the stack right after the parms.
  979.     xor    edx,edx
  980.     push    edx        ; Null byte(s).
  981.     mov    dword ptr prognamep,esp     ; Pointer to the program name.
  982. endif
  983.     jmp    short _prog_name
  984. endif    ; not XOS
  985.  
  986. get_pname:
  987. if      ePL_exists or eXOS
  988. PL_PN:        
  989. if    eXOS
  990.     les    edi,fword ptr prognamep    ; or pword ptr prognamep.
  991. endif   
  992. ; In small-data C, the program name must be moved into the DS group.
  993. ifdef    Small_data_HC        ; Move the program name to the stack.
  994.     xor    eax,eax
  995.     ; Find length of program name.
  996.     getminus1 ecx
  997.     mov    ebx,edi        ; Save starting address of name.
  998.     repnz    scasb
  999.     sub    edi,ebx        ; Length of name (including 0 trailer).
  1000.     lea     eax,3[edi]    ; Add some space on stack...
  1001.     and    eax,0fffch    ; Ensure mod 4 for nice value for SP.
  1002.     sub    esp,eax        ; Allocate space for name.
  1003.     mov    dword ptr prognamep,esp     ; Where the name will be put.
  1004.     mov    ecx,edi        ; Length of name
  1005.     mov    esi,ebx        ; Name is stored here.
  1006.     mov    edi,esp        ; Copy to here.
  1007.     push    ds
  1008.     mov    ds,word ptr envp+Word_size
  1009.     push    ss
  1010.     pop    es
  1011.     rep    movsb
  1012.     pop    ds
  1013. else
  1014.     ; Non-small data case:    just record the address.
  1015.     mov    dword ptr prognamep,edi
  1016.     mov    word ptr prognamep+Word_size,es
  1017. endif
  1018. endif
  1019.  
  1020. no_environment_at_all:
  1021. _prog_name:
  1022.  
  1023. ifdef HC
  1024.     ; Now allocate the space for the argv pointers.  One for the program name
  1025.     ; and one for each argument.  Although we don't know how many arguments there
  1026.     ; are, there can be at most 1 for every two characters of the environment
  1027.     ; string.
  1028.         mov     eax,arglen
  1029.         inc    eax
  1030.         shr    eax,1    ; Max arg ptrs for parameters
  1031.         inc    eax    ; Count the program name.
  1032.         inc    eax    ; ANSI requires argv[argc] = null pointer.
  1033.         shl    eax,2    ; Multiply by pointer size
  1034.         sub    esp,eax    ; Now allocate it.
  1035.         mov    dword ptr argvp,esp     ; sp is here.
  1036. endif    ; HC
  1037.  
  1038. endif    ; DOS
  1039.  
  1040. ;call file and user initialization, call main program
  1041.  
  1042.     assume    ds:DGROUP
  1043.     push    ds
  1044.     pop    es
  1045.     ; ss is already = ds.
  1046.     ; Since this is in Pascal, we must initialize ds first!
  1047. ;       call    init_interrupts
  1048. ; Phar lap asssembler won't take:
  1049. ;    pcall    finit ;initialize Pascal file system.
  1050.  
  1051.     mov    ebx,offset ds:_mwinitfrstcall
  1052.     mov    ecx,offset ds:_mwinitlastcall
  1053.     sub    ecx,ebx
  1054. mustcall:    or    ecx,ecx
  1055.     jz    mustdone
  1056.     mov    edi,[ebx]
  1057.     add    ebx,4
  1058.     sub    ecx,4
  1059.     ifndef    Small_code
  1060.     mov    esi,[ebx]
  1061.     add    ebx,2
  1062.     sub    ecx,2
  1063.     endif
  1064.     or    edi,edi
  1065.     jz    mustcall
  1066.     push    ebx
  1067.     push    ecx
  1068.     ifdef    Small_code
  1069.     call    edi
  1070.     else
  1071.     push    edi
  1072.     push    esi
  1073.     mov    ebx,sp
  1074.     call    dword ptr [ebx]
  1075.     pop    ecx
  1076.     pop    ecx
  1077.     endif
  1078.     pop    ecx
  1079.     pop    ebx
  1080.     jmp    mustcall
  1081.  
  1082. mustdone:
  1083.  
  1084.     pcall    _mwfinit ;initialize Pascal file system.
  1085.     pcall    cfinit        ;initialize C file system.
  1086. ifdef HC
  1087. ; In preparation for calling main, push addr of argv.
  1088. ifndef    Small_data
  1089.     push    word ptr Argvp+2    ; push segment
  1090. endif    
  1091.     push    dword ptr argvp    ; Push offset.
  1092.     sub    eax,eax        ; In case he supplies dummy routine:  argc = 0.
  1093.     pcall    set_up_args    ; Find argv values by scanning argument string.
  1094.     push    eax        ; Push computed ArgC.
  1095. endif
  1096. ifdef    DOS
  1097. ; Now check if he used the 1167, but it doesn't exist.
  1098. _MW1167_USED1 segment common byte 'DATA'
  1099. magic6  dw    1 dup(?)    ; Not initialized.
  1100. offoops6 dd    1 dup(?)    ; Not initialized.
  1101. oopsptr6 dd     1 dup(?)        ; Not initialized.
  1102. _MW1167_USED1 ends
  1103.     cmp    byte ptr _1167,1 
  1104.     je     short OK3             ; If 8087 there, no further checking needed.
  1105.     cmp    magic6,0abcdh
  1106.     jne    short OK3
  1107.     mov    eax,oopsptr6
  1108.     cmp    eax,offoops6
  1109.     jne    short OK3
  1110.     mov     edx,oopsptr6
  1111.     jmp    short more_message
  1112. OK3:
  1113. ; Now check if he used the Cyrix EMC 87, but it doesn't exist.
  1114. _MWEMC_USED1 segment common byte 'DATA'
  1115. magic7  dw    1 dup(?)    ; Not initialized.
  1116. offoops7 dd    1 dup(?)    ; Not initialized.
  1117. oopsptr7 dd     1 dup(?)        ; Not initialized.
  1118. _MWEMC_USED1 ends
  1119.     cmp    byte ptr _emc87,1 
  1120.     je     short OK4             ; If 8087 there, no further checking needed.
  1121.     cmp    DGROUP:magic7,0abcdh
  1122.     jne    short OK4
  1123.     mov    eax,DGROUP:oopsptr7
  1124.     cmp    eax,DGROUP:offoops7
  1125.     jne    short OK4
  1126.     mov     edx,DGROUP:oopsptr7
  1127.     jmp    short more_message
  1128. OK4:
  1129. ; Now check if he used the 8087, but it doesn't exist.
  1130. ; Here is how we determine if he dragged in fltused from the library:
  1131. ; magic will have a "magic" value, and offoops will have the offset of
  1132. ; the "oops" message.  If _mw87_used is not hauled in, magic and offoops
  1133. ; will be 0 when using all linkers under MS-DOS; on the Intel linkers 
  1134. ; they wil be garbage and WE HOPE THAT the fields won't accidentally  
  1135. ; look correct.  This is not foolproof, therefore, with linkers that don't  
  1136. ; zero out unitialized memory,  but it is much
  1137. ; cheaper than checking in the RTL for the 8087 presence for each 8087 
  1138. ; operator invoked.  I WISH OMF provided a "segment length"
  1139. ; fixup; then this could be made foolproof.
  1140. _MW87_USED1 segment common byte 'DATA'
  1141. magic   dw    1 dup(?)    ; Not initialized.
  1142. offoops dd    1 dup(?)    ; Not initialized.
  1143. oopsptr dd      1 dup(?)        ; Not initialized.
  1144. _MW87_USED1 ends
  1145.     cmp    byte ptr _8087,1 
  1146.     je     short OK              ; If 8087 there, no further checking needed.
  1147.     cmp    magic,0abcdh
  1148.     jne    short OK
  1149.     mov    eax,oopsptr
  1150.     cmp    eax,offoops
  1151.     jne    short OK
  1152.     mov     edx,oopsptr 
  1153. more_message:
  1154.     mov    ah,9
  1155.     int     21h
  1156.     jmp     Quit
  1157. OK:     ; Did he require 387, and is it here?
  1158. _MW387_USED1 segment common byte 'DATA'
  1159. magic3  dw    1 dup(?)    ; Not initialized.
  1160. _MW387_USED1 ends
  1161.     cmp    byte ptr _387,1
  1162.     je      short OK2
  1163.     cmp     magic3,0abcdh
  1164.     jne     short OK2
  1165.     ; He used it, but it's not present.
  1166.     mov     edx,cs:oops3ptr 
  1167.     mov    ah,9
  1168.     int    21h
  1169.     mov    edx,oopsptr
  1170.     add    edx,10    ; Skip past "8087/80287".
  1171.     jmp    more_message
  1172. _387msg db      '80387','$'
  1173. oops3ptr dd     offset _387msg
  1174. OK2:    
  1175.     
  1176. endif    
  1177.         jmp    Init_return
  1178. fp_init_cw dw 03FFH       ; For initializing 8087/287.
  1179. fp_init_cw_emc dw 83FFH       ; For initializing EMC 87.
  1180.     ; The 8000 is for testing presence of EMC 87 part.
  1181.     assume    es:nothing
  1182.  
  1183. INIT    endp
  1184.  
  1185. ; Next three routines are used by sysalloc and sysfree.
  1186.  
  1187. ;**************************************************************************
  1188. ;      function Heaplo(): Unsigned;  ; Returns bottom of heap space.
  1189. ;**************************************************************************
  1190. ;    This function returns the starting address of the heap.
  1191. ;    The heap is just above the stack.
  1192.  
  1193.     db    0
  1194. heaplo proc    far
  1195.     publab    heaplo
  1196.     ; return ss:_top; paragraph if non-small-data model.
  1197.     mov    eax,_top
  1198.     add    eax,16
  1199.     return
  1200. heaplo endp
  1201.  
  1202. ;**************************************************************************
  1203. ;    function Heaphi(): Unsigned;  ; Returns top of heap space.
  1204. ;**************************************************************************
  1205. ;    This returns the estimated top of the area that can be used
  1206. ;    for the heap.
  1207.  
  1208.     db    0
  1209. heaphi    proc    far
  1210.     publab    heaphi
  1211.     mov    eax,_heaphi
  1212.     return
  1213. heaphi    endp
  1214.  
  1215. if    AIA_CAN_GROW_HEAP
  1216. grow_parent_segment proc near    
  1217.         push    ebx             ; save regs that get altered
  1218.         push    edi
  1219.         push    es
  1220.  
  1221.         push    ebx             ; save paras - we need BX for OS386 call
  1222.         push    edx        ; this int 21 trashes edx
  1223.         mov     ax, 0ED00h      ; get info on segment which is to be grown
  1224.         mov     bx, ds
  1225.         int     21h             
  1226.         pop    edx        ; restore edx
  1227.         pop     ebx             ; DI now contains parent segment for DGROUP
  1228.  
  1229.         mov     es, di          ; now shrink this segment to paras in EBX
  1230.         mov     ah, SETBLOCK
  1231.         int     21h
  1232.  
  1233.         pop    es
  1234.         pop     edi        ; restore regs
  1235.         pop     ebx
  1236.         ret
  1237. grow_parent_segment endp
  1238. endif
  1239.  
  1240. ; The heap manager calls this routine to expand the heap when it
  1241. ; detects a heap overflow.  The expansion expands allocates more memory 
  1242. ; starting at _heaphi.  Record the new top-of-heap in _heaphi.
  1243. ; Currently this is implemented only for Phar Lap's DOS|Extender and
  1244. ; AIA's OS386.
  1245. expand_heap proc far
  1246.     publab    expand_heap
  1247. if    not eXOS
  1248.     push    ebx
  1249.         ; Has the user shut off heap expansion?  
  1250.         cmp    heap_expansion_enabled,CANT_EXPAND
  1251.         je    short Cant_grow
  1252.         cmp     env,PL_ENV
  1253. ifndef  PHAR_LAP_CAN_GROW_HEAP
  1254.     je      short Cant_grow ; Must have release >= 1.1t.
  1255. else
  1256.     je    short Can_grow    
  1257. endif   
  1258. ifndef    AIA_CAN_GROW_HEAP
  1259.     cmp    Lahey_format_load_file,1
  1260.     jne     short Cant_grow
  1261.     ; If Lahey format, we must be able to grow.
  1262. else    
  1263.     cmp     env,AI_ENV
  1264.     jne    short Cant_grow
  1265. endif   
  1266. Can_grow:
  1267.     mov    ebx,8[esp]    ; Request for more bytes.
  1268.     add    ebx,4095    ; Round to pages.
  1269.     shr    ebx,12
  1270.     add    ebx,cur_pages
  1271.     inc    ebx        ; Always have 4K of extra room.
  1272.     push    ebx        ; Save it.
  1273.     cmp     env,AI_ENV
  1274.     jne    short pages
  1275.     shl    ebx, 8        ; convert pages to paragraphs for AI.
  1276.     cmp    Lahey_format_load_file,1
  1277.     jne     short pages     ; if AI_ENV and PL linker skip to allocation
  1278.                                 ; else must be AI_ENV and Lahey Linker so 
  1279.                                 ; we must grow the parent segment first
  1280.         call    grow_parent_segment
  1281. pages:    
  1282.     mov    ah,SETBLOCK
  1283.     int    21h
  1284.     pop    eax        ; Amount requested.
  1285.     jc    short Cant_grow
  1286.     mov     cur_pages,eax
  1287.     shl    eax,12
  1288.     mov     _heaphi,eax
  1289.     ; mov    _heaphi,new top address of heap.
  1290. Cant_grow:
  1291.     pop    ebx
  1292. else 
  1293.     mov    eax,_heaphi    ; End of data segment currently.
  1294.     add     eax,4[esp]      ; He wants this much more heap added.
  1295.     inc    eax        ; New size requested.
  1296.     add     eax,4192        ; Always have 4K extra slop.
  1297.     add     eax,8192-1
  1298.     and    ax,not (8192-1)
  1299.     ; Round up to 8K segments.
  1300.     push    eax             ; Save the new size.
  1301.     sub    eax,eax
  1302.     mov    ax,ds
  1303.     push    eax
  1304.     push     0
  1305.     extrn    CPReallocSeg:near
  1306.     pcall   CPReallocSeg
  1307.     xor    eax,eax 
  1308.     jnz     short Cant_grow
  1309.         mov    ax,ds
  1310.         lsl    eax,eax
  1311.         mov    _heaphi,eax    ; Save new top.
  1312. Cant_grow:    
  1313. endif    
  1314.     return    4
  1315. expand_heap endp    
  1316.  
  1317. ;**************************************************************************
  1318. ;    procedure set_stack_limits(small,large:Cardinal);
  1319. ;**************************************************************************
  1320. ;    Set the two limits.
  1321. ;    This is called by the heap manager when the heap begins to creep
  1322. ;    into the stack, or when the heap has left the stack area.
  1323. ;    Basically, when the heap has used the lower portion of the stack,
  1324. ;    the stack margin variables are set to reflect a higher bottom-of-stack
  1325. ;    location, so that stack overflow will occur when the stack is within
  1326. ;    256 bytes of the heap.
  1327. ;    If the stack precedes the heap, the heap never creeps into the
  1328. ;    stack and this procedure will never be called.
  1329.  
  1330. Set_stack_limits    proc    far
  1331.     publab    set_stack_limits
  1332.     return    8
  1333. Set_stack_limits    endp
  1334. ;
  1335. ;**************************************************************************
  1336. ;    function ss: Cardinal; {Returns paragraph address of stack segment
  1337. ;**************************************************************************
  1338. ;
  1339. ssx    proc    far
  1340.     publab    ss
  1341.     mov    ax,ss
  1342.     return
  1343. ssx    endp
  1344.  
  1345. ;**************************************************************************
  1346. ;    function Getds: Cardinal;    -- Returns ds register.
  1347. ;**************************************************************************
  1348. ;    This function may actually no longer be needed.
  1349.  
  1350. ifdef    Small_data
  1351. getds    proc    far
  1352.     publab    getds    ; return ds register.
  1353.     mov    ax,ds
  1354.     return
  1355. getds    endp
  1356. endif
  1357.  
  1358. ?init    ends
  1359.     end    CGROUP:genesis
  1360.