home *** CD-ROM | disk | FTP | other *** search
/ Programming Languages Suite / ProgLangD.iso / Fortran.51 / DISK5 / DOS / CRT0.AS$ / CRT0.bin
Text File  |  1990-02-22  |  14KB  |  592 lines

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