home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / magazine / drdobbs / 1991 / 10 / embedcp / code / c0.asm < prev    next >
Assembly Source File  |  1991-05-27  |  19KB  |  561 lines

  1.         NAME    c0
  2.         PAGE    60,132
  3.         LOCALS
  4. ;[]-------------------------------------------------------------------[]
  5. ;|      C0.ASM -- Start Up Code for MIO                                |
  6. ;|                                                                     |
  7. ;|      Turbo C++ Run Time Library                                     |
  8. ;|                                                                     |
  9. ;|      Portions Copyright (c) 1991, Stuart G. Phillips.               |
  10. ;|      All rights reserved.                                           |
  11. ;|                                                                     |
  12. ;|      Copyright (c) 1987, 1991 by Borland International Inc.         |
  13. ;|      All rights reserved.                                           |
  14. ;|                                                                     |
  15. ;|      This software is subject to the terms and conditions of the    |
  16. ;|      license agreement distributed with Borland C++.                |
  17. ;[]-------------------------------------------------------------------[]
  18.  
  19.                 __C0__ = 1
  20. INCLUDE         RULES.ASI
  21.  
  22. ;       Segment and Group declarations
  23.  
  24. _BOOT           SEGMENT BYTE PUBLIC 'CODE' AT 0FFFFh
  25.                 ORG     0
  26. boot_vector     LABEL   BYTE
  27.                 ENDS 
  28.  
  29. _TEXT           SEGMENT BYTE PUBLIC 'CODE'
  30.                 ENDS
  31. _FARDATA        SEGMENT PARA PUBLIC 'FAR_DATA'
  32.                 ENDS
  33. _FARBSS         SEGMENT PARA PUBLIC 'FAR_BSS'
  34.                 ENDS
  35. IFNDEF __TINY__
  36. _OVERLAY_       SEGMENT PARA PUBLIC 'OVRINFO'
  37.                 ENDS
  38. _1STUB_         SEGMENT PARA PUBLIC 'STUBSEG'
  39.                 ENDS
  40. ENDIF
  41. _DATA           SEGMENT PARA PUBLIC 'DATA'
  42.                 ENDS
  43. _INIT_          SEGMENT WORD PUBLIC 'INITDATA'
  44. InitStart       label byte
  45.                 ENDS
  46. _INITEND_       SEGMENT BYTE PUBLIC 'INITDATA'
  47. InitEnd         label byte
  48.                 ENDS
  49. _EXIT_          SEGMENT WORD PUBLIC 'EXITDATA'
  50. ExitStart       label byte
  51.                 ENDS
  52. _EXITEND_       SEGMENT BYTE PUBLIC 'EXITDATA'
  53. ExitEnd         label byte
  54.                 ENDS
  55. _CVTSEG         SEGMENT WORD PUBLIC 'DATA'
  56.                 ENDS
  57. _SCNSEG         SEGMENT WORD PUBLIC 'DATA'
  58.                 ENDS
  59. IFNDEF __HUGE__
  60.   _BSS          SEGMENT WORD PUBLIC 'BSS'
  61.                 ENDS
  62.   _BSSEND       SEGMENT BYTE PUBLIC 'BSSEND'
  63.                 ENDS
  64. ENDIF
  65. IFNDEF __TINY__
  66.   _STACK        SEGMENT STACK 'STACK'
  67.                 ENDS
  68. ENDIF
  69.  
  70.         ASSUME  CS:_TEXT, DS:DGROUP
  71.  
  72. ;       External References
  73.  
  74. extrn           _main:DIST
  75. extrn           __stklen:word
  76. IF LDATA EQ false
  77. extrn           __heaplen:word
  78. ENDIF
  79.  
  80.         SUBTTL  Start Up Code
  81.         PAGE
  82. ;/*                                                     */
  83. ;/*-----------------------------------------------------*/
  84. ;/*                                                     */
  85. ;/*     Start Up Code                                   */
  86. ;/*     -------------                                   */
  87. ;/*                                                     */
  88. ;/*-----------------------------------------------------*/
  89. ;/*                                                     */
  90.  
  91. ; public  __AHINCR
  92. ; __AHINCR        equ     1000h
  93. ;                 public  __AHSHIFT
  94. ; __AHSHIFT       equ     12
  95.  
  96. IFDEF   __NOFLOAT__
  97. MINSTACK        equ     128     ; minimal stack size in words
  98. ELSE
  99. MINSTACK        equ     256     ; minimal stack size in words
  100. ENDIF
  101. ;
  102. ;       At the start, DS and ES both point to the segment prefix.
  103. ;       SS points to the stack segment except in TINY model where
  104. ;       SS is equal to CS
  105. ;
  106. _TEXT           SEGMENT
  107. IFDEF           __TINY__
  108. ENDIF
  109. STARTX          PROC    NEAR
  110.                 jmp     START
  111.                 
  112.                 ORG     2000h
  113.  
  114. START:
  115. ;       Save general information, such as :
  116. ;               DGROUP segment address
  117. ;               Top of far heap
  118.  
  119. IFDEF   __TINY__
  120.                 mov     dx, cs          ; DX = GROUP Segment address
  121. ELSE
  122.                 mov     dx, DGROUP      ; DX = GROUP Segment address
  123. ENDIF
  124.                 mov     cs:DGROUP@@, dx
  125.                 mov     ds,dx           ; Set DGROUP as data segment
  126.                 mov     bp,0c000h       ; BP = segment at top of memory
  127.  
  128. ; Calculate the first free segment value by finding the top of data
  129. ; in the DGROUP data group - add in the offset of the end and convert
  130. ; to paragraphs.
  131.  
  132.                 mov     ax,dx
  133.                 mov     dx,offset DGROUP:edata@
  134.                 add     dx,15
  135.                 mov     cl,4
  136.                 shr     dx,cl
  137.                 add     ax,dx
  138.                 mov     word ptr _heaptop@ + 2, ax
  139.  
  140. ; Set temporary stack at top of used memory - it gets changed later
  141.  
  142.                 cli
  143.                 mov     ss,ax
  144.                 mov     sp,100h
  145.                 sti
  146.  
  147.                 push    ax
  148. ;
  149. ;       Save several vectors and install default divide by zero handler.
  150. ;
  151.                 call    SaveVectors
  152.  
  153. ;       Determine the amount of memory that we need to keep
  154.  
  155.                 pop     ax
  156.  
  157. IFDEF _DSSTACK_
  158.                 mov     dx, ds
  159. ELSE
  160.                 mov     dx, ax
  161. ENDIF
  162.                 sub     bp, dx          ; BP = remaining size in paragraphs
  163. IF LDATA
  164.                 mov     di, seg __stklen
  165.                 mov     es, di
  166.                 mov     di, es:__stklen ; DI = Requested stack size
  167. ELSE
  168.                 mov     di, __stklen    ; DI = Requested stack size
  169. ENDIF
  170. ;
  171. ; Make sure that the requested stack size is at least MINSTACK words.
  172. ;
  173.                 cmp     di, 2*MINSTACK  ; requested stack big enough ?
  174.                 jae     AskedStackOK
  175.                 mov     di, 2*MINSTACK  ; no --> use minimal value
  176. IF LDATA
  177.                 mov     es:__stklen, di ; override requested stack size
  178. ELSE
  179.                 mov        __stklen, di ; override requested stack size
  180. ENDIF
  181.  
  182. AskedStackOK    label   near
  183. IFDEF _DSSTACK_
  184.                 add     di, offset DGROUP: edata@
  185.                 jb      InitFailed      ; DATA segment can NOT be > 64 Kbytes
  186. ENDIF
  187. IF LDATA EQ false
  188.                 add     di, __heaplen
  189.                 jb      InitFailed      ; DATA segment can NOT be > 64 Kbytes
  190. ENDIF
  191.                 mov     cl, 4
  192.                 shr     di, cl          ; $$$ Do not destroy CL $$$
  193.                 inc     di              ; DI = DS size in paragraphs
  194.                 cmp     bp, di
  195. IF LDATA EQ false
  196.                 jb      InitFailed      ; Not enough memory
  197.                 cmp     __stklen, 0
  198.                 je      ExpandDS        ; Expand DS up to 64 Kb
  199.                 cmp     __heaplen, 0
  200.                 jne     ExcessOfMemory  ; Much more available than needed
  201. ExpandDS        label   near
  202.                 mov     di, 1000h
  203.                 cmp     bp, di
  204.                 ja      ExcessOfMemory  ; Enough to run the program
  205.                 mov     di, bp
  206.                 jmp     short ExcessOfMemory  ; Enough to run the program
  207. ELSE
  208.                 jnb     ExcessOfMemory  ; Much more available than needed
  209. ENDIF
  210.  
  211. ;       All initialization errors arrive here
  212.  
  213. InitFailed      label   near
  214.                 jmp     near ptr _abort
  215.  
  216. ;       Set far heap base and pointer
  217.  
  218. ExcessOfMemory  label   near
  219.                 mov     bx, di
  220.                 add     bx, dx
  221.                 mov     word ptr _heapbase@ + 2, bx
  222.                 mov     word ptr _brklvl@ + 2, bx
  223.  
  224.                 shl     di, cl          ; $$$ CX is still equal to 4 $$$
  225.  
  226.                 cli                     ; req'd for pre-1983 88/86s
  227.                 mov     ss, dx          ; Set the program stack
  228.                 mov     sp, di
  229.                 sti
  230.  
  231.                 mov     word ptr _first_stack@, di
  232.                 mov     word ptr _first_stack@ + 2, dx
  233.  
  234. IFNDEF _DSSTACK_
  235. ; Set the stack to a known pattern
  236.  
  237.                 mov     bx,di
  238.                 mov     es,dx           ; ES is stack segment
  239.                 mov     cx,di
  240.                 shr     cx,1            ; Convert to words
  241.                 mov     di,0
  242.                 mov     ax,'ST'
  243.                 cld
  244.                 rep     stosw
  245.                 mov     di,bx
  246. ENDIF
  247.  
  248. IFNDEF _DSSTACK_
  249.                 mov     ax, seg __stklen
  250.                 mov     es, ax
  251.                 mov     es:__stklen, di ; If separate stack segment, save size
  252. ENDIF
  253.  
  254. IFNDEF  __HUGE__
  255.  
  256. ;       Reset uninitialized data area
  257.  
  258.                 xor     ax, ax
  259.                 mov     es, cs:DGROUP@@
  260.                 mov     di, offset DGROUP: bdata@
  261.                 mov     cx, offset DGROUP: edata@
  262.                 sub     cx, di
  263.                 cld
  264.                 rep     stosb
  265. ENDIF
  266.  
  267. ;       Prepare main arguments
  268.  
  269.                 xor     bp,bp                   ; set BP to 0 for overlay mgr
  270.  
  271. IFNDEF __TINY__
  272.                 mov     ax,DGROUP
  273.                 mov     ds,ax
  274.                 mov     si,offset DGROUP:InitStart      ;si = start of table
  275.                 mov     di,offset DGROUP:InitEnd        ;di = end of table
  276. ELSE
  277.                 mov     si,offset DGROUP:InitStart      ;si = start of table
  278.                 mov     di,offset DGROUP:InitEnd        ;di = end of table
  279. ENDIF
  280.                 call    StartExit
  281.                 mov     ds, cs:DGROUP@@
  282.  
  283. ; OK, to save space we use self-modifying code.
  284. ; Replace the JA instruction in the startup/exit logic with
  285. ; a JB instruction.  This allows us to scan the table on exit 
  286. ; executing functions in reverse priority.  Also change the 
  287. ; immediate which is stored in ah at the first instruction to a 0.
  288.  
  289.                 mov     byte ptr cs:JA_JB,72h
  290.                 mov     byte ptr cs:StartExit+1,0
  291.  
  292. ;       MIO main program is called with no parameters - set argc to
  293. ;       a zero count and argv to a null pointer
  294.  
  295. ;       ExitCode = main(argc,argv);
  296.  
  297.                 xor     ax,ax
  298.  
  299. IF      LDATA
  300.                 push    ax
  301.                 push    ax                      ; Null argv pointer
  302. ELSE
  303.                 push    ax                      ; Null argv pointer
  304. ENDIF
  305.                 push    ax                      ; arc = 0
  306.                 call    _main
  307.  
  308. ;       Clean up - MIO has no files or streams but clean up the
  309. ;       interrupt vectors and then jump back to the EPROM boot code
  310. ;       ready for the next download
  311.  
  312.                 push    ax
  313.                 jmp     far ptr boot_vector
  314.  
  315. ;---------------------------------------------------------------------------
  316. ;       _exit()
  317. ;
  318. ;       Restore interrupt vectors taken during startup.
  319. ;
  320. ;       Jump back to EPROM boot code
  321. ;
  322. ;---------------------------------------------------------------------------
  323. __exitclean     PROC    NEAR
  324.                 PUBLIC  __exitclean
  325. IFNDEF __TINY__
  326.                 mov     ax,DGROUP
  327.                 mov     ds,ax
  328.                 mov     si,offset DGROUP:ExitStart
  329.                 mov     di,offset DGROUP:ExitEnd
  330. ELSE
  331.                 mov     si,offset DGROUP:ExitStart
  332.                 mov     di,offset DGROUP:ExitEnd
  333. ENDIF
  334.                 call    StartExit
  335.  
  336.                 mov     ds, cs:DGROUP@@
  337.                 
  338.                 ENDP
  339.  
  340. __exit          PROC    DIST
  341.                 PUBLIC  __exit
  342.                 mov     ds, cs:DGROUP@@
  343.  
  344.                 call    DIST ptr __restorezero  ; restore captured INT vectors
  345.  
  346.                 jmp     far ptr boot_vector        
  347.                 ENDP 
  348.  
  349. STARTX          ENDP
  350.  
  351.         SUBTTL  Vector save/restore & default Zero divide routines
  352.         PAGE
  353. ;[]------------------------------------------------------------[]
  354. ;|                                                              |
  355. ;| Interrupt Save/Restore routines and default divide by zero   |
  356. ;| handler.                                                     |
  357. ;|                                                              |
  358. ;[]------------------------------------------------------------[]
  359.  
  360. ZeroDivision    PROC    FAR
  361.                 ret
  362. ZeroDivision    ENDP
  363.  
  364. ;
  365. ;       Install default divide by zero handler.
  366. ;
  367.  
  368. SaveVectors     PROC    FAR
  369.                 mov     ax, 0
  370.                 push    es                      ; Save current es
  371.                 push    di                      ; ... and di
  372.                 mov     es,ax
  373.                 mov     di,0
  374.                 mov     es:[di], cs
  375.                 mov     dx, offset ZeroDivision
  376.                 mov     es:[di+2],dx
  377.                 pop     di
  378.                 pop     es
  379.                 ret
  380. SaveVectors     ENDP
  381.  
  382. ;--------------------------------------------------------------------------
  383. ;       restorezero() resets the divide by zero interrupt to point to the
  384. ;                     boot prom entry point
  385. ;
  386. ;--------------------------------------------------------------------------
  387. __restorezero   PROC    DIST
  388.                 PUBLIC  __restorezero
  389.  
  390.                 push    es                      ; Save es
  391.                 push    di                      ; ...and di
  392.                 xor     ax,ax
  393.                 mov     es,ax
  394.                 mov     di,0
  395.                 mov     word ptr es:[si],0
  396.                 mov     word ptr es:[si+2],0ffffh
  397.                 pop     di
  398.                 pop     es
  399.                 ret
  400.                 ENDP
  401.  
  402. ;------------------------------------------------------------------
  403. ;  Loop through a startup/exit (SE) table, 
  404. ;  calling functions in order of priority.
  405. ;  DS:SI is assumed to point to the beginning of the SE table
  406. ;  DS:DI is assumed to point to the end of the SE table
  407. ;  First 64 priorities are reserved by Borland
  408. ;------------------------------------------------------------------
  409. PNEAR           EQU     0
  410. PFAR            EQU     1
  411. NOTUSED         EQU     0ffh
  412.  
  413. SE              STRUC
  414. calltype        db      ?                       ; 0=near,1=far,ff=not used
  415. priority        db      ?                       ; 0=highest,ff=lowest
  416. addrlow         dw      ?
  417. addrhigh        dw      ?
  418. SE              ENDS
  419.  
  420. StartExit       PROC    NEAR
  421. @@Start:        mov     ah,0ffh                 ; start with lowest priority
  422.                 mov     dx,di                   ; set sentinel to end of table
  423.                 mov     bx,si                   ; bx = start of table
  424.  
  425. @@TopOfTable:   cmp     bx,di                   ; and the end of the table?
  426.                 je      @@EndOfTable            ; yes, exit the loop
  427.                 cmp     [bx.calltype],NOTUSED   ; check the call type
  428.                 je      @@Next
  429.                 cmp     [bx.priority],ah        ; check the priority
  430. JA_JB:          ja      @@Next                  ; too high?  skip
  431.                 mov     ah,[bx.priority]        ; keep priority
  432.                 mov     dx,bx                   ; keep index in dx
  433. @@Next:         add     bx,SIZE SE              ; bx = next item in table
  434.                 jmp     @@TopOfTable
  435.  
  436. @@EndOfTable:   cmp     dx,di                   ; did we exhaust the table?
  437.                 je      @@Done                  ; yes, quit
  438.                 mov     bx,dx                   ; bx = highest priority item
  439.                 push    ds                      ; save ds
  440.                 pop     es
  441.                 push    es                      ; es = ds
  442.                 cmp     [bx.calltype],PNEAR     ; is it near or far?
  443.                 mov     [bx.calltype],NOTUSED   ; wipe the call type
  444.                 mov     ds, cs:DGROUP@@
  445.                 je      @@NearCall
  446.  
  447. @@FarCall:      call    DWORD PTR es:[bx.addrlow]
  448.                 pop     ds                      ; restore ds
  449.                 jmp     @@Start
  450.  
  451. @@NearCall:     call    WORD PTR es:[bx.addrlow]
  452.                 pop     ds                      ; restore ds
  453.                 jmp     @@Start
  454.  
  455. @@Done:         ret
  456. StartExit       ENDP
  457.  
  458.  
  459. _abort          PROC    DIST
  460.                 PUBLIC  _abort
  461.                 mov     ax, 3
  462.                 push    ax
  463.                 call    __exit           ; _exit(3);
  464.                 ENDP
  465.  
  466. ; The DGROUP@ variable is used to reload DS with DGROUP
  467.  
  468. PubSym@         DGROUP@, <dw    ?>, __PASCAL__
  469.  
  470. ; __MMODEL is used to determine the memory model or the default
  471. ; pointer types at run time.
  472.  
  473.                 public __MMODEL
  474. __MMODEL        dw      MMODEL
  475.  
  476. _TEXT           ENDS
  477.  
  478.                 SUBTTL  Start Up Data Area
  479.                 PAGE
  480. ;[]------------------------------------------------------------[]
  481. ;|      Start Up Data Area                                      |
  482. ;|                                                              |
  483. ;|      WARNING         Do not move any variables in the data   |
  484. ;|                      segment unless you're absolutely sure   |
  485. ;|                      that it does not matter.                |
  486. ;[]------------------------------------------------------------[]
  487.  
  488. _DATA           SEGMENT
  489.  
  490. ;       Magic symbol used by the debug info to locate the data segment
  491.                 public DATASEG@
  492. DATASEG@        label   byte
  493.  
  494.  
  495. CopyRight       db      4 dup(0)
  496.                 db      'Borland C++ - Copyright 1991 Borland Intl.',0
  497. ;
  498. ;                       Miscellaneous variables
  499. ;       
  500. PubSym@         _C0argc,        <dw     0>,             __CDECL__
  501. dPtrPub@        _C0argv,        0,                      __CDECL__
  502. dPtrPub@        _C0environ,     0,                      __CDECL__
  503. PubSym@         _envLng,        <dw     0>,             __CDECL__
  504. PubSym@         _envseg,        <dw     0>,             __CDECL__
  505. PubSym@         _envSize,       <dw     0>,             __CDECL__
  506. PubSym@         _psp,           <dw     0>,             __CDECL__
  507. PubSym@         _version,       <label word>,           __CDECL__
  508. PubSym@         _osmajor,       <db     0>,             __CDECL__
  509. PubSym@         _osminor,       <db     0>,             __CDECL__
  510. PubSym@         errno,          <dw     0>,             __CDECL__
  511. PubSym@         _StartTime,     <dw   0,0>,             __CDECL__
  512.  
  513.  
  514. ;       Memory management variables
  515.  
  516. IF      LDATA EQ false
  517. PubSym@         __heapbase,     <dw   DGROUP:edata@>,   __CDECL__
  518. PubSym@         __brklvl,       <dw   DGROUP:edata@>,   __CDECL__
  519. ENDIF
  520. PubSym@         _heapbase,      <dd   0>,       __CDECL__
  521. PubSym@         _brklvl,        <dd   0>,       __CDECL__
  522. PubSym@         _heaptop,       <dd   0>,       __CDECL__
  523. PubSym@         _first_stack    <dd   0>,       __CDECL__
  524. ;       If stack in DS and Large data model then override location of __emu
  525.  
  526. ; IFDEF   _DSSTACK_
  527. ; IF      LDATA
  528. ; public        __emu
  529. ; __emu db      044h    DUP (0)
  530. ;       db      0CCh    DUP (?)
  531. ; ENDIF
  532. ; ENDIF
  533.  
  534. _DATA           ENDS
  535.  
  536.  
  537. _CVTSEG         SEGMENT
  538. ; PubSym@         _RealCvtVector, <label  word>,  __CDECL__
  539.                 ENDS
  540.  
  541. _SCNSEG         SEGMENT
  542. ; PubSym@         _ScanTodVector,  <label word>,  __CDECL__
  543.                 ENDS
  544.  
  545. IFNDEF __HUGE__
  546. _BSS            SEGMENT
  547. bdata@          label   byte
  548.                 ENDS
  549.  
  550. _BSSEND         SEGMENT
  551. edata@          label   byte
  552.                 ENDS
  553. ENDIF
  554.  
  555. IFNDEF __TINY__
  556. _STACK          SEGMENT
  557.                 db      128 dup(?)               ;minimum stack size
  558.                 ENDS
  559. ENDIF
  560.                 END     STARTX
  561.