home *** CD-ROM | disk | FTP | other *** search
/ Programming Languages Suite / ProgLangD.iso / C++-7 / DISK7 / SOURCE / STARTUP / DOS / CRT0.AS$ / CRT0
Encoding:
Text File  |  1992-02-22  |  13.8 KB  |  620 lines

  1.     page    ,132
  2.     title    crt0 - C start up routine
  3. ;***
  4. ;crt0.asm - C start up routine
  5. ;
  6. ;    Copyright (c) 1985-1992, 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    DOS 2.x/3.x specific init/term
  14. ;        crt0msg.asm    DOS 2.x/3.x error messages
  15. ;        (winstart.asm)    Windows specific init/term (not included)
  16. ;
  17. ;        crt0dat.asm    remainder of shared DOS 3.x init/term
  18. ;
  19. ;    *************  IMPORTANT  *****************************************
  20. ;
  21. ;    The "DOSSEG" directive in this module must not be removed or else
  22. ;    the user will have to link with the "/DOSSEG" linker switch in
  23. ;    order to get proper segment ordering.
  24. ;
  25. ;    See the C documentation for more information about the /DOSSEG switch.
  26. ;
  27. ;    All assembler modules must be assembled with the /Mx switch, i.e.
  28. ;
  29. ;        masm -Mx crt0,;
  30. ;
  31. ;    .COM Files:
  32. ;    (1) Start at location 0x100
  33. ;    (2) No stack segment
  34. ;    (3) All segments grouped together
  35. ;    (4) All seg registers the same at _astart.
  36. ;
  37. ;*******************************************************************************
  38.  
  39. ;*******************************;*
  40.     DOSSEG            ;* specifies DOS SEGment ordering *
  41. ;*******************************;*
  42.  
  43. ?DF=    1            ; this is special for c startup
  44.  
  45. .xlist
  46. include version.inc
  47.  
  48. include cmacros.inc
  49. include msdos.inc
  50. include defsegs.inc
  51. include heap.inc
  52. include rterr.inc
  53. .list
  54.  
  55.     _DEBUGSCREEN equ 1    ; debug screen swapping
  56.     _FATALHOOK equ 1        ; enable fatal hook code
  57.  
  58. ifdef FARSTACK
  59. ife sizeD
  60.     error <You cannot have a far stack in Small or Medium memory models.>
  61. endif
  62. endif
  63.  
  64. ifdef    _COM_
  65.     if sizeC or sizeD
  66.     error <Must use Small memory model for .COM files.>
  67.     endif
  68. endif    ;_COM_
  69.  
  70.     page
  71. ;===========================================================================
  72. ;
  73. ;    Segment definitions
  74. ;
  75. ;    The segment order is essentially the same as in XENIX.
  76. ;    This module is edited after assembly to contain a dosseg comment
  77. ;    record for the linker.
  78. ;
  79. ;===========================================================================
  80.  
  81. CrtDefSegs <code,etext,data>
  82. CrtDefSegs <xiqcseg>
  83.  
  84. ifndef _COM_
  85. CrtDefSegs <stack>
  86. else
  87. DefGrpCom            ; Group all segments in DGROUP
  88. endif
  89.  
  90. codeOFFSET equ    offset _TEXT:
  91. dataOFFSET equ    offset DGROUP:
  92.  
  93.  
  94. page
  95.  
  96. public    __acrtused        ; trick to force in startup
  97.     __acrtused = 9876h    ; funny value not easily matched in SYMDEB
  98.  
  99.  
  100. extrn    __acrtmsg:abs        ; trick to pull in startup messages
  101.  
  102.  
  103. _STACK_SIZE = 2048        ; Default stack size = 2K
  104.  
  105. ifndef _COM_
  106. sBegin    stack
  107. assumes ds,data
  108.     db    _STACK_SIZE dup (?)    ; stack space
  109. sEnd
  110. endif    ;_COM_
  111.  
  112. ifdef FARSTACK
  113. ; Set up the first entry in the near heap
  114. ; (see defsegs.inc definition of <stack>)
  115. sBegin stubheap
  116.       stubheap_size    dw    1        ; 0-length free entry
  117.       stubheap_next    dw    _HEAP_END    ; mark end of heap
  118. sEnd
  119. endif ;FARSTACK
  120.  
  121. page
  122.  
  123. externP main            ; C main program
  124.  
  125. externP exit            ; exit ( code )
  126.  
  127. if    sizeC
  128. extrn    __exit:far        ; _exit ( code) (cmacros name conflict)
  129. else
  130. extrn    __exit:near
  131. endif
  132.  
  133.  
  134. ifdef _DEBUGSCREEN
  135. CrtDefSegs <dbdata>
  136. sBegin    dbdata            ; Debugger Screen swap setup segment
  137. assumes ds,data
  138. globalW  __aDBswpflg,0            ; Flag == __aDBswpyes if should attempt swapping
  139. globalW  __aDBswpchk,___aDBretaddr    ; By default points to a model dependent ret
  140. globalW  __aDBrterr,___aDBretaddr    ;
  141. globalW  __aDBexit,___aDBretaddr    ; (Report we are exiting)
  142. staticD  __aDBcallbk,0            ; Call back address to debugger
  143. sEnd
  144.     public    __aDBdoswp
  145. __aDBdoswp    =    0d6d6h
  146. endif    ; _DEBUGSCREEN
  147.  
  148. sBegin    xiqcseg
  149. externW    __qczrinit            ;* QC -Zr initializer call address
  150. sEnd
  151.  
  152. sBegin    data
  153.  
  154. extrn    __edata:byte        ; end of data (start of bss)
  155. extrn    __end:byte        ; end of bss (start of stack)
  156.  
  157. externW _psp            ; psp:0 (paragraph #)
  158. externW __argc
  159. externDP __argv
  160. externDP _environ
  161. externW _osversion        ; address of OS version
  162.  
  163. ;    these are used by DOS C memory management (not used in Windows)
  164.  
  165. globalW _atopsp,0        ; top of stack (heap bottom)
  166. globalW _aexit_rtn,<codeoffset __exit> ; NEAR pointer
  167.  
  168. ;*
  169. ;*    The following (_asizds and _nheap_desc) must be in this order!
  170. ;*
  171.  
  172. globalW _asizds,0        ; DGROUP size - 1 (in bytes)
  173.  
  174. labelW    <PUBLIC,_nheap_desc>    ; near heap descriptor
  175. _heap_seg_desc <0,_HEAP_NEAR OR _HEAP_MODIFY, 0,0,0,0,0,0>
  176. .ERRE    flags    eq    2    ; flags better be second word
  177.  
  178. .ERRE    offset _asizds+2 EQ offset _nheap_desc    ; make sure!
  179.  
  180. ; Heap segment limits (for use with QC)
  181.  
  182. globalW _aseghi,0        ; highest heap segment so far
  183. globalW _aseglo,0        ; lowest allowable heap segment
  184.  
  185. ;
  186. ; DOS Extender Flag
  187. ;
  188. globalW _fDosExt,0        ; 0 = no DOS Extender
  189.  
  190.  
  191.  
  192.  
  193. sEnd
  194.  
  195.     page
  196.  
  197.  
  198. externP _cinit            ; run-time initializers
  199.  
  200. externP _NMSG_WRITE        ; pascal - write error message to stdout
  201. externP _FF_MSGBANNER        ; pascal - error message banner
  202.                 ; (includes FORTRAN $DEBUG info)
  203.  
  204. externP _setargv        ; process command line arguments
  205. externP _setenvp        ; process environment
  206.  
  207. ifdef _FATALHOOK
  208. extrn       __farstub:far        ; alternative stub
  209. extrn       __fatalexit(__farstub):far    ; FAR ptr to fatal exit routine
  210. endif
  211.  
  212.  
  213. sBegin    code
  214. ifdef _COM_
  215. assumes cs,DGROUP        ; .com files are all in one segment
  216. else
  217. assumes cs,code
  218. endif
  219.  
  220. assumes ds,nothing
  221.  
  222.  
  223. page
  224. ;***
  225. ;_astart - start of all C programs
  226. ;
  227. ;Purpose:
  228. ;    Startup routine to initialize C run-time environment
  229. ;
  230. ;Entry:
  231. ;
  232. ;Exit:
  233. ;    Exits to DOS via exit().
  234. ;
  235. ;Uses:
  236. ;
  237. ;Exceptions:
  238. ;
  239. ;*******************************************************************************
  240.  
  241. ifdef _COM_
  242.     org    0100h        ; .COM files start at 0100h
  243. endif
  244.  
  245. labelNP <PUBLIC,_astart>    ; start address of all "C" programs
  246.  
  247.  
  248. ;    check MS-DOS version for 2.0 or later
  249.  
  250.     callos    VERSION     ; ax = DOS version
  251.                 ; *** ax gets preserved for a long time ***
  252.     cmp    al,2        ; check for version 2 or later
  253.     jae    setup        ;   yes - continue with setup
  254. ifdef _COM_            ; DOS puts 0 on stack for .COM files
  255.     retn            ; DOS 1.0 exit program (int 20h at psp:0)
  256. else    ; _COM_
  257.     xor    ax,ax
  258.     push    es        ; push warm start vector es:ax = psp:0
  259.     push    ax
  260.     retf            ; DOS 1.0 exit program (int 20h at psp:0)
  261. endif    ; _COM_
  262.  
  263. setup:
  264.  
  265.  
  266. ifdef _COM_
  267.     mov    di,ds        ; di = DGROUP
  268.     mov    si,ds:[DOS_MAXPARA] ; get max. paragraph
  269. else
  270.     mov    di,DGROUP    ; di = DGROUP
  271.     mov    si,ds:[DOS_MAXPARA] ; get max. paragraph
  272. endif    ;_COM_
  273.  
  274. ifdef  _COM_
  275.     mov    cs:[_dataseg],di ; save dgroup for future
  276. endif
  277.  
  278.     sub    si,di        ; si = # para in data area
  279.     cmp    si,1000h    ; if more than 64K
  280.     jb    setSP
  281.  
  282.     mov    si,1000H    ; use full 64K (-16)
  283.  
  284. setSP:
  285.  
  286. ifdef _COM_
  287.     ;
  288.     ; .COM files - allocate stack (-2 for _asizds limit)
  289.     ; [Do the calculation in a temp register in case it overflows.]
  290.     ;
  291.     mov    bx,dataoffset __end ; go to end of DGROUP
  292.     add    bx,(_STACK_SIZE-2) ; stack is beyond that
  293.     jnc    SPok        ; jump out if stack ok (ax = new sp)
  294.     ;fall thru        ; error - not enough stack space
  295.  
  296. else    ;!_COM_
  297.  
  298. ifdef FARSTACK
  299.     jmp    short SPok    ; stack can't be too big, if .EXE was loaded
  300. else ;!FARSTACK
  301.     cli            ; turn off interrupts
  302.     mov    ss,di        ; SS = DGROUP
  303.     add    sp,dataoffset __end-2 ; 2 for _asizds limit
  304.     sti            ; turn interrupts back on
  305.     jnc    SPok
  306.  
  307.     push    ss        ; establish DS=DGROUP for
  308.     pop    ds        ; _FF_MSGBANNER -> _NMSG_WRITE -> _NMSG_TEXT
  309. endif ;FARSTACK
  310.  
  311. endif  ;_COM_
  312.  
  313. ;
  314. ; Error - Not enough stack space
  315. ;
  316.  
  317.     callcrt _FF_MSGBANNER    ; for "\r\nrun-time error " banner
  318.     xor    ax,ax        ; stack overflow error message (_RT_STACK=0)
  319.     push    ax
  320.     callcrt _NMSG_WRITE
  321.     mov    ax,DOS_terminate shl 8 + 255
  322.     callos            ; terminate process with 255
  323.     ;*** NEVER RETURNS ***
  324.  
  325. ;
  326. ; ax = os version
  327. ; es = psp
  328. ;
  329.  
  330. SPok:
  331.  
  332. ifdef _COM_
  333.     ; bx = new sp value
  334.     mov    sp,bx        ; set new sp value
  335. endif
  336.  
  337. ifdef FARSTACK
  338.     mov    ds, di        ; reload dgroup
  339.     assumes ds, data
  340. else
  341.     assumes ss,data
  342. endif
  343.  
  344.  
  345.     mov    [_osversion],ax ;* save OS version number
  346.  
  347.  
  348. ; at this point:
  349. ;    COM files:  DS = DI = ES = SS = DGROUP
  350. ;    EXE files:  DI = SS = DGROUP, DS = ES = PSP
  351. ;    FARSTACK:     DI = DS = DGROUP, ES = PSP, SS = STACK
  352.  
  353. ;
  354. ; Save size of dgroup
  355. ;
  356.  
  357. stup10:
  358.     mov    ax,si        ; si = # paragraphs in dgroup
  359.     mov    cl,4
  360.     shl    ax,cl        ; ax = size of dgroup (bytes)
  361.     dec    ax        ; ax = size DGROUP - 1
  362.     mov    [_asizds],ax    ; Size of Global Data Segment
  363.  
  364. ;
  365. ; Carve an initial near heap out of the bottom of the stack
  366. ;
  367.  
  368. ifdef FARSTACK
  369.     ; for far stacks, we use the dummy subheap segment instead
  370.     mov    bx,dataoffset _nheap_desc ; ds:bx = near heap descriptor
  371.     mov    [bx].checksum,ds      ; save dgroup in near heap desc
  372.     mov    [bx].segsize, dataOFFSET(stubheap_next) + 2
  373.     mov    [bx].last, dataOFFSET(stubheap_next)
  374.     mov    [bx].start, dataOFFSET(stubheap_size)
  375.     mov    [bx].rover, dataOFFSET(stubheap_size)
  376.  
  377. else
  378.     mov    bx,dataoffset _nheap_desc ; ss:bx = near heap descriptor
  379.     mov    ss:[bx].checksum,ss ; save dgroup in near heap desc
  380.  
  381.     and    sp,not 1        ; make even (if not)
  382.     mov    ss:[bx].segsize,sp  ; save as segment size
  383.  
  384.     .ERRE    _HEAP_END -2    ; make sure they're equal
  385.     mov    ax,_HEAP_END    ; get end-of-heap flag
  386.     push    ax        ; into place
  387.     mov    ss:[bx].last,sp ; pointer to end-of-heap
  388.     not    ax        ; ax = 1 (0-length free entry)
  389.     push    ax        ; first heap entry
  390.     mov    ss:[bx].start,sp; init start/rover
  391.     mov    ss:[bx].rover,sp
  392. endif
  393.  
  394. ;
  395. ; Now initialize the top of stack location
  396. ;
  397.  
  398.     mov    [_atopsp],sp    ; Top of Stack Region
  399.  
  400. ;    release extra space to DOS
  401.  
  402.  
  403.  
  404.     add    si,di        ; si = DGROUP + # para in DGROUP
  405. ifdef FARSTACK
  406.     ; at this point es still has the psp address
  407.     mov    es:[DOS_MAXPARA],si ; fix psp:2
  408. else
  409.     mov    ds:[DOS_MAXPARA],si ; fix psp:2
  410. endif
  411.  
  412.     mov    bx,es        ; bx = PSP base
  413.     sub    bx,si        ; bx = - # para used
  414.     neg    bx
  415.     callos    setmem        ; set memory block size
  416. ifdef FARSTACK
  417.     ; for FARSTACK, es has the psp address, ds = DGROUP
  418. stup20:
  419.     mov    [_psp],es
  420. else
  421.     ; no FARSTACK, ds = psp, ss = DGROUP
  422. stup20:
  423.     mov    [_psp],ds    ; save psp:0
  424. endif
  425.  
  426. ;    zero data areas (_BSS and c_common)
  427.  
  428. ifdef FARSTACK
  429.     push    ds
  430.     pop    es        ; ES = DGROUP
  431.     assumes es, data
  432. else
  433.  
  434. ifndef _COM_
  435.     push    ss
  436.     pop    es        ; ES = DGROUP
  437. endif    ;_COM_
  438.     assumes es,data
  439.  
  440. endif ;FARSTACK
  441.  
  442. ; at this point:
  443. ;    COM files:  DS = ES = SS = DGROUP
  444. ;    EXE files:  SS = ES = DGROUP, DS = PSP
  445. ;    FARSTACK:     DS = ES = DGROUP, SS = STACK
  446.  
  447.     cld            ; set direction flag (up)
  448.     mov    di,dataOFFSET __edata ; beginning of bss area
  449.     mov    cx,dataOFFSET __end ; end of bss area
  450.     sub    cx,di
  451.     xor    ax,ax
  452.     rep    stosb        ; zero bss
  453.  
  454.  
  455. ;    C segmentation conventions set up here    (DS=SS and CLD)
  456.  
  457. ifndef _COM_
  458. ifndef FARSTACK
  459.     push    ss        ; set up initial DS=ES=SS, CLD
  460.     pop    ds
  461. endif    ;FARSTACK
  462. endif    ;_COM_
  463.     assumes ds,data
  464.  
  465. ; OK, we now have DS = ES = DGROUP for all models, and SS = DGROUP
  466. ; except for the far stack model.
  467.  
  468. ;    Must run this initializer prior to any far heap allocations being
  469. ;    done.  This means that we have hack-ed this in here.  There should
  470. ;    be a better solution for C7
  471.  
  472.     mov    cx,__qczrinit        ;* Get initializer addr
  473.     jcxz    @F            ;* Is it zero?
  474.     call    cx            ;* No -- call indirect through
  475. @@:
  476.  
  477. ;    process command line and environment
  478.  
  479.     call    _setenvp    ; crack environment
  480.     call    _setargv    ; crack command line
  481.  
  482. ;
  483. ; Zero bp for debugging backtrace support (i.e., mark top-of-stack).
  484. ;
  485.  
  486.     xor    bp,bp        ; mark top stack frame for SYMDEB
  487.  
  488. ;    do necessary initialization
  489.  
  490.     call    _cinit        ; shared by DOS and Windows
  491.  
  492. ifndef    _COM_
  493. ifdef FARSTACK
  494.     mov    ax, DGROUP
  495.     mov    ds, ax        ; ds = DGROUP
  496. else
  497.     push    ss
  498.     pop    ds        ; ds = DGROUP
  499. endif ;FARSTACK
  500. endif ;_COM_
  501.     assumes ds,data
  502.  
  503. ;    call main and exit
  504.  
  505. if    sizeD
  506.     push    word ptr [_environ+2] ; the environment is not always in DS
  507. endif
  508.     push    word ptr [_environ]
  509.  
  510. if    sizeD
  511.     push    word ptr [__argv+2] ; the arguments are not always in DS
  512. endif
  513.     push    word ptr [__argv]
  514.  
  515.     push    [__argc]    ; argument count
  516.  
  517.     call    main        ; main ( argc , argv , envp )
  518.  
  519. ; use whatever is in ax after returning here from the main program
  520.  
  521.     push    ax
  522.     callcrt exit        ; exit (AX)
  523.                 ;   _exit will call terminators
  524.  
  525. ifdef _DEBUGSCREEN
  526. ___aDBretaddr:            ; label to appropriate "RET"
  527.     ret            ; Default dbdata address
  528. endif    ; _DEBUGSCREEN
  529.  
  530.  
  531. page
  532. ;***
  533. ;_amsg_exit, _cintDIV - Fast exit fatal errors
  534. ;
  535. ;Purpose:
  536. ;    Exit the program with error code of 255 and appropriate error
  537. ;    message.  cintDIV is used for integer divide by zero, amsg_exit
  538. ;    is for other run time errors.
  539. ;
  540. ifdef _FATALHOOK
  541. ;    Weak extern call through _fatalexit was added so programs
  542. ;    may be notified of imminent termination (e.g., PWB).
  543. endif
  544. ;
  545. ;Entry:
  546. ;    AX    = error message number (amsg_exit only).
  547. ;
  548. ;Exit:
  549. ;    calls exit() [cintDIV] or indirect through _aexit_rtn [amg_exit].
  550. ;
  551. ;Uses:
  552. ;
  553. ;Exceptions:
  554. ;
  555. ;*******************************************************************************
  556.  
  557. labelNP <PUBLIC,_cintDIV>
  558.  
  559.     assumes ds,nothing
  560.  
  561.     mov    ax,cs:[_dataseg]
  562.     mov    ds, ax        ; ds = DGROUP
  563.     assumes ds, data
  564.  
  565.     mov    ax,_RT_INTDIV    ; Integer divide by zero interrupt
  566.     mov    [_aexit_rtn],codeoffset _exit ; call high-level exit()
  567.                 ; to cause file buffer flushing
  568.  
  569. labelNP <PUBLIC,_amsg_exit>
  570.  
  571.     assumes ds,nothing
  572.  
  573.     push    ax        ; message number for _NMSG_WRITE
  574.                 ; save around call to __fatalexit
  575. ifdef _FATALHOOK
  576.     ; weak extern call to fatal exit hook
  577.     ; ax = error code
  578.     mov    bx,cs:[_dataseg]
  579.     mov    ds, bx        ; ds = DGROUP
  580.     assumes ds, data
  581.     call    __fatalexit
  582. endif
  583.                 ; error code already on stack
  584.     callcrt _FF_MSGBANNER    ; run-time error message banner
  585.     callcrt _NMSG_WRITE    ; write error message to stdout
  586.  
  587. ifdef _DEBUGSCREEN
  588.     cmp    __aDBswpflg,__aDBdoswp    ; Aware debugger as parent?
  589.     jne    @F            ; No -- skip
  590.     pop    ax
  591.     push    ax
  592.     call    __aDBrterr        ; Yes -- report a runtime error
  593. @@:
  594. endif    ; _DEBUGSCREEN
  595.  
  596.     assumes ds,data
  597.  
  598.     mov    ax,255
  599.     push    ax
  600. if    sizeC
  601.     push    cs                ; _exit is compiled far
  602.                         ;    but called near
  603. endif
  604.     call    word ptr [_aexit_rtn] ; _exit(255) ordinarily
  605.                 ; (or exit(255) for div by 0)
  606.                 ; NEAR routine pointer
  607.  
  608. ; Location that holds DGROUP segment (necessary for .COM file support)
  609.  
  610. ifdef  _COM_
  611. globalW _dataseg,0        ; will hold DGROUP
  612.  
  613. else    ;not _COM_
  614. globalW _dataseg,DGROUP
  615.  
  616. endif    ;not _COM_
  617.  
  618. sEnd
  619.     end    _astart     ; start address
  620.