home *** CD-ROM | disk | FTP | other *** search
/ Boston 2 / boston-2.iso / DOS / PROGRAM / C / TEMPLATE / CRT0DAT.ASM < prev    next >
Assembly Source File  |  1993-12-01  |  25KB  |  917 lines

  1.         page    ,132
  2.         title   crt0dat - DOS and Windows shared startup and termination
  3. ;***
  4. ;crt0dat.asm - DOS and Windows shared startup and termination
  5. ;
  6. ;       Copyright (c) 1985-1990, Microsoft Corporation.  All rights reserved.
  7. ;
  8. ;Purpose:
  9. ;       Shared startup and termination.
  10. ;
  11. ;       NOTE:  This source is included in crt0.asm for assembly purposes
  12. ;       when building .COM startup.  This is so the .COM startup resides
  13. ;       in a single special object that can be supplied to the user.
  14. ;
  15. ;*******************************************************************************
  16.  
  17. _NFILE_ =       20              ; Maximum number of file handles
  18.  
  19. ?DF     =       1               ;; tell cmacros.inc we want to define our own segments
  20.  
  21. .xlist
  22. include version.inc
  23. include cmacros.inc
  24. include msdos.inc
  25. .list
  26.  
  27. ifdef FARSTACK
  28. ife sizeD
  29. error <You cannot have a far stack in Small or Medium memory models.>
  30. endif
  31. endif
  32.  
  33. ifdef   _COM_
  34.     if sizeC or sizeD
  35.         error <Must use Small memory model for .COM files.>
  36.     endif
  37. endif   ;_COM_
  38.  
  39. createSeg _TEXT, code,  word,   public, CODE,   <>
  40. createSeg CDATA, cdata, word,   common, DATA,   DGROUP
  41. createSeg _DATA, data,  word,   public, DATA,   DGROUP
  42.  
  43. createSeg DBDATA, dbdata, word, common, DATA,   DGROUP
  44.  
  45. createSeg XIQC, xiqcseg, word,  common, DATA,   DGROUP  ; QC initializer -Zr  (DOS only)
  46.  
  47. createSeg XIFB, xifbseg, word,  public, DATA,   DGROUP
  48. createSeg XIF,  xifseg, word,   public, DATA,   DGROUP ; far init's
  49. createSeg XIFE, xifeseg, word,  public, DATA,   DGROUP
  50.  
  51. createSeg XIB,  xibseg, word,   public, DATA,   DGROUP
  52. createSeg XI,   xiseg,  word,   public, DATA,   DGROUP ; init's
  53. createSeg XIE,  xieseg, word,   public, DATA,   DGROUP
  54.  
  55. createSeg XOB,  xobseg, word,   public, BSS,    DGROUP
  56. createSeg XO,   xoseg,  word,   public, BSS,    DGROUP ; onexit table
  57. createSeg XOE,  xoeseg, word,   public, BSS,    DGROUP
  58.  
  59. createSeg XPB,  xpbseg, word,   public, DATA,   DGROUP
  60. createSeg XP,   xpseg,  word,   public, DATA,   DGROUP ; preterm's
  61. createSeg XPE,  xpeseg, word,   public, DATA,   DGROUP
  62.  
  63. createSeg XCB,  xcbseg, word,   public, DATA,   DGROUP
  64. createSeg XC,   xcseg,  word,   public, DATA,   DGROUP ; term's
  65. createSeg XCE,  xceseg, word,   public, DATA,   DGROUP
  66.  
  67. createSeg XCFB, xcfbseg, word,  public, DATA,   DGROUP
  68. createSeg XCF,  xcfseg, word,   public, DATA,   DGROUP ; far term's
  69. createSeg XCFE, xcfeseg, word,  public, DATA,   DGROUP
  70.  
  71. ifdef  _COM_
  72. createSeg EMULATOR_DATA, EmData, para, public, FAR_DATA, DGROUP
  73. createSeg EMULATOR_TEXT, EmCode, para, public, CODE, DGROUP
  74. endif   ;_COM_
  75.  
  76. defGrp  DGROUP                  ; define DGROUP
  77.  
  78. codeOFFSET equ  offset _TEXT:
  79. dataOFFSET equ  offset DGROUP:
  80.  
  81. page
  82. sBegin  xifbseg
  83. xifbegin label  byte
  84. sEnd    xifbseg
  85.  
  86. sBegin  xifeseg
  87. xifend  label   byte
  88. sEnd    xifeseg
  89.  
  90. sBegin  xibseg
  91. xibegin label   byte
  92. sEnd    xibseg
  93.  
  94. sBegin  xieseg
  95. xiend   label   byte
  96. sEnd    xieseg
  97.  
  98. sBegin  xobseg
  99. xontab  label   byte            ; start of onexit table
  100. sEnd    xobseg
  101.  
  102. sBegin  xoeseg
  103. xonend  label   byte
  104. sEnd    xoeseg
  105.  
  106. sBegin  xpbseg
  107. xpbegin label   byte            ; end of onexit table
  108. sEnd    xpbseg
  109.  
  110. sBegin  xpeseg
  111. xpend   label   byte
  112. sEnd    xpeseg
  113.  
  114. sBegin  xcbseg
  115. xcbegin label   byte
  116. sEnd    xcbseg
  117.  
  118. sBegin  xceseg
  119. xcend   label   byte
  120. sEnd    xceseg
  121.  
  122. sBegin  xcfbseg
  123. xcfbegin label  byte
  124. sEnd    xifbseg
  125.  
  126. sBegin  xcfeseg
  127. xcfend  label   byte
  128. sEnd    xcfeseg
  129.  
  130. sBegin  cdata                   ; floating point setup segment
  131. assumes ds,data
  132.  
  133.         dw      0               ; force segment to be at least 0's
  134. labelD  <PUBLIC,_fpinit>        ; public for signal
  135. fpmath  dd      1 dup (?)       ; linking trick for fp
  136. fpdata  dd      1 dup (?)
  137. fpsignal dd     1 dup (?)       ; fp signal message
  138.  
  139. sEnd
  140.  
  141.  
  142. sBegin  dbdata                          ;*
  143.         assumes ds,data                 ;*  Used to do the running under
  144. externW         __aDBswpflg             ;*  a debugger screen swapping
  145. externW         __aDBexit               ;*
  146. sEnd    dbdata                          ;*
  147.         extrn   __aDBdoswp:ABS          ;*
  148.  
  149. sBegin  xiqcseg
  150. globalW __qczrinit, 0                   ;* QC -Zr initializer call address
  151. sEnd    xiqcseg
  152.  
  153.  
  154. ifdef  _COM_
  155.     sBegin  EmData
  156.     labelB  _EmDataLabel
  157.     sEnd    EmData
  158.  
  159.     sBegin  EmCode
  160.     globalW _EmDataSeg,0
  161.     sEnd    EmCode
  162.  
  163. else    ;not _COM
  164.     EMULATOR_DATA  segment para public 'FAR_DATA'
  165.     EMULATOR_DATA  ends
  166.  
  167.     EMULATOR_TEXT  segment para public 'CODE'
  168.  
  169.     public __EmDataSeg
  170.     __EmDataSeg dw  EMULATOR_DATA
  171.  
  172.     EMULATOR_TEXT  ends
  173. endif   ;not _COM_
  174.  
  175. sBegin  data
  176. assumes ds,data
  177.  
  178. ;       special C environment string
  179.  
  180.         labelB  <PUBLIC,_acfinfo>
  181.         cfile   db      '_C_FILE_INFO='
  182.         cfilex  db      0
  183.         cfileln =       cfilex-cfile
  184.  
  185. globalD _aintdiv,0              ; divide error interrupt vector save
  186.  
  187. globalT _fac,0                  ; floating accumulator
  188. globalW errno,0                 ; initial error code
  189. globalW _umaskval,0             ; initial umask value
  190.  
  191. ;=============== following must be in this order
  192.  
  193. globalW _pspadr,0               ; psp:0 (far * to PSP segment)
  194. globalW _psp,0                  ; psp:0 (paragraph #)
  195.  
  196. ;=============== above must be in this order
  197.  
  198. ;=============== following must be in this order
  199.  
  200. labelW  <PUBLIC,_osversion>
  201. labelB  <PUBLIC,_dosvermajor>
  202. globalB _osmajor,0
  203. labelB  <PUBLIC,_dosverminor>
  204. globalB _osminor,0
  205.  
  206. ;=============== above must be in this order
  207.  
  208.  
  209. globalB _osmode,0               ; 0 = real mode
  210.  
  211. labelW  <PUBLIC,_oserr>
  212. globalW _doserrno,0             ; initial DOS error code
  213.  
  214. globalW _nfile,_NFILE_          ; maximum number of file handles
  215.  
  216. labelB  <PUBLIC,_osfile>
  217.         db      3 dup (FOPEN+FTEXT) ; stdin, stdout, stderr
  218.         db      2 dup (FOPEN)   ; stdaux, stdprn
  219.         db      _NFILE_-5 dup (0) ; the other 15 handles
  220.  
  221.  
  222. globalW __argc,0
  223. globalDP __argv,0
  224. globalDP environ,0              ; environment pointer
  225.  
  226. labelD  <PUBLIC,_pgmptr>        ; pointer to program name
  227.         dw      dataOFFSET dos2nam
  228. ifdef _COM_
  229.         dw      0               ; No relocations in tiny model
  230. elseifdef _QC2
  231.         dw      0               ; No DGROUP references allowed
  232. elseifdef _WINDOWS
  233.         dw      0               ; No DGROUP references allowed
  234. else    ;DEFAULT
  235.         dw      DGROUP
  236. endif
  237.  
  238. dos2nam db      0               ; dummy argv[0] for DOS 2.X
  239.  
  240.  
  241. ; signal related common data
  242.  
  243. globalW _child,0                ; flag used to handle signals from child process
  244.  
  245. ;Overlay related data
  246.  
  247. globalB _ovlflag,0      ;Overlay flag (0 = no overlays)
  248. globalB _intno,0        ;Overlay interrupt value (e.g., 3F)
  249. globalD _ovlvec,0       ;Address of original overlay handler
  250.  
  251.  
  252. sEnd    data
  253.  
  254. page
  255. externNP _fptrap
  256.  
  257. externP _cintDIV
  258.  
  259. externP _nullcheck
  260.  
  261. ifdef  FARSTACK
  262. endif
  263.  
  264. sBegin  code
  265. assumes cs,code
  266.  
  267. if      sizeC
  268. global  proc    far
  269. endif
  270.  
  271. page
  272. ;***
  273. ;_cinit - C initialization
  274. ;
  275. ;Purpose:
  276. ;       This routine performs the shared DOS and Windows initialization.
  277. ;       The following order of initialization must be preserved -
  278. ;
  279. ;       1.      Integer divide interrupt vector setup
  280. ;       2.      Floating point initialization
  281. ;       3.      Copy ;C_FILE_INFO into _osfile
  282. ;       4.      Check for devices for file handles 0 - 4
  283. ;       5.      General C initializer routines
  284. ;
  285. ;Entry:
  286. ;
  287. ;Exit:
  288. ;
  289. ;Uses:
  290. ;
  291. ;Exceptions:
  292. ;
  293. ;*******************************************************************************
  294.  
  295. cProc   _cinit,<PUBLIC>,<>
  296.  
  297. cBegin  <nogen>                 ; no local frame to set up in standard libs
  298.  
  299. assumes ds,data
  300. ifndef FARSTACK
  301. assumes ss,data
  302. endif
  303.  
  304. ;
  305. ;       Initialize the DGROUP portion of _pgmptr.  We must do this at
  306. ;       runtime since there are no load-time fixups in .COM files.
  307. ;
  308. ifdef _COM_
  309.         mov     word ptr [_pgmptr+2],ds ; init seg portion of _pgmptr
  310. endif   ;_COM_
  311.  
  312.  
  313. ;       *** Increase File Handle Count ***
  314. ;
  315. ;       (1) This code only works on DOS Version 3.3 and later.
  316. ;       (2) This code is intentially commented out; the user must enable
  317. ;       this code to access more than 20 files.
  318. ;
  319. ;       mov     ah,67h          ; system call number
  320. ;       mov     bx,_NFILE_      ; number of file handles to allow
  321. ;       callos                  ; issue the system call
  322. ;       ;check for error here, if desired (if carry set, AX equals error code)
  323. ;
  324. ;       *** End Increase File Handle Count ***
  325.  
  326.  
  327. ;       1.      Integer divide interrupt vector setup
  328.  
  329.         mov     ax,DOS_getvector shl 8 + 0
  330.         callos                  ; save divide error interrupt
  331.         mov     word ptr [_aintdiv],bx
  332.         mov     word ptr [_aintdiv+2],es
  333.  
  334.         push    cs
  335.         pop     ds
  336.         assumes ds,nothing
  337.         mov     ax,DOS_setvector shl 8 + 0
  338.         mov     dx,codeOFFSET _cintDIV
  339.         callos                  ; set divide error interrupt
  340.         push    ss
  341.         pop     ds
  342.         assumes ds,data
  343.  
  344. ;       2.      Floating point initialization
  345.  
  346. if  memS
  347.         cmp     word ptr [fpmath], 0        ; Note: make sure offset __fpmath != 0
  348.         je      nofloat_i
  349.  
  350.         mov     word ptr [fpmath+2], cs     ; fix up these far addresses
  351.         mov     word ptr [fpsignal+2], cs   ; in the small model math libs
  352.  
  353.     ifdef  _COM_
  354.         mov     [_EmDataSeg], cs
  355.         mov     ax, offset DGROUP:_EmDataLabel
  356.         sub     ax, offset EMULATOR_DATA:_EmDataLabel
  357.         mov     cl, 4
  358.         shr     ax, cl
  359.         add     [_EmDataSeg], ax
  360.     endif   ;_COM_
  361.  
  362. else    ;not memS
  363.         mov     cx,word ptr [fpmath+2]
  364.         jcxz    nofloat_i
  365. endif   ;not memS
  366.  
  367.         mov     es,[_psp]       ; psp segment
  368.         mov     si,es:[DOS_ENVP] ; environment segment
  369. ifdef FARSTACK
  370.         mov     ax, word ptr [fpdata]
  371.         mov     dx, word ptr [fpdata+2]
  372. else
  373.         lds     ax,[fpdata]     ; get task data area
  374.         assumes ds,nothing
  375.         mov     dx,ds           ;   into dx:ax
  376. endif
  377.         xor     bx,bx           ; (si) = environment segment
  378.         call    [fpmath]        ; fpmath(0) - init
  379. ifdef FARSTACK
  380.         mov     ax, DGROUP
  381.         mov     ds, ax
  382. endif
  383.         jnc     fpok
  384.  
  385. ifndef FARSTACK
  386.         push    ss              ; restore ds from ss
  387.         pop     ds
  388. endif
  389.         jmp     _fptrap         ; issue "Floating point not loaded"
  390.                                 ; error and abort
  391.  
  392. fpok:
  393. ifdef FARSTACK
  394.         mov     ax, word ptr [fpsignal]
  395.         mov     dx, word ptr [fpsignal+2]
  396. else
  397.         lds     ax,[fpsignal]   ; get signal address
  398.         assumes ds,nothing
  399.         mov     dx,ds
  400. endif
  401.         mov     bx,3
  402.         call    [fpmath]        ; fpmath(3) - set signal address
  403. ifdef FARSTACK
  404.         mov     ax, DGROUP
  405.         mov     ds, ax          ; restore DS=DGROUP
  406. else
  407.         push    ss
  408.         pop     ds
  409.         assumes ds,data
  410. endif
  411.  
  412. nofloat_i:
  413.  
  414. ;       3.      Copy _C_FILE_INFO= into _osfile
  415.  
  416. ;       fix up files inherited from parent using _C_FILE_INFO=
  417.  
  418.         mov     es,[_psp]       ; es = PSP
  419.         mov     cx,word ptr es:[DOS_envp] ; es = user's environment
  420.         jcxz    nocfi           ;   no environment !!!
  421.         mov     es,cx
  422.         xor     di,di           ; start at 0
  423.  
  424. cfilp:
  425.         cmp     byte ptr es:[di],0 ; check for end of environment
  426.         je      nocfi           ;   yes - not found
  427.         mov     cx,cfileln
  428.         mov     si,dataOFFSET cfile
  429.         repe    cmpsb           ; compare for '_C_FILE_INFO='
  430.         je      gotcfi          ;   yes - now do something with it
  431.         mov     cx,07FFFh       ; environment max = 32K
  432.         xor     ax,ax
  433.         repne   scasb           ; search for end of current string
  434.         jne     nocfi           ;   no 00 !!! - assume end of env.
  435.         jmp     cfilp           ; keep searching
  436.  
  437. ;       found _C_FILE_INFO= and transfer info into _osfile
  438.  
  439. gotcfi:
  440.         push    es
  441.         push    ds
  442.         pop     es              ; es = DGROUP
  443.         pop     ds              ; ds = env. segment
  444.         assumes ds,nothing
  445.         assumes es,data
  446.         mov     si,di           ; si = startup of _osfile info
  447.         mov     di,dataOFFSET _osfile ; di = _osfile block
  448.  
  449.         mov     cl, 4
  450.  
  451. osfile_lp:
  452.         lodsb
  453.         sub     al, 'A'
  454.         jb      donecfi
  455.         shl     al, cl
  456.         xchg    dx, ax
  457.  
  458.         lodsb
  459.         sub     al, 'A'
  460.         jb      donecfi
  461.         or      al, dl
  462.         stosb
  463.         jmp     short osfile_lp
  464.  
  465. donecfi:
  466. ifdef FARSTACK
  467.         push    es
  468. else
  469.         push    ss
  470. endif
  471.         pop     ds              ; ds = DGROUP
  472.         assumes ds,data
  473.  
  474. nocfi:
  475.  
  476.  
  477.  
  478. ;       4.      Check for devices for file handles 0 - 4
  479. ;
  480. ;               Clear the FDEV bit (which might be inherited from C_FILE_INFO)
  481. ;               and then call DOS to see if it really is a device or not
  482. ;
  483.         mov     bx,4
  484.  
  485. devloop:
  486.         and     _osfile[bx],not FDEV ; clear FDEV bit on principal
  487.  
  488.         mov     ax,DOS_ioctl shl 8 + 0 ; issue ioctl(0) to get dev info
  489.         callos
  490.         jc      notdev
  491.  
  492.         test    dl,80h          ; is it a device ?
  493.         jz      notdev          ;   no
  494.         or      _osfile[bx],FDEV ;   yes - set FDEV bit
  495.  
  496. notdev:
  497.         dec     bx
  498.         jns     devloop
  499.  
  500.  
  501.  
  502. ;       5.      General C initializer routines
  503.  
  504.         mov     si,dataOFFSET xifbegin
  505.         mov     di,dataOFFSET xifend
  506. if      sizeC
  507.         call    initterm        ; call the far initializers
  508. else
  509.         call    farinitterm     ; call the far initializers
  510. endif
  511.  
  512.         mov     si,dataOFFSET xibegin
  513.         mov     di,dataOFFSET xiend
  514.         call    initterm        ; call the initializers
  515.  
  516.  
  517.         ret
  518. cEnd    <nogen>         ; standard C libs
  519.  
  520.  
  521. page
  522. ;***
  523. ;exit(status), _exit(status), _cexit(void), _c_exit(void) - C termination
  524. ;
  525. ;Purpose:
  526. ;
  527. ;       Entry points:
  528. ;
  529. ;               exit(code):  Performs all the C termination functions
  530. ;                       and terminates the process with the return code
  531. ;                       supplied by the user.
  532. ;
  533. ;               _exit(code):  Performs a quick exit routine that does not
  534. ;                       do certain 'high-level' exit processing.  The _exit
  535. ;                       routine terminates the process with the return code
  536. ;                       supplied by the user.
  537. ;
  538. ;               _cexit():  Performs the same C lib termination processing
  539. ;                       as exit(code) but returns control to the caller
  540. ;                       when done (i.e., does NOT terminate the process).
  541. ;
  542. ;               _c_exit():  Performs the same C lib termination processing
  543. ;                       as _exit(code) but returns control to the caller
  544. ;                       when done (i.e., does NOT terminate the process).
  545. ;
  546. ;       Termination actions:
  547. ;
  548. ;               exit(), _cexit ():
  549. ;
  550. ;               1.      call user's terminator routines
  551. ;               2.      call C runtime preterminators
  552. ;
  553. ;               _exit(), _c_exit():
  554. ;
  555. ;               3.      call C runtime terminators
  556. ;               4.      perform _nullcheck() for null pointer assignment
  557. ;               5.      terminate floating point
  558. ;               6.      reset divide by zero interrupt vector
  559. ;               7.      restore int 3F handler
  560. ;               8.      return to DOS or caller
  561. ;
  562. ;       Notes:
  563. ;
  564. ;       The termination sequence is complicated due to the multiple entry
  565. ;       points sharing the common code body while having different entry/exit
  566. ;       sequences.
  567. ;
  568. ;Entry:
  569. ;       exit(), _exit()
  570. ;               int status - exit status (0-255)
  571. ;
  572. ;       _cexit(), _c_exit()
  573. ;               <no input>
  574. ;
  575. ;Exit:
  576. ;       exit(), _exit()
  577. ;               <EXIT to DOS>
  578. ;
  579. ;       _cexit(), _c_exit()
  580. ;               Return to caller
  581. ;
  582. ;Uses:
  583. ;
  584. ;Exceptions:
  585. ;
  586. ;*******************************************************************************
  587.  
  588. ;
  589. ;--- exit(): Full exit and term process ---
  590. ;
  591.  
  592. public  _exit
  593. _exit:
  594. cProc   dummy1,<>,<>
  595.  
  596.         parmw   status          ; termination code
  597.  
  598. cBegin
  599.  
  600.         xor     cx,cx           ; exit(): cl = 0, ch = 0
  601.         jmp     short common1   ; join common code
  602.  
  603. cEnd    <nogen>
  604.  
  605. ;
  606. ;--- _exit(): Quickie exit and term process ---
  607. ;
  608.  
  609. public  __exit
  610. __exit:
  611. cProc   dummy2,<>,<>
  612.  
  613.         parmw   status          ; termination code
  614.  
  615. cBegin
  616.  
  617.         mov     cx,1            ; _exit(): cl = 1, ch = 0
  618.         jmp     short common1   ; join common code
  619.  
  620. cEnd    <nogen>
  621.  
  622. if      sizeC
  623. global  endp
  624. endif
  625.  
  626. ;
  627. ;--- _cexit(): Full exit and return to caller ---
  628. ;
  629.  
  630. cProc   _cexit,<PUBLIC>,<SI,DI>
  631.  
  632. cBegin
  633.  
  634.         mov     cx,(1 SHL 8)    ; _cexit(): ch = 1, cl = 0
  635.         jmp     short common1   ; join common code
  636.  
  637. cEnd    <nogen>
  638.  
  639. ;
  640. ;--- _c_exit(): Quickie exit and return to caller ---
  641. ;
  642.  
  643. cProc   _c_exit,<PUBLIC>,<SI,DI>
  644.  
  645. cBegin
  646.  
  647.         mov     cx,(1 SHL 8)+1  ; _c_exit(): ch = 1, cl = 1
  648.         ;fall through
  649.  
  650. ;
  651. ;--- Common entry point ---
  652. ; cx = entry value:
  653. ;       cl = full vs quick exit path
  654. ;            0 = exit() code
  655. ;            1 = _exit() code
  656. ;       ch = term process vs return to caller
  657. ;            0 = term process
  658. ;            1 = return to caller
  659. ;
  660.  
  661. common1:                        ; all code paths join here
  662.  
  663. assumes ds,data
  664. ifndef FARSTACK
  665. assumes ss,data
  666. endif
  667.  
  668. ;
  669. ; If _exit()/_c_exit(), jump over the initial termination processing
  670. ; cx = entry code
  671. ;
  672.  
  673.         push    cx              ; save entry code on top of stack
  674.         or      cl,cl           ; cl != 0 means _exit()/_c_exit()
  675.         jnz     short common2   ; if _exit()/_c_exit(), jump down
  676.         ;fall thru              ; continue (exit, _cexit)
  677.  
  678.  
  679. ;       1.      call user terminators
  680. ;               - onexit processing
  681.  
  682.         mov     si,dataOFFSET xontab ; beginning of onexit table
  683.         mov     di,dataOFFSET xonend ; end of onexit table
  684.         call    initterm
  685.  
  686. ;       2.      call C runtime preterminators
  687. ;               - flushall
  688. ;               - rmtmp
  689.  
  690.         mov     si,dataOFFSET xpbegin ; beginning of pre-terminators
  691.         mov     di,dataOFFSET xpend ; end of pre-terminators
  692.         call    initterm
  693.  
  694.         ;*
  695.         ;*      Tell the debugger we are going to exit
  696.         ;*
  697.         ; *** NOTE: Currently, this appears to be called for both
  698.         ; exit() and _cexit().  Is this what we want?
  699.         ;
  700.  
  701.         cmp     __aDBswpflg,__aDBdoswp  ;* Are we under a debugger?
  702.         jne     @F                      ;* No -- skip forward
  703.         cCall   __aDBexit               ;* Yes -- tell it we are exiting
  704. @@:
  705.  
  706. ;
  707. ;--- Common entry point ---
  708. ;
  709.  
  710. common2:                        ; __exit() enters here
  711.  
  712.  
  713. ;       3.      perform C terminators
  714.  
  715.         mov     si,dataOFFSET xcbegin
  716.         mov     di,dataOFFSET xcend
  717.         call    initterm        ; call the terminators
  718.  
  719.         mov     si,dataOFFSET xcfbegin
  720.         mov     di,dataOFFSET xcfend
  721. if      sizeC
  722.         call    initterm        ; call the far terminators
  723. else
  724.         call    farinitterm     ; call the far terminators
  725. endif
  726.  
  727. ;       4.      perform _nullcheck() for null pointer assignment
  728.  
  729. ifndef  _COM_   ; DS:0 is the PSP in .COM files!
  730.  
  731.         call    _nullcheck      ; check data in NULL data segment at DS:0
  732.                                 ; this must be far call in large code models
  733.                                 ; since user can stub it out
  734.         or      ax,ax           ; zero if no null ptr assignment detected
  735.         jz      afternullchk
  736.  
  737.         pop     ax              ; get entry code
  738.         or      ah,ah           ; ah != 0 means _cexit()/_c_exit()
  739.         push    ax              ; put it back for later
  740.         jnz      short afternullchk ; jump if no status value (_cexit/_c_exit)
  741.  
  742.         cmp     status,0        ; zero if no other error has occurred
  743.         jnz     short afternullchk
  744.         mov     status,255      ; nonzero status to indicate an
  745.                                 ; null-pointer-assignment error
  746. afternullchk:
  747.  
  748. endif   ;_COM_
  749.  
  750. ;       5.      terminate floating point
  751. ;       6.      reset divide by zero interrupt vector
  752. ;       7.      restore int 3F handler
  753.  
  754.         call    _ctermsub       ; fast cleanup
  755.  
  756. ;       8.      return to the DOS or caller
  757.  
  758.         pop     ax              ; get entry code off top of stack
  759.         or      ah,ah           ; ah = 0 means term process
  760.         jnz      returning      ; skip down if not term'ing
  761.  
  762. ;       8a.      return to the DOS
  763.  
  764. exiting:
  765.         mov     ax,status       ; get return value
  766.  
  767.         callos  terminate       ; exit with al = return code
  768.  
  769.  
  770.         ;*** PROCESS IS TERMINATED ***
  771.  
  772. ;       8b.     Return to caller.
  773.  
  774. returning:
  775.  
  776. cEnd    <nolocals>
  777.  
  778.  
  779. page
  780. ;***
  781. ;_ctermsub - more C termination code
  782. ;
  783. ;Purpose:
  784. ;       This routine
  785. ;               (1) performs floating-point termination
  786. ;               (2) resets the divide by zero interrupt vector
  787. ;               (3) restore int 3F handler
  788. ;
  789. ;Entry:
  790. ;
  791. ;Exit:
  792. ;
  793. ;Uses:
  794. ;       AX,BX,CX,DX.
  795. ;
  796. ;Exceptions:
  797. ;
  798. ;*******************************************************************************
  799.  
  800. labelNP <PUBLIC,_ctermsub>
  801.  
  802. ;       4.      terminate floating point
  803.  
  804.  
  805.         mov     cx,word ptr [fpmath+2] ; test for floating point
  806.         jcxz    nofloat_t       ;   no
  807.  
  808.         mov     bx,2            ;   yes - cleanup
  809.         call    [fpmath]
  810.  
  811. nofloat_t:
  812.  
  813.  
  814. ;       5.      reset divide by zero interrupt vector
  815.  
  816.         push    ds
  817.         lds     dx,[_aintdiv]   ; ds:dx = restore vector
  818.         mov     ax,DOS_setvector shl 8 + 0
  819.         callos                  ; set divide error interrupt
  820.         pop     ds
  821.  
  822. ;       6.      restore overlay interrupt vector
  823.  
  824.         cmp     byte ptr [_ovlflag],0   ; Overlays in use ??
  825.         jz      done_ovlvec             ; if 0, don't restore overlay vector
  826.         push    ds                      ; save ds
  827.         mov     al,byte ptr [_intno]    ; overlay interrupt number
  828.         lds     dx,dword ptr [_ovlvec]  ; original ovl interrupt vector
  829.         callos  setvector               ; restore the overlay vector
  830.         pop     ds                      ; restore ds
  831. done_ovlvec:
  832.         ret
  833.  
  834.  
  835. page
  836. ;***
  837. ;initterm - do a set of initializers or terminators
  838. ;
  839. ;Purpose:
  840. ;       The initializors and terminators may be written in C
  841. ;       so we are assuming C conventions (DS=SS, CLD, SI and DI preserved)
  842. ;       We go through them in reverse order for onexit.
  843. ;
  844. ;Entry:
  845. ;       SI      = start of procedure list
  846. ;       DI      = end of procedure list
  847. ;
  848. ;Exit:
  849. ;
  850. ;Uses:
  851. ;
  852. ;Exceptions:
  853. ;
  854. ;*******************************************************************************
  855.  
  856. initterm:
  857.         cmp     si,di           ; are we done?
  858.         jae     itdone          ;   yes - no more
  859.  
  860. if      sizeC
  861.         sub     di,4
  862.         mov     ax,[di]
  863.         or      ax,[di+2]
  864.         jz      initterm        ; skip null procedures
  865.         call    dword ptr [di]
  866. else
  867.         dec     di
  868.         dec     di
  869.         mov     cx,[di]
  870.         jcxz    initterm        ; skip null procedures
  871.         call    cx
  872. endif
  873.         jmp     initterm        ; keep looping
  874.  
  875. itdone:
  876.         ret
  877.  
  878. page
  879. ife     sizeC                   ; S/C models only
  880. ;***
  881. ;farinitterm - do a set of far initializers or terminators
  882. ;
  883. ;Purpose:
  884. ;       The initializors and terminators may be written in C
  885. ;       so we are assuming C conventions (DS=SS, CLD, SI and DI preserved)
  886. ;       We go through them in reverse order for onexit.
  887. ;
  888. ;Entry:
  889. ;       SI      = start of procedure list
  890. ;       DI      = end of procedure list
  891. ;
  892. ;Exit:
  893. ;
  894. ;Uses:
  895. ;
  896. ;Exceptions:
  897. ;
  898. ;*******************************************************************************
  899.  
  900. farinitterm:
  901.         cmp     si,di           ; are we done?
  902.         jae     faritdone       ;   yes - no more
  903.  
  904.         sub     di,4
  905.         mov     ax,[di]
  906.         or      ax,[di+2]
  907.         jz      farinitterm     ; skip null procedures
  908.         call    dword ptr [di]
  909.         jmp     farinitterm     ; keep looping
  910.  
  911. faritdone:
  912.         ret
  913. endif   ;sizeC
  914. sEnd
  915.  
  916.         end
  917.