home *** CD-ROM | disk | FTP | other *** search
/ Programming Languages Suite / ProgLangD.iso / Fortran.51 / DISK5 / OS2 / CRT0.AS$ / CRT0.bin
Text File  |  1989-08-31  |  12KB  |  509 lines

  1.     page    ,132
  2.     title    crt0 - OS/2 C start up routine
  3. ;***
  4. ;crt0.asm - OS/2 C start up routine
  5. ;
  6. ;    Copyright (c) 1986-1990, Microsoft Corporation, All Rights Reserved
  7. ;
  8. ;Purpose:
  9. ;    How startup works in a few words -
  10. ;
  11. ;    The startup and termination is performed by a few modules
  12. ;
  13. ;        crt0.asm    OS/2 specific init/term
  14. ;        crt0msg.asm    OS/2 error messages
  15. ;        crt0dat.asm    remainder of shared OS/2 init/term
  16. ;
  17. ;    *************  IMPORTANT  *****************************************
  18. ;
  19. ;    The "DOSSEG" directive in this module must not be removed or else
  20. ;    the user will have to link with the "/DOSSEG" linker switch in
  21. ;    order to get proper segment ordering.
  22. ;
  23. ;    See the C documentation for more information about the /DOSSEG switch.
  24. ;
  25. ;    All assembler modules must be assembled with the /Mx switch, i.e.
  26. ;
  27. ;        masm -Mx crt0,;
  28. ;
  29. ;*******************************************************************************
  30.  
  31. ;*******************************;*
  32.     DOSSEG            ;* specifies DOS SEGment ordering *
  33. ;*******************************;*
  34.  
  35. ;*******************************;*
  36.     INCLUDELIB OS2        ;* Library Search Record for "OS2.LIB"
  37. ;*******************************;*
  38.  
  39. ?DF=    1            ; this is special for c startup
  40.  
  41. .xlist
  42. include version.inc
  43. include cmacros.inc
  44. include msdos.inc
  45. include heap.inc
  46. include rterr.inc
  47. .list
  48.  
  49. ifdef FARSTACK
  50. ife sizeD
  51.     error <You cannot have a far stack in Small or Medium memory models.>
  52. endif
  53. endif
  54.  
  55.     page
  56. ;===========================================================================
  57. ;
  58. ;    Segment definitions
  59. ;
  60. ;    The segment order is essentially the same as in XENIX.
  61. ;    This module is edited after assembly to contain a dosseg comment
  62. ;    record for the linker.
  63. ;
  64. ;===========================================================================
  65.  
  66. createSeg _TEXT, code,    word,    public, CODE,    <>
  67. createSeg C_ETEXT,etext, word,    public, ENDCODE,<>
  68. createSeg _DATA, data,    word,    public, DATA,    DGROUP
  69. ifdef FARSTACK
  70. ; This segment has STACK class so it is at the end of DGROUP; it is the first
  71. ; entry in the near heap.
  72. createSeg NEARHEAP, stubheap, para, <>, STACK, DGROUP
  73. ; Here is the real stack, not in DGROUP
  74. createSeg STACK, stack, para,    stack,    STACK, <>
  75. else ; not FARSTACK
  76. createSeg STACK, stack, para,    stack,    STACK,    DGROUP
  77. endif ;FARSTACK
  78.  
  79. defGrp    DGROUP            ; define DGROUP
  80.  
  81. codeOFFSET equ    offset _TEXT:
  82. dataOFFSET equ    offset DGROUP:
  83.  
  84. page
  85.  
  86. public    __aDBused        ; debug value used by QC
  87.     __aDBused = 0d6d6h
  88.  
  89. public    __aDBdoswp
  90.     __aDBdoswp = 0d6d6h
  91.  
  92. public    __acrtused        ; trick to force in startup
  93.     __acrtused = 9876h    ; funny value not easily matched in SYMDEB
  94.  
  95. extrn    __acrtmsg:abs        ; trick to pull in startup messages
  96.  
  97.  
  98. sBegin    stack
  99. assumes ds,data
  100.     db    2560 dup (?)    ; default stack size (2.5 KB)
  101. sEnd
  102.  
  103. ifdef FARSTACK
  104. ; Set up the first entry in the near heap
  105. sBegin stubheap
  106.       stubheap_size    dw    1        ; 0-length free entry
  107.       stubheap_next    dw    _HEAP_END    ; mark end of heap
  108. sEnd
  109. endif ;FARSTACK
  110.  
  111.  
  112. page
  113.  
  114. sBegin    data
  115.  
  116. extrn    _edata:byte        ; end of data (start of bss)
  117. extrn    _end:byte        ; end of bss (start of stack)
  118.  
  119. externW __argc
  120. externDP __argv
  121. externDP environ
  122. externB _osfile
  123. externB _osmajor        ; Major and Minor versions of OS/2
  124. externB _osmode         ; real/protected mode flag
  125.  
  126.  
  127. ;    these are used by DOS C memory management (not used in Windows)
  128.  
  129. ;*
  130. ;*    The following (_acmdln and _aenvseg) must be in this order!
  131. ;*
  132. globalW _acmdln,0        ; Offset of command line string in env
  133. globalW _aenvseg,0        ; Selector of Environment segment
  134.  
  135. globalW _atopsp,0        ; top of stack (heap bottom)
  136. globalW _aexit_rtn,<codeoffset __exit> ; NEAR pointer
  137.  
  138.  
  139. ;*
  140. ;*    The following (_asizds and _nheap_desc) must be in this order!
  141. ;*
  142.  
  143. globalW _asizds,0        ; DGROUP size - 1 (in bytes)
  144.  
  145. labelW    <PUBLIC,_nheap_desc>    ; near heap descriptor
  146. _heap_seg_desc <0,_HEAP_NEAR OR _HEAP_MODIFY, 0,0,0,0,0,0>
  147. .ERRE    flags    eq    2    ; flags better be second word
  148.  
  149. .ERRE    _asizds+2    EQ    _nheap_desc    ; make sure!
  150.  
  151.  
  152. ;    special C environment string
  153.  
  154. labelB    <PUBLIC,_acfinfo>
  155. cfile    db    '_C_FILE_INFO='
  156. cfilex    db    0
  157. cfileln =    cfilex-cfile
  158.  
  159.  
  160. ;    Heap segment limits for compiler range checking
  161.  
  162. globalW _aseglo,1        ; lowest segment
  163. globalW _aseghi,0FFFFh        ; highest segment
  164.  
  165. globalW __aDBswpflg,0        ; QC smart debugger screen swap
  166. globalW __aDBrterr,0
  167.  
  168. sEnd
  169.  
  170.     page
  171.  
  172.  
  173. externP _cinit            ; run-time initializers
  174.  
  175. externP _NMSG_WRITE        ; pascal - write error message to stdout
  176. externP _FF_MSGBANNER        ; pascal - C/FORTRAN error message banner
  177.  
  178. externP _setargv        ; process command line arguments
  179. externP _setenvp        ; process environment
  180.  
  181. externP main            ; C main program
  182. externP exit            ; exit ( code )
  183.  
  184. if    sizeC
  185. extrn    __exit:far        ; _exit ( code) (cmacros name conflict)
  186. else
  187. extrn    __exit:near
  188. endif
  189.  
  190.     extrn    DOSGETVERSION:far
  191.     extrn    DOSGETMACHINEMODE:far
  192.  
  193. sBegin    code
  194. assumes cs,code
  195.  
  196. page
  197. ;***
  198. ;_astart - start of all C programs
  199. ;
  200. ;Purpose:
  201. ;    Startup routine to initialize C run-time environment.
  202. ;
  203. ;Entry:
  204. ;    OS/2 Start-Up Conditions:
  205. ;
  206. ;    DS    = Automatic Data Segment
  207. ;    SS:SP    = Stack Segment and Initial Stack Pointer
  208. ;    ES    = 0000
  209. ;    AX    = Selector of Environment Segment
  210. ;    BX    = Offset of Command Line in Environment Segment
  211. ;    CX    = Size of Automatic Data Segment (CX=0 means 65536 bytes)
  212. ;    BP    = 0000
  213. ;
  214. ;Exit:
  215. ;    Exits to OS/2 via exit().
  216. ;
  217. ;Uses:
  218. ;
  219. ;Exceptions:
  220. ;
  221. ;*******************************************************************************
  222.  
  223. labelNP <PUBLIC,_astart>    ; start address of all "C" programs
  224. ;
  225. ;
  226.  
  227.     cld            ; set direction flag (up)
  228.  
  229. ;
  230. ; Save initial values
  231. ;
  232.  
  233.     mov    [_aenvseg],ax    ; Handle of Environment Segment
  234.     mov    [_acmdln],bx    ; Offset of Command Line String
  235.  
  236.  
  237. ;
  238. ; Init size of dgroup
  239. ;
  240.  
  241.     dec    cx        ; cx = size DGROUP - 1
  242.     mov    [_asizds],cx    ; Size of Global Data Segment
  243.  
  244. ;
  245. ; Carve an initial near heap out of the bottom of the stack.
  246. ;
  247.  
  248.     mov    bx,dataoffset _nheap_desc ; ds:bx = near heap descriptor
  249.     mov    [bx].checksum,ds; save DS in heap descriptor
  250.  
  251. ifdef FARSTACK
  252.     ; initialize the near heap with a small entry in the stubheap segment
  253.     mov    [bx].segsize, dataOFFSET(stubheap_next) + 2
  254.     mov    [bx].last, dataOFFSET(stubheap_next)
  255.     mov    [bx].start, dataOFFSET(stubheap_size)
  256.     mov    [bx].rover, dataOFFSET(stubheap_size)
  257. else ;not FARSTACK
  258.     and    sp,not 1    ; make even (if not)
  259.     mov    [bx].segsize,sp ; save as segment size
  260.  
  261.     .ERRE    _HEAP_END -2    ; make sure they're equal
  262.     mov    ax,_HEAP_END    ; get end-of-heap flag
  263.     push    ax        ; into place
  264.     mov    [bx].last,sp    ; pointer to end-of-heap
  265.     not    ax        ; ax = 1 (0-length free entry)
  266.     push    ax        ; first heap entry
  267.     mov    [bx].start,sp    ; init start/rover
  268.     mov    [bx].rover,sp
  269. endif ;FARSTACK
  270.  
  271. ;
  272. ; Now initialize the top of stack location
  273. ;
  274.  
  275.     mov    [_atopsp],sp    ; Top of Stack Region
  276.  
  277. ;
  278. ;    get OS/2 version
  279. ;
  280.     push    ax
  281.     mov    ax,sp
  282.  
  283.     push    ss
  284.     push    ax        ; address for version
  285.     call    DOSGETVERSION
  286.     pop    ax
  287.     xchg    ah,al        ; swap bytes
  288.     mov    word ptr [_osmajor],ax
  289. ;
  290. ; Get real/protected mode flag
  291. ;
  292.     mov    ax,dataOFFSET _osmode
  293.     push    ds
  294.     push    ax
  295.     call    DOSGETMACHINEMODE
  296.  
  297. ;****
  298. ;*    C_FILE_INFO must be processed before _cinit() is called
  299. ;*    because _cinit() checks handles 0-2 for device/pipe.
  300. ;****
  301.  
  302. ;    fix up files inherited from child using _C_FILE_INFO
  303.  
  304.     call    inherit
  305.  
  306. ;    process command line and environment
  307.  
  308.     call    _setargv    ; crack command line
  309.     call    _setenvp    ; crack environment
  310.  
  311. ;
  312. ;    [NOTE: bp must be 0 at this point so that debug stack back
  313. ;    tracing works (i.e., end of stack is marked).  Since
  314. ;    OS/2 inits bp to 0, no extra code to do that is necessary.
  315. ;
  316.  
  317. ;    do necessary initialization
  318.  
  319.     call    _cinit        ; shared by OS/2 and Windows
  320.  
  321. ;    call main and exit
  322.  
  323. if    sizeD
  324.     push    word ptr [environ+2] ; the environment is not always in DS
  325. endif
  326.     push    word ptr [environ]
  327.  
  328. if    sizeD
  329.     push    word ptr [__argv+2] ; the arguments are not always in DS
  330. endif
  331.     push    word ptr [__argv]
  332.  
  333.     push    [__argc]    ; argument count
  334.  
  335.     call    main        ; main ( argc , argv , envp )
  336.  
  337. ; use whatever is in ax after returning here from the main program
  338.  
  339.     push    ax
  340.     callcrt exit        ; exit (AX)
  341.                 ;   _exit will call terminators
  342.  
  343. page
  344. ;***
  345. ;_amsg_exit, _cintDIV - Fast exit fatal errors
  346. ;
  347. ;Purpose:
  348. ;    Exit the program with error code of 255 and appropriate error
  349. ;    message.  cintDIV is used for integer divide by zero, amsg_exit
  350. ;    is for other run time errors.
  351. ;
  352. ;Entry:
  353. ;    AX    = error message number (amsg_exit only).
  354. ;
  355. ;Exit:
  356. ;    Calls exit() [cintDIV] or indirect through _aexit_rtn [amsg_exit].
  357. ;    For multi-thread: calls _exit() function
  358. ;
  359. ;Uses:
  360. ;
  361. ;Exceptions:
  362. ;
  363. ;*******************************************************************************
  364.  
  365. labelNP <PUBLIC,_cintDIV>
  366.  
  367.     assumes ds,nothing
  368. ifdef FARSTACK
  369.     mov    ax,DGROUP
  370.     mov    ds,ax
  371.     assumes ds,data
  372. else
  373.     assumes ss,data
  374. endif ;FARSTACK
  375.  
  376. ;    _NMSG_WRITE will reestablish ds = DGROUP
  377.  
  378.     mov    ax,_RT_INTDIV    ; Integer divide by zero interrupt
  379.     mov    [_aexit_rtn],codeoffset _exit ; call high-level exit()
  380.                 ; to cause file buffer flushing
  381.  
  382. labelNP <PUBLIC,_amsg_exit>
  383.     push    ax        ; message number for _NMSG_WRITE
  384.     callcrt _FF_MSGBANNER    ; run-time error message banner
  385.     callcrt _NMSG_WRITE    ; write error message to stdout
  386.  
  387.     assumes ds,data
  388.  
  389.     mov    ax,255
  390.     push    ax
  391. if sizeC
  392.     push    cs
  393. endif
  394.     call    word ptr [_aexit_rtn] ; _exit(255) ordinarily
  395.                 ; (or exit(255) for div by 0)
  396.                 ; NEAR routine pointer
  397.  
  398. page
  399. ;***
  400. ;inherit - process C_FILE_INFO variable from the environment
  401. ;
  402. ;Purpose:
  403. ;    locates and interprets the "C_FILE_INFO" environment variable.
  404. ;    The value of this variable is written into the "_osfile" array.
  405. ;
  406. ;    DOS and OS/2:    "_C_FILE_INFO=<AA><BB><CC><DD>" + "\0"
  407. ;
  408. ;        In this case the variable is a null-terminated string
  409. ;        (a well-formed environment variable) where each pair
  410. ;        of successive letters form one byte in _osfile.
  411. ;        The letters are in the range "A" through "P", representing
  412. ;        0 through 15.  The first letter of each pair is the more
  413. ;        significant 4 bits of the result.
  414. ;
  415. ;Entry:
  416. ;
  417. ;Exit:
  418. ;
  419. ;Uses:
  420. ;    AX, BX, CX, DX, SI, DI, ES
  421. ;
  422. ;Exceptions:
  423. ;
  424. ;*******************************************************************************
  425.  
  426.  
  427. inherit proc    near
  428.     mov    bx,cfileln
  429.     xor    di,di
  430.     mov    es,[_aenvseg]    ; ES:DI points to environment strings
  431.     mov    cx,07FFFh    ; environment max = 32K
  432.     cmp    byte ptr es:[di],0
  433.     jne    cfilp
  434.     inc    di        ; first environment string is null
  435. cfilp:
  436.     cmp    byte ptr es:[di],0 ; check for end of environment
  437.     je    nocfi        ;   yes - not found
  438.     mov    si,dataOFFSET cfile
  439.     mov    dx,cx        ; DX has count of bytes left in environment
  440.     mov    cx,bx        ; BX=cfileln
  441.     repe    cmpsb        ; compare for '_C_FILE_INFO='
  442.     mov    cx,dx        ; environment max = 32K
  443.     je    gotcfi        ;   yes - now do something with it
  444.     xor    ax,ax
  445.     repne    scasb        ; search for end of current string
  446.     je    cfilp        ; keep searching
  447. ;
  448.     jmp    short nocfi    ;   no 00 !!! - assume end of env.
  449. ;
  450. ;    found _C_FILE_INFO, so transfer handle info into _osfile
  451. ;
  452. gotcfi:
  453.     push    es
  454.     push    ds
  455.  
  456.     pop    es        ; es = DGROUP
  457.     mov    si,di        ; si = startup of _osfile info
  458.     pop    ds        ; ds = env. segment
  459.     assumes es,data
  460.     assumes ds,nothing
  461.  
  462.     mov    di,dataOFFSET _osfile ; di = _osfile block
  463.  
  464. ; _C_FILE_INFO:
  465. ;    Read in pairs of characters, expected to be ['A'..'P'].
  466. ;    Each pair represents one byte in the _osfile array.
  467. ;    A null is the normal terminator for the string.
  468. ;
  469.     mov    cl,4
  470. CL_FOUR equ    cl    ; normal can't
  471.  
  472. osfile_lp:
  473.     lodsb            ; get next byte (more significant 4 bits)
  474.     sub    al,'A'
  475.     jb    nocfi        ; string should terminate with a null
  476.     shl    al,CL_FOUR
  477.     xchg    dx,ax        ; save in DL
  478.  
  479.     lodsb            ; get next byte (less significant 4 bits)
  480.     sub    al,'A'
  481.     jb    nocfi
  482.     or    al,dl        ; this assumes that AL is in range
  483.     stosb
  484.     jmp    short osfile_lp
  485.  
  486. nocfi:
  487. ifdef FARSTACK
  488.     mov    ax,DGROUP
  489.     mov    ds,ax        ; ds = dgroup
  490. else
  491.     push    ss
  492.     pop    ds        ; ds = DGROUP
  493. endif
  494.     assumes ds,data
  495.  
  496.     ret
  497. inherit endp
  498.  
  499.  
  500. ; Location that holds DGROUP segment (necessary for .COM file support)
  501.  
  502. globalW _dataseg,DGROUP
  503.  
  504. sEnd
  505.  
  506. START_ADDR    equ <end _astart>
  507.  
  508.     START_ADDR
  509.