home *** CD-ROM | disk | FTP | other *** search
/ Programmer Plus 2007 / Programmer-Plus-2007.iso / Programming / Low Level Languages / FORTRAN.500 / DISK5 / OS2 / CRT0DAT.AS$ / CRT0DAT.bin
Encoding:
Text File  |  1991-02-01  |  15.3 KB  |  765 lines

  1.     page    ,132
  2.     title    crt0dat - OS/2 C run-time initialization/termination
  3. ;***
  4. ;crt0dat.asm - OS/2 C run-time initialization/termination routines
  5. ;
  6. ;    Copyright (c) 1986-1990, Microsoft Corporation, All Rights Reserved
  7. ;
  8. ;Purpose:
  9. ;    This module contains the routines _cinit, exit, and _exit
  10. ;    for C run-time startup and termination.  _cinit and exit
  11. ;    are called from the _astart code in crt0.asm.
  12. ;
  13. ;    [NOTE: Lock segment definitions are at end of module.]
  14. ;
  15. ;*******************************************************************************
  16.  
  17. _NFILE_ =    20
  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.  
  28. ifdef FARSTACK
  29. ife sizeD
  30.     error <You cannot have a far stack in Small or Medium memory models.>
  31. endif
  32. endif
  33.  
  34. createSeg _TEXT, code,    word,    public, CODE,    <>
  35. createSeg CDATA, cdata, word,    common, DATA,    DGROUP
  36. createSeg _DATA, data,    word,    public, DATA,    DGROUP
  37.  
  38. createSeg XIFB, xifbseg, word,    public, DATA,    DGROUP
  39. createSeg XIF,    xifseg, word,    public, DATA,    DGROUP ; far init's
  40. createSeg XIFE, xifeseg, word,    public, DATA,    DGROUP
  41.  
  42. createSeg XIB,    xibseg, word,    public, DATA,    DGROUP
  43. createSeg XI,    xiseg,    word,    public, DATA,    DGROUP ; init's
  44. createSeg XIE,    xieseg, word,    public, DATA,    DGROUP
  45.  
  46. createSeg XOB,    xobseg, word,    public, BSS,    DGROUP
  47. createSeg XO,    xoseg,    word,    public, BSS,    DGROUP ; onexit table
  48. createSeg XOE,    xoeseg, word,    public, BSS,    DGROUP
  49.  
  50. createSeg XPB,    xpbseg, word,    public, DATA,    DGROUP
  51. createSeg XP,    xpseg,    word,    public, DATA,    DGROUP ; preterm's
  52. createSeg XPE,    xpeseg, word,    public, DATA,    DGROUP
  53.  
  54. createSeg XCB,    xcbseg, word,    public, DATA,    DGROUP
  55. createSeg XC,    xcseg,    word,    public, DATA,    DGROUP ; term's
  56. createSeg XCE,    xceseg, word,    public, DATA,    DGROUP
  57.  
  58. createSeg XCFB, xcfbseg, word,    public, DATA,    DGROUP
  59. createSeg XCF,    xcfseg, word,    public, DATA,    DGROUP ; far term's
  60. createSeg XCFE, xcfeseg, word,    public, DATA,    DGROUP
  61.  
  62. defGrp    DGROUP            ;; define DGROUP
  63.  
  64. codeOFFSET equ    offset _TEXT:
  65. dataOFFSET equ    offset DGROUP:
  66.  
  67. page
  68. sBegin    xifbseg
  69. xifbegin label    byte
  70. sEnd    xifbseg
  71.  
  72. sBegin    xifeseg
  73. xifend    label    byte
  74. sEnd    xifeseg
  75.  
  76. sBegin    xibseg
  77. xibegin label    byte
  78. sEnd    xibseg
  79.  
  80. sBegin    xieseg
  81. xiend    label    byte
  82. sEnd    xieseg
  83.  
  84. sBegin    xobseg
  85. xontab    label    byte        ; start of onexit table
  86. sEnd    xobseg
  87.  
  88. sBegin    xoeseg
  89. xonend    label    byte
  90. sEnd    xoeseg
  91.  
  92. sBegin    xpbseg
  93. xpbegin label    byte        ; end of onexit table
  94. sEnd    xpbseg
  95.  
  96. sBegin    xpeseg
  97. xpend    label    byte
  98. sEnd    xpeseg
  99.  
  100. sBegin    xcbseg
  101. xcbegin label    byte
  102. sEnd    xcbseg
  103.  
  104. sBegin    xceseg
  105. xcend    label    byte
  106. sEnd    xceseg
  107.  
  108. sBegin    xcfbseg
  109. xcfbegin label    byte
  110. sEnd    xifbseg
  111.  
  112. sBegin    xcfeseg
  113. xcfend    label    byte
  114. sEnd    xcfeseg
  115.  
  116.  
  117. sBegin    cdata            ; floating point setup segment
  118. assumes ds,data
  119.  
  120.     dw    0        ; force segment to be at least 0's
  121. labelD    <PUBLIC,_fpinit>    ; public for signal
  122. fpmath    dd    1 dup (?)    ; linking trick for fp
  123. fpdata    dd    1 dup (?)
  124. fpsignal dd    1 dup (?)    ; fp signal message
  125.  
  126. externW _aenvseg        ; Selector of Environment segment
  127. sEnd
  128.  
  129. sBegin    data
  130. assumes ds,data
  131.  
  132.  
  133. globalT _fac,0            ; floating accumulator
  134. globalW errno,0         ; initial error code
  135.  
  136. globalW _umaskval,0        ; initial umask value
  137.  
  138. ;================= following must be in this order
  139.  
  140. labelW    <PUBLIC,_osversion>
  141. labelB    <PUBLIC,_dosvermajor>
  142. globalB _osmajor,0
  143. labelB    <PUBLIC,_dosverminor>
  144. globalB _osminor,0
  145.  
  146. ;================= above must be in this order
  147.  
  148. labelB    <PUBLIC,_dosmode>
  149. globalB _osmode,0        ; Dual-Mode execution
  150. labelW    <PUBLIC,_oserr>
  151. globalW _doserrno,0        ; initial DOS error code
  152.  
  153.  
  154. globalW _nfile,_NFILE_        ; maximum number of file handle
  155.  
  156. labelB    <PUBLIC,_osfile>
  157.     db    3 dup (FOPEN+FTEXT) ; stdin, stdout, stderr
  158.     db    _NFILE_-3 dup (0) ; the other 17 handles
  159.  
  160. labelB    <PUBLIC,_pipech>
  161.     db    _NFILE_ dup (0AH) ; peek-ahead buffers for pipes
  162.  
  163.  
  164. globalW __argc,0
  165. globalDP __argv,0
  166. globalDP environ,0        ; environment pointer
  167. globalD _pgmptr,0        ; far pointer to program name
  168.  
  169. globalW _child,0        ; flag that child program is executing
  170.                 ; needed by signal code in real mode
  171.  
  172.  
  173. sEnd    data
  174.  
  175. page
  176.  
  177.  
  178. extrn    DOSQHANDTYPE:far
  179. extrn    DOSSETVEC:far
  180. extrn    DOSEXIT:far
  181.  
  182. ;    *** Increase File Handle Count ***
  183. ;    Enable this extrn reference if you are increasing the file count.
  184. ;
  185. ;extrn    DOSSETMAXFH:far
  186. ;
  187. ;    *** End Increase File Handle Count ***
  188.  
  189. externNP _fptrap
  190. externP _cintDIV
  191. externP _nullcheck
  192.  
  193. sBegin    code
  194. assumes cs,code
  195.  
  196. if    sizeC
  197. global    proc    far
  198. endif
  199.  
  200.  
  201. page
  202. ;***
  203. ;_cinit - C initialization
  204. ;
  205. ;Purpose:
  206. ;    This routine performs the shared DOS and Windows initialization.
  207. ;    The following order of initialization must be preserved -
  208. ;
  209. ;    1.    Check for devices for file handles 0 - 2
  210. ;    2.    Integer divide interrupt vector setup
  211. ;    3.    Floating point initialization
  212. ;    4.    General C initializer routines
  213. ;
  214. ;Entry:
  215. ;
  216. ;Exit:
  217. ;
  218. ;Uses:
  219. ;
  220. ;Exceptions:
  221. ;
  222. ;*******************************************************************************
  223.  
  224. cProc    _cinit,<PUBLIC>,<>
  225.  
  226. cBegin    nogen            ; no local frame to set up
  227. assumes ds,data
  228. ifndef FARSTACK
  229. assumes ss,data
  230. endif
  231.  
  232.  
  233. ;    *** Increase File Handle Count ***
  234. ;
  235. ;    This code is intentially commented out; the user must enable
  236. ;    this code to access more than 20 files.
  237. ;
  238. ;    mov    ax,_NFILE_    ; new file handle count
  239. ;    push    ax        ; onto stack
  240. ;    call    DOSSETMAXFH    ; set new file handle limit
  241. ;    ;check for error here, if desired (AX = 0 means no error)
  242. ;
  243. ;    *** End Increase File Handle Count ***
  244.  
  245.  
  246. ;    1.    Check for devices for file handles 0 - 2
  247.  
  248.     mov    bx,2
  249.  
  250.     push    dx        ; space for device driver attribute
  251.     mov    dx,sp
  252. devloop:
  253.     and    _osfile[bx],not (FDEV or FPIPE)
  254.                 ; Assume this handle is not a device or pipe
  255.     push    ax        ; space for isdevice flag
  256.     mov    ax,sp
  257.     push    bx        ; handle
  258.     push    ss
  259.     push    ax        ; address for isdevice flag
  260.     push    ss
  261.     push    dx        ; address for device driver attribute
  262.     call    DOSQHANDTYPE
  263.  
  264.     or    ax,ax        ; test for error
  265.     pop    ax        ; get isdevice flag
  266.     jnz    notdevpipe
  267.  
  268.     ; Note that we only test bottom 8 bits of device flag, high
  269.     ; byte has network info we're not interested in.
  270.     mov    cl,FDEV     ; assume device
  271.     cmp    al,IS_DEV    ; is the handle a device ?
  272.     je    devpipe     ; yes - set FDEV bit
  273.     cmp    al,IS_PIPE    ; is the handle a pipe ?
  274.     jne    notdevpipe    ; no - it is a file
  275.     mov    cl,FPIPE    ; PIPE instead of DEVICE
  276. devpipe:
  277.     or    _osfile[bx],cl    ; set FDEV or FPIPE bit as appropriate
  278. notdevpipe:
  279.     dec    bx
  280.     jns    devloop
  281.  
  282.     pop    dx        ; clean up stack
  283.  
  284. ;    2.    Integer divide interrupt vector setup
  285.  
  286.     xor    ax,ax
  287.  
  288.     push    ax
  289.     push    ax        ; space for previous handler (returned)
  290.     mov    bx,sp
  291.  
  292.     push    ax        ; zero means divide by 0 exception
  293.  
  294.     mov    dx,offset _TEXT:__cintDIV
  295.     push    cs
  296.     push    dx        ; address of divide exception handler
  297.  
  298.     push    ss
  299.     push    bx        ; address of address for prev. handler
  300.  
  301.     call    DOSSETVEC
  302.     pop    ax        ; clean-up stack
  303.     pop    ax        ; (ignore return value)
  304.  
  305. ;    3.    Floating point initialization
  306.  
  307.  
  308. if  memS
  309.     cmp    word ptr [fpmath], 0        ; Note: make sure offset __fpmath != 0
  310.     je    nofloat_i
  311.  
  312.     mov    word ptr [fpmath+2], cs     ; fix up these far addresses
  313.     mov    word ptr [fpsignal+2], cs   ; in the small model math libs
  314.  
  315. else    ;not memS
  316.     mov    cx,word ptr [fpmath+2]
  317.     jcxz    nofloat_i
  318. endif    ;not memS
  319.  
  320. ifdef    FARSTACK
  321.     push    ds
  322.     pop    es
  323.     assumes es,data     ; es = DGROUP
  324. endif
  325.     mov    si,[_aenvseg]    ; environment segment
  326.     lds    ax,[fpdata]    ; get task data area
  327.     assumes ds,nothing
  328.     mov    dx,ds        ;   into dx:ax
  329.     xor    bx,bx        ; (si) = environment segment
  330.     call    [fpmath]    ; fpmath(0) - init
  331.     jnc    fpok
  332.  
  333. ifdef FARSTACK
  334.     mov    ax, DGROUP
  335.     mov    ds, ax        ; restore ds
  336.     assumes ds,data
  337.     assumes es,nothing
  338. else
  339.     push    ss        ; restore ds from ss
  340.     pop    ds
  341. endif
  342.     jmp    _fptrap     ; issue "Floating point not loaded"
  343.                 ; error and abort
  344.  
  345. fpok:
  346. ifdef FARSTACK
  347.     assumes ds,nothing
  348.     mov    ax,DGROUP
  349.     mov    es,ax
  350.     assumes es,data
  351. endif
  352.     lds    ax,[fpsignal]    ; get signal address
  353.     assumes ds,nothing
  354.     mov    dx,ds
  355.     mov    bx,3
  356.     call    [fpmath]    ; fpmath(3) - set signal address
  357. ifdef FARSTACK
  358.     mov    ax, DGROUP
  359.     mov    ds, ax        ; restore ds
  360.     assumes ds,data
  361.     assumes es,nothing
  362. else
  363.     push    ss
  364.     pop    ds
  365.     assumes ds,data
  366. endif
  367.  
  368. nofloat_i:
  369.  
  370.  
  371. ;    4.    General C initializer routines
  372.  
  373.     mov    si,dataOFFSET xifbegin
  374.     mov    di,dataOFFSET xifend
  375. if    sizeC
  376.     call    initterm    ; call the far initializers
  377. else
  378.     call    farinitterm    ; call the far initializers
  379. endif
  380.  
  381.     mov    si,dataOFFSET xibegin
  382.     mov    di,dataOFFSET xiend
  383.     call    initterm    ; call the initializers
  384.  
  385.     ret
  386. cEnd    nogen
  387.  
  388.  
  389.  
  390. page
  391. ;***
  392. ;exit(status), _exit(status), _cexit(void), _c_exit(void) - C termination
  393. ;
  394. ;Purpose:
  395. ;
  396. ;    Entry points:
  397. ;
  398. ;        exit(code):  Performs all the C termination functions
  399. ;            and terminates the process with the return code
  400. ;            supplied by the user.
  401. ;
  402. ;        _exit(code):  Performs a quick exit routine that does not
  403. ;            do certain 'high-level' exit processing.  The _exit
  404. ;            routine terminates the process with the return code
  405. ;            supplied by the user.
  406. ;
  407. ;        _cexit():  Performs the same C lib termination processing
  408. ;            as exit(code) but returns control to the caller
  409. ;            when done (i.e., does NOT terminate the process).
  410. ;
  411. ;        _c_exit():  Performs the same C lib termination processing
  412. ;            as _exit(code) but returns control to the caller
  413. ;            when done (i.e., does NOT terminate the process).
  414. ;
  415. ;    Termination actions:
  416. ;
  417. ;        exit(), _cexit():
  418. ;
  419. ;        1.    call user's terminator routines
  420. ;        2.    call C runtime preterminators
  421. ;
  422. ;        _exit(), _c_exit():
  423. ;
  424. ;        3.    call C runtime terminators
  425. ;        4.    perform _nullcheck() for null pointer assignment
  426. ;        5.    terminate floating point
  427. ;        6.    return to DOS or caller
  428. ;
  429. ;    Notes:
  430. ;
  431. ;    The termination sequence is complicated due to the multiple entry
  432. ;    points sharing the common code body while having different entry/exit
  433. ;    sequences.
  434. ;
  435. ;Entry:
  436. ;    exit(), _exit()
  437. ;        int status - exit status (0-255)
  438. ;
  439. ;    _cexit(), _c_exit()
  440. ;        <no input>
  441. ;
  442. ;Exit:
  443. ;    exit(), _exit()
  444. ;        <EXIT to DOS>
  445. ;
  446. ;    _cexit(), _c_exit()
  447. ;        Return to caller
  448. ;
  449. ;Uses:
  450. ;
  451. ;Exceptions:
  452. ;
  453. ;*******************************************************************************
  454.  
  455. ;
  456. ;--- exit(): Full exit and term process ---
  457. ;
  458.  
  459. public    _exit
  460. _exit:
  461. cProc    dummy1,<>,<>
  462.  
  463.     parmw    status        ; termination code
  464.  
  465. cBegin
  466.  
  467.     xor    cx,cx        ; exit(): cl = 0, ch = 0
  468.     jmp    short common1    ; join common code
  469.  
  470. cEnd    <nogen>
  471.  
  472. ;
  473. ;--- _exit(): Quickie exit and term process ---
  474. ;
  475.  
  476. public    __exit
  477. __exit:
  478. cProc    dummy2,<>,<>
  479.  
  480.     parmw    status        ; termination code
  481.  
  482. cBegin
  483.  
  484.     mov    cx,1        ; _exit(): cl = 1, ch = 0
  485.     jmp    short common1    ; join common code
  486.  
  487. cEnd    <nogen>
  488.  
  489. if    sizeC
  490. global    endp
  491. endif
  492.  
  493. ;
  494. ;--- _cexit(): Full exit and return to caller ---
  495. ;
  496.  
  497. cProc    _cexit,<PUBLIC>,<SI,DI>
  498.  
  499. cBegin
  500.  
  501.     mov    cx,(1 SHL 8)    ; _cexit(): ch = 1, cl = 0
  502.     jmp    short common1    ; join common code
  503.  
  504. cEnd    <nogen>
  505.  
  506. ;
  507. ;--- _c_exit(): Quickie exit and return to caller ---
  508. ;
  509.  
  510. cProc    _c_exit,<PUBLIC>,<SI,DI>
  511.  
  512. cBegin
  513.  
  514.     mov    cx,(1 SHL 8)+1    ; _c_exit(): ch = 1, cl = 1
  515.     ;fall through
  516.  
  517. ;
  518. ;--- Common entry point ---
  519. ; cx = entry value:
  520. ;    cl = full vs quick exit path
  521. ;         0 = exit() code
  522. ;         1 = _exit() code
  523. ;    ch = term process vs return to caller
  524. ;         0 = term process
  525. ;         1 = return to caller
  526. ;
  527.  
  528. common1:            ; all code paths join here
  529.  
  530. assumes ds,data
  531.  
  532.  
  533.  
  534.  
  535.  
  536. ;
  537. ; If _exit()/_c_exit(), jump over the initial termination processing
  538. ; cx = entry code
  539. ;
  540.  
  541.     push    cx        ; save entry code on top of stack
  542.     or    cl,cl        ; cl != 0 means _exit()/_c_exit()
  543.     jnz    short common2    ; if _exit()/_c_exit(), jump down
  544.     ;fall thru        ; continue (exit, _cexit)
  545.  
  546.  
  547. ;    1.    call user terminators
  548. ;        - onexit processing
  549.  
  550.     mov    si,dataOFFSET xontab ; beginning of onexit table
  551.     mov    di,dataOFFSET xonend ; end of onexit table
  552.     call    initterm
  553.  
  554. ;    2.    call C runtime preterminators
  555. ;        - flushall
  556. ;        - rmtmp
  557.  
  558.     mov    si,dataOFFSET xpbegin ; beginning of pre-terminators
  559.     mov    di,dataOFFSET xpend ; end of pre-terminators
  560.     call    initterm
  561.     ;fall thru
  562.  
  563. ;
  564. ;--- Common entry point ---
  565. ;
  566.  
  567. common2:            ; __exit() enters here
  568.  
  569.  
  570. ;    3.    perform C terminators
  571.  
  572.     mov    si,dataOFFSET xcbegin
  573.     mov    di,dataOFFSET xcend
  574.     call    initterm
  575.  
  576.     mov    si,dataOFFSET xcfbegin
  577.     mov    di,dataOFFSET xcfend
  578. if    sizeC
  579.     call    initterm    ; call the far terminators
  580. else
  581.     call    farinitterm    ; call the far terminators
  582. endif
  583.  
  584. ;    4.    perform _nullcheck() for null pointer assignment
  585.  
  586.     call    _nullcheck    ; perform null check
  587.                 ; this must be far call in large code models
  588.                 ; since user can stub it out
  589.     or    ax,ax        ; zero if no null pointer asmt. detected
  590.     jz    short afternullchk
  591.  
  592.     pop    ax        ; get entry code
  593.     or    ah,ah        ; ah != 0 means _cexit()/_c_exit()
  594.     push    ax        ; put it back for later
  595.     jnz     short afternullchk ; jump if no status value (_cexit/_c_exit)
  596.  
  597.     cmp    status,0    ; zero if no other error has occurred
  598.     jnz    short afternullchk
  599.     mov    status,255    ; nonzero status to indicate an
  600.                 ; null-pointer-assignment error
  601. afternullchk:
  602.  
  603. ;    5.    terminate floating point
  604.  
  605.     call    _ctermsub    ; fast cleanup
  606.  
  607. ;    6.    return to the DOS or caller
  608.  
  609.     pop    ax        ; get entry code off top of stack
  610.     or    ah,ah        ; ah = 0 means term process
  611.     jnz     returning    ; skip down if not term'ing
  612.  
  613. ;    6a.    Return to DOS
  614.  
  615. exiting:
  616.     mov    ax,1        ; terminate all threads of this process
  617.     push    ax
  618.     mov    al,byte ptr [status] ; get return value (low 8 bits)
  619.     push    ax
  620.  
  621.  
  622.     call    DOSEXIT     ; exit with return code
  623.  
  624.  
  625.     ;*** PROCESS IS TERMINATED ***
  626.  
  627. ;    6b.    Return to caller.
  628.  
  629. returning:
  630.  
  631.  
  632.  
  633. cEnd    <nolocals>
  634.  
  635.  
  636.  
  637.  
  638. page
  639. ;***
  640. ;_ctermsub - Terminate Floating Point
  641. ;
  642. ;Purpose:
  643. ;    Terminate Floating Point
  644. ;
  645. ;Entry:
  646. ;
  647. ;Exit:
  648. ;
  649. ;Uses:
  650. ;
  651. ;Exceptions:
  652. ;
  653. ;*******************************************************************************
  654.  
  655. labelNP <PUBLIC,_ctermsub>
  656.  
  657.  
  658. ;    5.    terminate floating point
  659.  
  660.     mov    cx,word ptr [fpmath+2] ; test for floating point
  661.     jcxz    nofloat_t    ;   no
  662.  
  663.     mov    bx,2        ;   yes - cleanup
  664.     call    [fpmath]
  665.  
  666. nofloat_t:
  667.  
  668.     ret
  669.  
  670. page
  671. ;***
  672. ;initterm - do all the initializers and terminators
  673. ;
  674. ;Purpose:
  675. ;    The initializers and terminators may be written in C
  676. ;    so we are assuming C conventions (DS=SS, CLD, SI and DI preserved)
  677. ;    We go through them in reverse order for onexit.
  678. ;
  679. ;Entry:
  680. ;    SI    = start of procedure list
  681. ;    DI    = end of procedure list
  682. ;
  683. ;Exit:
  684. ;
  685. ;Uses:
  686. ;
  687. ;Exceptions:
  688. ;
  689. ;*******************************************************************************
  690.  
  691. initterm:
  692.     cmp    si,di        ; are we done?
  693.     jae    itdone        ;   yes - no more
  694.  
  695. if    sizeC
  696.     sub    di,4
  697.     mov    ax,[di]
  698.     or    ax,[di+2]
  699.     jz    initterm    ; skip null procedures
  700.     call    dword ptr [di]
  701. else
  702.     dec    di
  703.     dec    di
  704.     mov    cx,[di]
  705.     jcxz    initterm    ; skip null procedures
  706.     call    cx
  707. endif
  708.     jmp    initterm    ; keep looping
  709.  
  710. itdone:
  711.     ret
  712.  
  713. page
  714. ife    sizeC            ; S/C models only
  715. ;***
  716. ;farinitterm - do a set of far initializers or terminators
  717. ;
  718. ;Purpose:
  719. ;    The initializors and terminators may be written in C
  720. ;    so we are assuming C conventions (DS=SS, CLD, SI and DI preserved)
  721. ;    We go through them in reverse order for onexit.
  722. ;
  723. ;Entry:
  724. ;    SI    = start of procedure list
  725. ;    DI    = end of procedure list
  726. ;
  727. ;Exit:
  728. ;
  729. ;Uses:
  730. ;
  731. ;Exceptions:
  732. ;
  733. ;*******************************************************************************
  734.  
  735. farinitterm:
  736.     cmp    si,di        ; are we done?
  737.     jae    faritdone    ;   yes - no more
  738.  
  739.     sub    di,4
  740.     mov    ax,[di]
  741.     or    ax,[di+2]
  742.     jz    farinitterm    ; skip null procedures
  743.     call    dword ptr [di]
  744.     jmp    farinitterm    ; keep looping
  745.  
  746. faritdone:
  747.     ret
  748. endif    ;sizeC
  749.  
  750. sEnd
  751.  
  752.     EMULATOR_DATA  segment para public 'FAR_DATA'
  753.     EMULATOR_DATA  ends
  754.  
  755.     EMULATOR_TEXT  segment para public 'CODE'
  756.  
  757.     public __EmDataSeg
  758.     __EmDataSeg dw  EMULATOR_DATA
  759.  
  760.     EMULATOR_TEXT  ends
  761.  
  762.  
  763.  
  764.     end
  765.