home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / World_Of_Computer_Software-02-385-Vol-1of3.iso / m / msc7.zip / C7CRT0DA.ASM < prev    next >
Assembly Source File  |  1992-02-14  |  23KB  |  1,135 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-1992, 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. ifdef _QWIN
  20. _WFILE_ =    20        ; Maximum number of QWIN file handles
  21. endif
  22.  
  23. ?DF    =    1        ;; tell cmacros.inc we want to define our own segments
  24.  
  25. .xlist
  26. include version.inc
  27. include cmacros.inc
  28. include msdos.inc
  29. include defsegs.inc
  30. include stdlib.inc
  31. .list
  32.  
  33. ifndef _WINDOWS
  34.     _DEBUGSCREEN equ 1        ; debug screen swapping
  35. endif
  36.  
  37. ifdef FARSTACK
  38. ife sizeD
  39. error <You cannot have a far stack in Small or Medium memory models.>
  40. endif
  41. endif
  42.  
  43. ifdef    _COM_
  44.     if sizeC or sizeD
  45.     error <Must use Small memory model for .COM files.>
  46.     endif
  47. endif    ;_COM_
  48.  
  49.  
  50. CrtDefSegs  <code,cdata,data>
  51.  
  52. ifdef _DEBUGSCREEN
  53.     CrtDefSegs    <dbdata>
  54. endif    ; _DEBUGSCREEN
  55.  
  56. ifndef _WINDOWS
  57.     CrtDefSegs    <xiqcseg>
  58. endif
  59.  
  60.     CrtDefSegs    <xifseg,xiseg,xoseg,xofseg,xpseg,xcseg,xcfseg>
  61.  
  62.     CrtDefSegs    <xifcseg>
  63.  
  64.  
  65. ifdef  _COM_
  66.     CrtDefSegs <emdata, emcode>
  67. endif    ;_COM_
  68.  
  69. defGrp    DGROUP            ; define DGROUP
  70.  
  71. codeOFFSET equ    offset _TEXT:
  72. dataOFFSET equ    offset DGROUP:
  73.  
  74. page
  75.  
  76.  
  77. sBegin    xifbseg
  78. xifbegin label    byte        ; Far initializers begin/end
  79. sEnd    xifbseg
  80.  
  81. sBegin    xifeseg
  82. xifend    label    byte
  83. sEnd    xifeseg
  84.  
  85.  
  86. sBegin    xibseg
  87. xibegin label    byte        ; Initializers begin/end
  88. sEnd    xibseg
  89.  
  90. sBegin    xieseg
  91. xiend    label    byte
  92. sEnd    xieseg
  93.  
  94.  
  95.     sBegin  xifcbseg
  96.     xifcbegin label   byte    ; far C++ constructors begin/end
  97.     sEnd    xifcbseg
  98.  
  99.     sBegin  xifceseg
  100.     xifcend   label   byte
  101.     sEnd    xifceseg
  102.  
  103.  
  104. sBegin    xobseg
  105. xontab    label    byte        ; atexit/onexit begin/end
  106. sEnd    xobseg
  107.  
  108. sBegin    xoeseg
  109. xonend    label    byte
  110. sEnd    xoeseg
  111.  
  112.  
  113. ife sizeC
  114.     ; in large model _fatexit = atexit so table not needed
  115.     sBegin  xofbseg
  116.     xfontab  label   byte    ; far atexit/onexit begin/end
  117.     sEnd    xofbseg
  118.  
  119.     sBegin  xofeseg
  120.     xfonend  label   byte
  121.     sEnd    xofeseg
  122. endif
  123.  
  124.  
  125. sBegin    xpbseg
  126. xpbegin label    byte        ; Pre-terminators begin/end
  127. sEnd    xpbseg
  128.  
  129. sBegin    xpeseg
  130. xpend    label    byte
  131. sEnd    xpeseg
  132.  
  133.  
  134. sBegin    xcbseg
  135. xcbegin label    byte        ; C terminators begin/end
  136. sEnd    xcbseg
  137.  
  138. sBegin    xceseg
  139. xcend    label    byte
  140. sEnd    xceseg
  141.  
  142.  
  143. sBegin    xcfbseg
  144. xcfbegin label    byte        ; C far terminators begin/end
  145. sEnd    xifbseg
  146.  
  147. sBegin    xcfeseg
  148. xcfend    label    byte
  149. sEnd    xcfeseg
  150.  
  151.  
  152. sBegin    cdata            ; floating point setup segment
  153. assumes ds,data
  154.  
  155.     dw    0        ; force segment to be at least 0's
  156. labelD    <PUBLIC,_fpinit>    ; public for signal
  157. fpmath    dd    1 dup (?)    ; linking trick for fp
  158. fpdata    dd    1 dup (?)
  159. fpsignal dd    1 dup (?)    ; fp signal message
  160.  
  161. sEnd
  162.  
  163.  
  164. ifdef _DEBUGSCREEN
  165. sBegin    dbdata                ;
  166.     assumes ds,data         ; Used to do the running under
  167. externW     __aDBswpflg        ; a debugger screen swapping
  168. externW     __aDBexit        ;
  169. sEnd    dbdata                ;
  170.     extrn    __aDBdoswp:ABS        ;
  171. endif    ; _DEBUGSCREEN
  172.  
  173. ifndef _WINDOWS
  174. sBegin    xiqcseg
  175. globalW    __qczrinit, 0            ;* QC -Zr initializer call address
  176. sEnd    xiqcseg
  177. endif
  178.  
  179.  
  180. ifdef  _COM_
  181.     sBegin  EmData
  182.     labelB  _EmDataLabel
  183.     sEnd    EmData
  184.  
  185.     sBegin  EmCode
  186.     globalW _EmDataSeg,0
  187.     sEnd    EmCode
  188.  
  189. else    ;not _COM
  190.   ifndef  _WINDOWS
  191.     EMULATOR_DATA  segment para public 'FAR_DATA'
  192.     EMULATOR_DATA  ends
  193.  
  194.     EMULATOR_TEXT  segment para public 'CODE'
  195.  
  196.     public __EmDataSeg
  197.     __EmDataSeg dw  EMULATOR_DATA
  198.  
  199.     EMULATOR_TEXT  ends
  200.   endif   ;not _WINDOWS
  201. endif    ;not _COM_
  202.  
  203. sBegin    data
  204. assumes ds,data
  205.  
  206. ifndef _WINDLL
  207. ;    special C environment string
  208.     labelB    <PUBLIC,_acfinfo>
  209.     cfile    db    '_C_FILE_INFO='
  210.     cfilex    db    0
  211.     cfileln =    cfilex-cfile
  212. endif    ;!_WINDLL
  213.  
  214. globalD _aintdiv,0        ; divide error interrupt vector save
  215.  
  216. globalT _fac,0            ; floating accumulator
  217. globalW errno,0         ; initial error code
  218. globalW _umaskval,0        ; initial umask value
  219.  
  220. ifndef _WINDLL
  221. ;=============== following must be in this order
  222.  
  223. globalW _pspadr,0        ; psp:0 (far * to PSP segment)
  224. globalW _psp,0            ; psp:0 (paragraph #)
  225.  
  226. ;=============== above must be in this order
  227. endif
  228.  
  229. ;=============== following must be in this order
  230. ifdef _WINDOWS
  231.  
  232. labelW    <PUBLIC,_osversion>        ; WIN version
  233. globalB _osmajor,0
  234. globalB _osminor,0
  235.  
  236. labelW    <PUBLIC,_dosversion>        ; DOS version
  237. globalB _dosmajor,0
  238. globalB _dosminor,0
  239.  
  240. else    ;!_WINDOWS
  241.  
  242. labelW    <PUBLIC,_osversion>        ; OS version
  243. labelB    <PUBLIC,_dosvermajor>
  244. globalB _osmajor,0
  245. labelB    <PUBLIC,_dosverminor>
  246. globalB _osminor,0
  247.  
  248. endif    ;_WINDOWS
  249. ;=============== above must be in this order
  250.  
  251.  
  252. ifdef _WINDOWS
  253. globalB _osmode,_WIN_MODE    ; Windows
  254. globalB _cpumode,_PROT_MODE    ; protect mode (default)
  255. else
  256. globalB _osmode,_DOS_MODE    ; DOS
  257. globalB _cpumode,_REAL_MODE    ; real mode
  258. endif
  259.  
  260. labelW    <PUBLIC,_oserr>
  261. globalW _doserrno,0        ; initial DOS error code
  262.  
  263. ;
  264. ; --- I/O Data ---
  265. ;
  266.  
  267. globalW _nfile,_NFILE_            ; maximum number of file handles
  268.  
  269. ifdef _QWIN
  270. globalW _wfile,_WFILE_            ; maximum number of QWIN file handles
  271. globalW _wnfile,(_NFILE_+_WFILE_)    ; maximum number of total file handles
  272. endif
  273.  
  274. ifdef _WINDOWS
  275. labelB    <PUBLIC,_osfile>
  276.     db    _NFILE_ dup (0)     ; (no std files in windows)
  277. else
  278. labelB    <PUBLIC,_osfile>
  279.     db    3 dup (FOPEN+FTEXT)    ; stdin, stdout, stderr
  280.     db    2 dup (FOPEN)        ; stdaux, stdprn
  281.     db    _NFILE_-5 dup (0)    ; the other 15 handles
  282. endif    ;_WINDOWS
  283.  
  284. ifdef    _QWIN
  285. labelB    <PUBLIC,_wsfile>
  286.     db    (FOPEN+FTEXT+FDEV)    ; stdin/out/err
  287.     db    _WFILE_-1 dup (0)    ; the other QWIN handles
  288.  
  289. ; Make sure _osfile and _wsfile are contiguous
  290. .ERRE    offset _osfile+_NFILE_ EQ offset _wsfile
  291. endif    ;_QWIN
  292.  
  293. ifdef _QWIN
  294. ;Force in QWIN system
  295. extrn    __qwinused:word         ; QWIN used/notused flag
  296. endif
  297.  
  298. ; --- End I/O Data ---
  299.  
  300. globalW __argc,0
  301. globalDP __argv,0
  302. globalDP _environ,0        ; environment pointer
  303.  
  304. labelD    <PUBLIC,_pgmptr>    ; pointer to program name
  305.     dw    dataOFFSET dos2nam
  306. ifdef _COM_
  307.     dw    0        ; No relocations in tiny model
  308. elseifdef _QC2
  309.     dw    0        ; No DGROUP references allowed
  310. elseifdef _WINDOWS
  311.     dw    0        ; No DGROUP references allowed
  312. else    ;DEFAULT
  313.     dw    DGROUP
  314. endif
  315.  
  316. dos2nam db    0        ; dummy argv[0] for DOS 2.X
  317.  
  318.  
  319. ; signal related common data
  320.  
  321. globalW _child,0        ; flag used to handle signals from child process
  322.  
  323. ifndef _WINDOWS
  324. ;Overlay related data
  325. globalB _ovlflag,0    ;Overlay flag (0 = no overlays)
  326. globalB _intno,0    ;Overlay interrupt value (e.g., 3F)
  327. globalD _ovlvec,0    ;Address of original overlay handler
  328. endif    ;!_WINDOWS
  329.  
  330.  
  331. globalB _exitflag,0    ; callable exit
  332.  
  333. sEnd    data
  334.  
  335. page
  336.  
  337. externNP _fptrap
  338.  
  339. ifndef    _WINDLL
  340.     externP _cintDIV
  341. endif
  342.  
  343. ifndef    _WINDOWS
  344.     externP _nullcheck
  345. endif
  346.  
  347. ifdef  FARSTACK
  348.     ifdef  _WINDOWS
  349.     externP _GetDGROUP
  350.     endif
  351. endif
  352.  
  353. ifdef _QWIN
  354.     externNP  _wcexit            ; exit the QWIN system
  355. endif
  356.  
  357. ifdef _WINDLL
  358.     extern    __nearstub:near         ; weak extern substitute
  359.     extern    __freefarheap(__nearstub):near    ; free up all far heap mem
  360.     extern    __freebasedheap(__nearstub):near; free up all based heap mem
  361. endif
  362.  
  363. if (_NFILE_ NE 20)
  364.     ifdef _WINDOWS
  365.     extern    SETHANDLECOUNT:far        ; set file count
  366.     endif
  367. endif
  368.  
  369. sBegin    code
  370. assumes cs,code
  371.  
  372. if    sizeC
  373. global    proc    far
  374. endif
  375.  
  376. page
  377. ;***
  378. ;_cinit - C initialization
  379. ;
  380. ;Purpose:
  381. ;    This routine performs the shared DOS and Windows initialization.
  382. ;    The following order of initialization must be preserved -
  383. ;
  384. ;    1.    Integer divide interrupt vector setup
  385. ;    2.    Floating point initialization
  386. ;    3.    Copy ;C_FILE_INFO into _osfile
  387. ;    4.    Check for devices for file handles 0 - 4
  388. ;    5.    General C initializer routines
  389. ;
  390. ;Entry:
  391. ;
  392. ;Exit:
  393. ;
  394. ;Uses:
  395. ;
  396. ;Exceptions:
  397. ;
  398. ;*******************************************************************************
  399.  
  400. cProc    _cinit,<PUBLIC>,<>
  401.  
  402. ifdef    _WINDOWS        ; add windows prolog/epilog code to far frames
  403. if    sizeC
  404. cBegin
  405. else
  406. cBegin    <nogen>
  407. endif    ;sizeC
  408. else
  409. cBegin    <nogen>         ; no local frame to set up in standard libs
  410. endif    ; _WINDOWS
  411.  
  412. assumes ds,data
  413. ifndef FARSTACK
  414. assumes ss,data
  415. endif
  416.  
  417. ifdef _COM_
  418. ;
  419. ;    Initialize the DGROUP portion of _pgmptr.  We must do this at
  420. ;    runtime since there are no load-time fixups in .COM files.
  421. ;
  422.     mov    word ptr [_pgmptr+2],ds ; init seg portion of _pgmptr
  423. endif    ;_COM_
  424.  
  425.  
  426. if (_NFILE_ NE 20)
  427. ;
  428. ;    *** Increase File Handle Count ***
  429. ;
  430. ifdef _WINDOWS
  431.     mov    bx,_NFILE_    ; number of file handle to allow
  432.     push    bx
  433.     call    SETHANDLECOUNT    ; issue the system call
  434.     ;check for error here, if desired (AX equals number of files supported)
  435. else
  436. ;    This code only works on DOS Version 3.3 and later.
  437.     mov    ah,67h        ; system call number
  438.     mov    bx,_NFILE_    ; number of file handles to allow
  439.     callos            ; issue the system call
  440.     ;check for error here, if desired (if carry set, AX equals error code)
  441. endif
  442. ;
  443. ;    *** End Increase File Handle Count ***
  444. ;
  445. endif    ; (_NFILE_ NE 20)
  446.  
  447.  
  448. ifndef    _WINDLL
  449.  
  450. ;    1.    Integer divide interrupt vector setup
  451.  
  452.     mov    ax,DOS_getvector shl 8 + 0
  453.     callos            ; save divide error interrupt
  454.     mov    word ptr [_aintdiv],bx
  455.     mov    word ptr [_aintdiv+2],es
  456.  
  457.     push    cs
  458.     pop    ds
  459.     assumes ds,nothing
  460.     mov    ax,DOS_setvector shl 8 + 0
  461.     mov    dx,codeOFFSET _cintDIV
  462.     callos            ; set divide error interrupt
  463.  
  464. ifdef FARSTACK
  465.     ifdef  _WINDOWS
  466.     callcrt _GetDGROUP
  467.     mov    ds, ax
  468.     else
  469.     mov    ax, DGROUP
  470.     mov    ds, ax
  471.     endif
  472. else
  473.     push    ss
  474.     pop    ds        ; restore DS=DGROUP
  475. endif
  476.     assumes ds,data
  477.  
  478. endif    ;!_WINDLL
  479.  
  480.  
  481. ;    2.    Floating point initialization
  482.  
  483.  
  484. if  memS
  485.  
  486.   ifdef  _WINDOWS
  487.     mov    cx,word ptr [fpmath+2]
  488.     jcxz    nofloat_i
  489.  
  490.   else      ;not _WINDOWS
  491.     cmp    word ptr [fpmath], 0        ; Note: make sure offset __fpmath != 0
  492.     je    nofloat_i
  493.  
  494.     mov    word ptr [fpmath+2], cs     ; fix up these far addresses
  495.     mov    word ptr [fpsignal+2], cs   ; in the small model math libs
  496.  
  497.     ifdef  _COM_
  498.     mov    [_EmDataSeg], cs
  499.     mov    ax, offset DGROUP:_EmDataLabel
  500.     sub    ax, offset EMULATOR_DATA:_EmDataLabel
  501.     mov    cl, 4
  502.     shr    ax, cl
  503.     add    [_EmDataSeg], ax
  504.     endif   ;_COM_
  505.  
  506.   endif   ;not _WINDOWS
  507.  
  508. else    ;not memS
  509.  
  510.     mov    cx,word ptr [fpmath+2]
  511.     jcxz    nofloat_i
  512.  
  513. endif    ;not memS
  514.  
  515. ifdef    _WINDLL
  516.     xor    si,si        ; no environment in Win DLL
  517. else    ;!_WINDLL
  518.     mov    es,[_psp]    ; psp segment
  519.     mov    si,es:[DOS_ENVP] ; environment segment
  520. endif    ;_WINDLL
  521.  
  522.     mov    ax, word ptr [fpdata]
  523.     mov    dx, word ptr [fpdata+2]
  524.     xor    bx,bx        ; (si) = environment segment
  525.     call    [fpmath]    ; fpmath(0) - init
  526.     jnc    fpok
  527.     jmp    _fptrap     ; issue "Floating point not loaded"
  528.                 ; error and abort
  529. fpok:
  530.  
  531. ifndef _WINDLL
  532.  
  533.     mov    ax, word ptr [fpsignal]
  534.     mov    dx, word ptr [fpsignal+2]
  535.     mov    bx,3
  536.     call    [fpmath]    ; fpmath(3) - set signal address
  537.  
  538. endif    ;!_WINDLL
  539.  
  540. nofloat_i:
  541.  
  542.  
  543.  
  544. ifndef _WINDLL
  545.  
  546. ;    3.    Copy _C_FILE_INFO= into _osfile
  547.  
  548. ;    fix up files inherited from parent using _C_FILE_INFO=
  549.  
  550.     mov    es,[_psp]    ; es = PSP
  551.     mov    cx,word ptr es:[DOS_envp] ; es = user's environment
  552.     jcxz    nocfi        ;   no environment !!!
  553.     mov    es,cx
  554.     xor    di,di        ; start at 0
  555.  
  556. cfilp:
  557.     cmp    byte ptr es:[di],0 ; check for end of environment
  558.     je    nocfi        ;   yes - not found
  559.     mov    cx,cfileln
  560.     mov    si,dataOFFSET cfile
  561.     repe    cmpsb        ; compare for '_C_FILE_INFO='
  562.     je    gotcfi        ;   yes - now do something with it
  563.     mov    cx,07FFFh    ; environment max = 32K
  564.     xor    ax,ax
  565.     repne    scasb        ; search for end of current string
  566.     jne    nocfi        ;   no 00 !!! - assume end of env.
  567.     jmp    cfilp        ; keep searching
  568.  
  569. ;    found _C_FILE_INFO= and transfer info into _osfile
  570.  
  571. gotcfi:
  572.     push    es
  573.     push    ds
  574.     pop    es        ; es = DGROUP
  575.     pop    ds        ; ds = env. segment
  576.     assumes ds,nothing
  577.     assumes es,data
  578.     mov    si,di        ; si = startup of _osfile info
  579.     mov    di,dataOFFSET _osfile ; di = _osfile block
  580.  
  581.     mov    cl, 4
  582.  
  583. osfile_lp:
  584.     lodsb
  585.     sub    al, 'A'
  586.     jb    donecfi
  587.     shl    al, cl
  588.     xchg    dx, ax
  589.  
  590.     lodsb
  591.     sub    al, 'A'
  592.     jb    donecfi
  593.     or    al, dl
  594.     stosb
  595.     jmp    short osfile_lp
  596.  
  597. donecfi:
  598. ifdef FARSTACK
  599.     push    es
  600. else
  601.     push    ss
  602. endif
  603.     pop    ds        ; ds = DGROUP
  604.     assumes ds,data
  605.  
  606. nocfi:
  607.  
  608. endif    ;!_WINDLL
  609.  
  610.  
  611. ifndef _WINDOWS
  612.  
  613. ;    4.    Check for devices for file handles 0 - 4
  614. ;
  615. ;        Clear the FDEV bit (which might be inherited from C_FILE_INFO)
  616. ;        and then call DOS to see if it really is a device or not
  617. ;
  618.     mov    bx,4
  619.  
  620. devloop:
  621.     and    _osfile[bx],not FDEV ; clear FDEV bit on principal
  622.  
  623.     mov    ax,DOS_ioctl shl 8 + 0 ; issue ioctl(0) to get dev info
  624.     callos
  625.     jc    notdev
  626.  
  627.     test    dl,80h        ; is it a device ?
  628.     jz    notdev        ;   no
  629.     or    _osfile[bx],FDEV ;   yes - set FDEV bit
  630.  
  631. notdev:
  632.     dec    bx
  633.     jns    devloop
  634.  
  635. endif    ;!_WINDOWS
  636.  
  637.  
  638. ;    5.    General C initializer routines
  639.  
  640.     mov    si,dataOFFSET xifbegin
  641.     mov    di,dataOFFSET xifend
  642.     call    farinitterm    ; call the far initializers
  643.  
  644.     mov    si,dataOFFSET xibegin
  645.     mov    di,dataOFFSET xiend
  646.     call    initterm    ; call the initializers
  647.  
  648.     mov    si,dataOFFSET xifcbegin
  649.     mov    di,dataOFFSET xifcend
  650.     call    farinitterm    ; call far C++ constructors.
  651.  
  652. ifdef    _WINDOWS    ; add epilog code to windows far frame
  653. if    sizeC
  654. cEnd
  655. else
  656.     ret
  657. cEnd    <nogen>
  658. endif    ;sizeC
  659. else
  660.     ret
  661. cEnd    <nogen>     ; standard C libs
  662. endif    ; _WINDOWS
  663.  
  664.  
  665. page
  666. ;***
  667. ;exit(status), _exit(status), _cexit(void), _c_exit(void) - C termination
  668. ;
  669. ;Purpose:
  670. ;
  671. ;    Entry points:
  672. ;
  673. ;        exit(code):  Performs all the C termination functions
  674. ;            and terminates the process with the return code
  675. ;            supplied by the user.
  676. ;
  677. ;        _exit(code):  Performs a quick exit routine that does not
  678. ;            do certain 'high-level' exit processing.  The _exit
  679. ;            routine terminates the process with the return code
  680. ;            supplied by the user.
  681. ;
  682. ;        _cexit():  Performs the same C lib termination processing
  683. ;            as exit(code) but returns control to the caller
  684. ;            when done (i.e., does NOT terminate the process).
  685. ;
  686. ;        _c_exit():  Performs the same C lib termination processing
  687. ;            as _exit(code) but returns control to the caller
  688. ;            when done (i.e., does NOT terminate the process).
  689. ;
  690. ;    Termination actions:
  691. ;
  692. ;        exit(), _cexit ():
  693. ;
  694. ;        1.    call user's terminator routines
  695. ;        2.    call C runtime preterminators
  696. ;
  697. ;        _exit(), _c_exit():
  698. ;
  699. ;        3.    call C runtime terminators
  700. ;        4.    perform _nullcheck() for null pointer assignment
  701. ;        5.    terminate floating point
  702. ;        6.    reset divide by zero interrupt vector
  703. ;        7.    return to DOS or caller
  704. ;
  705. ;    Notes:
  706. ;
  707. ;    The termination sequence is complicated due to the multiple entry
  708. ;    points sharing the common code body while having different entry/exit
  709. ;    sequences.
  710. ;
  711. ;Entry:
  712. ;    exit(), _exit()
  713. ;        int status - exit status (0-255)
  714. ;
  715. ;    _cexit(), _c_exit()
  716. ;        <no input>
  717. ;
  718. ;Exit:
  719. ;    exit(), _exit()
  720. ;        <EXIT to DOS>
  721. ;
  722. ;    _cexit(), _c_exit()
  723. ;        Return to caller
  724. ;
  725. ;Uses:
  726. ;
  727. ;Exceptions:
  728. ;
  729. ;*******************************************************************************
  730.  
  731. ifndef _WINDLL
  732.  
  733. ;
  734. ;--- exit(): Full exit and term process ---
  735. ;
  736.  
  737.  
  738. public    _exit
  739. _exit:
  740. cProc    dummy1,<>,<>
  741.  
  742.     parmw    status        ; termination code
  743.  
  744. cBegin
  745.  
  746.     xor    cx,cx        ; exit(): cl = 0, ch = 0
  747.     jmp    short common1    ; join common code
  748.  
  749. cEnd    <nogen>
  750.  
  751. ;
  752. ;--- _exit(): Quickie exit and term process ---
  753. ;
  754.  
  755.  
  756. public    __exit
  757. __exit:
  758. cProc    dummy2,<>,<>
  759.  
  760.     parmw    status        ; termination code
  761.  
  762. cBegin
  763.  
  764.     mov    cx,1        ; _exit(): cl = 1, ch = 0
  765.     jmp    short common1    ; join common code
  766.  
  767. cEnd    <nogen>
  768.  
  769. endif    ;!_WINDLL
  770.  
  771. if    sizeC
  772. global    endp
  773. endif
  774.  
  775. ;
  776. ;--- _cexit(): Full exit and return to caller ---
  777. ;
  778.  
  779. cProc    _cexit,<PUBLIC>,<SI,DI>
  780.  
  781. cBegin
  782.  
  783.     mov    cx,(1 SHL 8)    ; _cexit(): ch = 1, cl = 0
  784.     jmp    short common1    ; join common code
  785.  
  786. cEnd    <nogen>
  787.  
  788. ;
  789. ;--- _c_exit(): Quickie exit and return to caller ---
  790. ;
  791.  
  792. cProc    _c_exit,<PUBLIC>,<SI,DI>
  793.  
  794. cBegin
  795.  
  796.     mov    cx,(1 SHL 8)+1    ; _c_exit(): ch = 1, cl = 1
  797.     ;fall through
  798.  
  799. ;
  800. ;--- Common entry point ---
  801. ; cx = entry value:
  802. ;    cl = full vs quick exit path
  803. ;         0 = exit() code
  804. ;         1 = _exit() code
  805. ;    ch = term process vs return to caller
  806. ;         0 = term process
  807. ;         1 = return to caller
  808. ;
  809.  
  810. common1:            ; all code paths join here
  811.  
  812. assumes ds,data
  813. ifndef FARSTACK
  814. assumes ss,data
  815. endif
  816.  
  817. ;
  818. ; save exit flag (used by terminators)
  819. ;
  820.     mov    [_exitflag],ch
  821.  
  822. ;
  823. ; If _exit()/_c_exit(), jump over the initial termination processing
  824. ; cx = entry code
  825. ;
  826.  
  827.     push    cx        ; save entry code on top of stack
  828.     or    cl,cl        ; cl != 0 means _exit()/_c_exit()
  829.     jnz    short common2    ; if _exit()/_c_exit(), jump down
  830.     ;fall thru        ; continue (exit, _cexit)
  831.  
  832.  
  833. ;    1.    call user terminators
  834. ;        (atexit/onexit processing)
  835.  
  836.     mov    si,dataOFFSET xontab
  837.     mov    di,dataOFFSET xonend
  838.     call    initterm    ; atexit/onexit table
  839.  
  840. ife sizeC
  841.     ; in large code, _fatexit = atexit so no need to walk far table
  842.     mov    si,dataOFFSET xfontab
  843.     mov    di,dataOFFSET xfonend
  844.     call    farinitterm    ; far atexit/onexit table
  845. endif
  846.  
  847. ;    2.    call C runtime preterminators
  848. ;        - flushall
  849. ;        - rmtmp
  850.  
  851.     mov    si,dataOFFSET xpbegin ; beginning of pre-terminators
  852.     mov    di,dataOFFSET xpend ; end of pre-terminators
  853.     call    initterm
  854.  
  855. ifdef _QWIN
  856. ;
  857. ; Exit the QWIN system.  We can't do this in the pre-terminators because
  858. ; we want to make sure flushall() gets called before _QWINExit.
  859. ;
  860.     mov    si,[status]
  861.     push    si
  862.     call    _wcexit
  863.     add    sp,2
  864.  
  865. endif    ;_QWIN
  866.  
  867. ifdef _DEBUGSCREEN
  868. ;
  869. ; Tell the debugger we are going to exit
  870. ;
  871.     cmp    __aDBswpflg,__aDBdoswp    ; Are we under a debugger?
  872.     jne    @F            ; No -- skip forward
  873.     cCall    __aDBexit        ; Yes -- tell it we are exiting
  874. @@:
  875. endif    ; _DEBUGSCREEN
  876.  
  877. ;
  878. ;--- Common entry point ---
  879. ;
  880.  
  881. common2:            ; __exit() enters here
  882.  
  883.  
  884. ;    3.    perform C terminators
  885.  
  886.     mov    si,dataOFFSET xcbegin
  887.     mov    di,dataOFFSET xcend
  888.     call    initterm    ; call the terminators
  889.  
  890.     mov    si,dataOFFSET xcfbegin
  891.     mov    di,dataOFFSET xcfend
  892.     call    farinitterm    ; call the far terminators
  893.  
  894. ;    4.    perform _nullcheck() for null pointer assignment
  895.  
  896. ifndef    _COM_        ; DS:0 is the PSP in .COM files!
  897. ifndef    _WINDOWS    ; Don't validate the copyright message in windows
  898.  
  899.     call    _nullcheck    ; check data in NULL data segment at DS:0
  900.                 ; this must be far call in large code models
  901.                 ; since user can stub it out
  902.     or    ax,ax        ; zero if no null ptr assignment detected
  903.     jz    afternullchk
  904.  
  905.     pop    ax        ; get entry code
  906.     or    ah,ah        ; ah != 0 means _cexit()/_c_exit()
  907.     push    ax        ; put it back for later
  908.     jnz     short afternullchk ; jump if no status value (_cexit/_c_exit)
  909.  
  910.     cmp    status,0    ; zero if no other error has occurred
  911.     jnz    short afternullchk
  912.     mov    status,255    ; nonzero status to indicate an
  913.                 ; null-pointer-assignment error
  914. afternullchk:
  915.  
  916. endif    ;_WINDOWS
  917. endif    ;_COM_
  918.  
  919. ;    5.    terminate floating point
  920. ;    6.    reset divide by zero interrupt vector
  921.  
  922.     call    _ctermsub    ; fast cleanup
  923.  
  924. ifdef _WINDLL
  925. ;    6a.    free up all global memory to the OS
  926. ;        [NOTE 1: This is necessary because WINDLL memory is
  927. ;        shared and windows won't reclaim it.]
  928. ;        [NOTE 2: This routine must be called last because a
  929. ;        terminator may reference the heap.]
  930.  
  931.     call    __freefarheap     ; free up far memory
  932.     call    __freebasedheap  ; free up based memory
  933. endif
  934.  
  935. ;    7.    return to the DOS or caller
  936.  
  937. ifdef  _WINDLL
  938.     ; Always return to caller (exit/_exit is illegal)
  939.     pop    ax        ; clean off stack
  940. else
  941.     pop    ax        ; get entry code off top of stack
  942.     or    ah,ah        ; ah = 0 means term process
  943.     jnz     returning    ; skip down if not term'ing
  944.  
  945. ;    7a.     return to the DOS
  946.  
  947. exiting:
  948.     mov    ax,status    ; get return value
  949.  
  950.     callos    terminate    ; exit with al = return code
  951.  
  952.  
  953.     ;*** PROCESS IS TERMINATED ***
  954.  
  955. endif    ;_WINDLL
  956.  
  957. ;    7b.    Return to caller.
  958.  
  959. returning:
  960.  
  961. cEnd    <nolocals>
  962.  
  963.  
  964. page
  965. ;***
  966. ;_ctermsub - more C termination code
  967. ;
  968. ;Purpose:
  969. ;    This routine
  970. ;        (1) performs floating-point termination
  971. ;        (2) resets the divide by zero interrupt vector
  972. ;        (3) restore int 3F handler
  973. ;
  974. ;Entry:
  975. ;
  976. ;Exit:
  977. ;
  978. ;Uses:
  979. ;    AX,BX,CX,DX.
  980. ;
  981. ;Exceptions:
  982. ;
  983. ;*******************************************************************************
  984.  
  985. labelNP <PUBLIC,_ctermsub>
  986.  
  987. ;    4.    terminate floating point
  988.  
  989.  
  990.     mov    cx,word ptr [fpmath+2] ; test for floating point
  991.     jcxz    nofloat_t    ;   no
  992.  
  993.     mov    bx,2        ;   yes - cleanup
  994.     call    [fpmath]
  995.  
  996. nofloat_t:
  997.  
  998.  
  999.  
  1000. ifndef    _WINDLL
  1001.  
  1002. ;    5.    reset divide by zero interrupt vector
  1003.  
  1004.     mov    ax, 1686h
  1005.     int    2fh
  1006.     or    ax, ax
  1007.     jz    protUnhook
  1008.  
  1009.     push    ds
  1010.     lds    dx,[_aintdiv]    ; ds:dx = restore vector
  1011.     mov    ax,DOS_setvector shl 8 + 0
  1012.     callos            ; set divide error interrupt
  1013.     pop    ds
  1014.     jmp    short _ctsExit
  1015.  
  1016.  
  1017. protUnhook:
  1018.     mov    ax, 201h
  1019.     mov    bl, 0
  1020.     mov    cx, word ptr [_aintdiv+2]
  1021.     mov    dx, word ptr [_aintdiv]
  1022.     int    31h
  1023.  
  1024. endif    ;!_WINDLL
  1025.  
  1026. _ctsExit:
  1027.     ret
  1028.  
  1029.  
  1030. page
  1031. ;***
  1032. ;initterm - do a set of initializers or terminators
  1033. ;
  1034. ;Purpose:
  1035. ;    The initializors and terminators may be written in C
  1036. ;    so we are assuming C conventions (DS=SS, CLD, SI and DI preserved)
  1037. ;    We go through them in reverse order for onexit.
  1038. ;
  1039. ;Entry:
  1040. ;    SI    = start of procedure list
  1041. ;    DI    = end of procedure list
  1042. ;
  1043. ;Exit:
  1044. ;
  1045. ;Uses:
  1046. ;
  1047. ;Exceptions:
  1048. ;
  1049. ;*******************************************************************************
  1050.  
  1051. if sizeC
  1052. farinitterm:            ; large code farinitterm = initterm
  1053. endif
  1054.  
  1055. initterm:
  1056.     cmp    si,di        ; are we done?
  1057.     jae    itdone        ;   yes - no more
  1058.  
  1059. if    sizeC
  1060.     sub    di,4
  1061.     mov    ax,[di]
  1062.     or    ax,[di+2]
  1063.     jz    initterm    ; skip null procedures
  1064.     call    dword ptr [di]
  1065. else
  1066.     dec    di
  1067.     dec    di
  1068.     mov    cx,[di]
  1069.     jcxz    initterm    ; skip null procedures
  1070.     call    cx
  1071. endif
  1072.     jmp    initterm    ; keep looping
  1073.  
  1074. itdone:
  1075.     ret
  1076.  
  1077. page
  1078.  
  1079. ife    sizeC            ; S/C models only
  1080. ;***
  1081. ; chkvector - if exiting in protected mode, fixup the terminate vector
  1082. ;
  1083. ; input: ds:[di] points to vector
  1084. ;
  1085. chkvector PROC USES AX 
  1086.     mov    ax, 1686h
  1087.     int    2fh
  1088.     or    ax, ax
  1089.     jnz    cvExit
  1090.  
  1091.     mov    [di].2, cs
  1092. cvExit:
  1093.     ret
  1094. chkvector ENDP
  1095.  
  1096. ;***
  1097. ;farinitterm - do a set of far initializers or terminators
  1098. ;
  1099. ;Purpose:
  1100. ;    The initializors and terminators may be written in C
  1101. ;    so we are assuming C conventions (DS=SS, CLD, SI and DI preserved)
  1102. ;    We go through them in reverse order for onexit.
  1103. ;
  1104. ;Entry:
  1105. ;    SI    = start of procedure list
  1106. ;    DI    = end of procedure list
  1107. ;
  1108. ;Exit:
  1109. ;
  1110. ;Uses:
  1111. ;
  1112. ;Exceptions:
  1113. ;
  1114. ;*******************************************************************************
  1115.  
  1116. farinitterm:
  1117.     cmp    si,di        ; are we done?
  1118.     jae    faritdone    ;   yes - no more
  1119.  
  1120.     sub    di,4
  1121.     mov    ax,[di]
  1122.     or    ax,[di+2]
  1123.     jz    farinitterm    ; skip null procedures
  1124.     call    chkvector
  1125.     call    dword ptr [di]
  1126.     jmp    farinitterm    ; keep looping
  1127.  
  1128. faritdone:
  1129.     ret
  1130. endif    ;sizeC
  1131.  
  1132. sEnd
  1133.  
  1134.     end
  1135.