home *** CD-ROM | disk | FTP | other *** search
/ Atari FTP / ATARI_FTP_0693.zip / ATARI_FTP_0693 / Tex / Shells / ms.arc / GEMSTART.S < prev    next >
Text File  |  1988-10-17  |  25KB  |  737 lines

  1. ******************************************************************************
  2. *
  3. * gemstart.s -startup code for the C runtime library, aesbind, vdibind
  4. *    
  5. *    IMPORTANT: SEE THE DESCRIPTION OF THE "STACK" VARIABLE, BELOW.
  6. *
  7. *    This is the startup code for any application running on the Atari ST.
  8. *    This includes gemlib, vdi, and the aes bindings.
  9. *
  10. *    Look carefully at the comments below; they will determine the nature
  11. *    of this startup code (stack size, AES & VDI usage, etc.).
  12. *
  13. *    This must be the first object file in a LINK command. When the
  14. *    operating system gives it control, our process has ALL of memory
  15. *    allocated to it, and our stack pointer is at the top.
  16. *    This code (conditionally) gives some of that memory back
  17. *    to the operating system, places its stack pointer at the top
  18. *    of the memory it still owns, sets up some global variables,
  19. *    and calls __main, the run-time library startup routine (which
  20. *    parses the command line into argc/argv, opens stdin and stdout,
  21. *    etc., before calling the programmer's _main).
  22. *
  23. *    This object file also includes __exit, which is the procedure the
  24. *    runtime library calls to exit back to the operating system.
  25. *    As a new feature with this release, the argument passed to __exit
  26. *    is NOT ignored; it is passed to the operating system using the Pterm
  27. *    function call, which returns it as the value of the Pexec() call
  28. *    which invoked this process.
  29. *
  30. ******************************************************************************
  31. *
  32. *    CONFIGUING THIS STARTUP FILE
  33. *
  34. *    There are several memory models which this startup file will
  35. *    assemble for, selected by the assembly variable STACK.
  36. *
  37. *    When your process gets control, it owns its basepage, its text
  38. *    (program) segment, its data segment, its bss segment (uninitialized
  39. *    data), and all the "free memory" from there to the top of the TPA.
  40. *    A process can choose to keep all that free memory for its stack
  41. *    (used by function calls and local variables) and heap (used by
  42. *    malloc()), or it can return some or all of that space to the
  43. *    operating system.
  44. *
  45. *    The memory between the top of your bss segment and your stack pointer
  46. *    is used both for a heap and for the stack.  The line between heap
  47. *    and stack is called the "break".  When malloc() uses up all the
  48. *    memory below the break, it calls _brk() (in this file) to move the 
  49. *    break up.  If the break gets too close to the stack, _brk() returns 
  50. *    an error code, and malloc() will return NULL because it couldn't
  51. *    satisfy the request.  If the stack actually overflows the break,
  52. *    _brk() prints an error message and exits, returning 1 to its parent.
  53. *
  54. *    If you are using the AES or VDI, you must return at least a little of
  55. *    the free memory to the operating system, because they need it.
  56. *    About 8K should be enough. The AES uses this memory for blt buffers,
  57. *    and the VDI uses it for virtual workstation data.
  58. *    Also, if your program uses the Pexec() call, you will need to return
  59. *    some space to make room for the child process.
  60. *
  61. *    It is usually a good idea to keep only as much memory as you will
  62. *    use, because some programs depend on processes returning some 
  63. *    memory to the operating system.
  64. *
  65. *************************************************************************
  66. *
  67. *    Here are the memory models you can set up with the STACK variable:
  68. *
  69. *    STACK
  70. *    value    Meaning
  71. *    ------    ---------------------------------------------------------
  72. *    -1    Keep all the memory for this process. Return NONE of it
  73. *        to the operating system.  This model gives you the most
  74. *        memory.
  75. *
  76. *        WARNING: IF YOU REQUEST ALL OF MEMORY (with STACK = -1),
  77. *        YOU MUST NOT USE THE AES, THE VDI, OR THE BIOS PEXEC() 
  78. *        FUNCTION. PEXEC WILL RETURN A CORRECT ERROR CODE (-39, 
  79. *        ENSMEM), BUT IT WILL ALSO BREAK THE MEMORY MANAGEMENT SYSTEM.
  80. *
  81. *     0    Return all but a minimal amount (MINSTACK) of the free
  82. *        space to the operating system.  This is a good idea if
  83. *        you know you won't be using malloc() much, or if you
  84. *        will be using Pexec() and your program doesn't need much
  85. *        stack space.  Remember, though, that some library functions,
  86. *        especially fopen(), use malloc() and will use your heap
  87. *        space.
  88. *
  89. *     1    Keep 1/4 of the free space.  This is a good model if
  90. *        you will be using malloc() a lot, but also want to use 
  91. *        Pexec() to spawn subprocesses.
  92. *
  93. *     2    Keep 2/4 (1/2) of the free space.  This is good if you
  94. *        use malloc() a lot, but don't want to be too much of a 
  95. *        memory hog.
  96. *
  97. *     3    Keep 3/4 of the free space.  This is a good choice for
  98. *        programs which use the AES or VDI, because it gives you plenty
  99. *        of room for using malloc(), but leaves enough for the
  100. *        AES and VDI to allocate their buffers, too.
  101. *
  102. *     4    This is a special value which means "Keep the number of
  103. *        bytes in the LONG global variable __STKSIZ."  You must declare
  104. *        a variable in your program called "_STKSIZ" and initialize
  105. *        it to the number of bytes you want for your stack and heap.
  106. *        If __STKSIZ is negative, it means "Keep all BUT the number
  107. *        of bytes in __STKSIZ."  As a safeguard, if __STKSIZ is
  108. *        undefined, you will get MINSTACK bytes of stack/heap.
  109. *
  110. *        An example using __STKSIZ this in C is:
  111. *
  112. *            /* outside all function blocks */
  113. *            unsigned long _STKSIZ = 32767;    /* 32K stack+heap */
  114. *        or
  115. *            unsigned long _STKSIZ = -8192;    /* keep all but 8K */
  116. *
  117. *        Note that in C, all variables get an underscore stuck on
  118. *        the front, so you just use one underscore in your program.
  119. *        Note also that it has to be all upper-case.
  120. *
  121. *    Any other POSITIVE value of STACK will be taken as the number of
  122. *    bytes you want to KEEP for your stack and heap.
  123. *
  124. *    Any other NEGATIVE value of STACK will be taken as the number of
  125. *    bytes you want to give back to the operating system.
  126. *
  127. *    Note that if you give back less than 512 bytes, you still shouldn't
  128. *    use Pexec(), and if you give back less than (about) 4K, you shouldn't
  129. *    use the AES or VDI.
  130. *
  131. *    In all cases, a minimum stack size is enforced.  This minimum is
  132. *    set by the variable MINSTACK in this assembly file.  This value
  133. *    should be at least 256 bytes, but should be more like 4K. If
  134. *    the stack size from the STACK model you choose or the _STKSIZ
  135. *    variable in your program is less than MINSTACK, you'll get
  136. *    MINSTACK bytes.  If there aren't MINSTACK bytes free past the end
  137. *    of your BSS, the program will abort with an error message.
  138. *
  139. *************************************************************************
  140. *
  141. * STACK variable summary:
  142. *    -1=keep all
  143. *     0=keep MINSTACK bytes
  144. *     1=keep 1/4 of free memory
  145. *     2=keep 2/4
  146. *     3=keep 3/4
  147. *     4=use _STKSIZ: keep (if >0) or give up (if <0) _STKSIZ bytes.
  148. *    other=keep that many bytes (positive) or give back that many (negative)
  149.  
  150. STACK=4            * CHANGE THIS VARIABLE TO CHOOSE A MEMORY MODEL
  151. MINSTACK=4096        * minimum stack+heap size.
  152. FUDGE=512        * minimum space to leave ABOVE our stack
  153.  
  154. * BASEPAGE ADDRESSES:
  155. p_lowtpa=$0        * Low TPA address (basepage address)
  156. p_hitpa=$4        * High TPA address (and initial stack pointer)
  157. p_tbase=$8        * ptr to Code segment start
  158. p_tlen=$c        * Code segment length
  159. p_dbase=$10        * ptr to Data segment start
  160. p_dlen=$14        * Data segment length
  161. p_bbase=$18        * ptr to Bss  segment start
  162. p_blen=$1c        * Bss  segment length
  163. p_dta=$20        * ptr to process's initial DTA
  164. p_parent=$24        * ptr to process's parent's basepage
  165. p_reserved=$28        * reserved pointer
  166. p_env=$2c        * ptr to environment string for process
  167. p_cmdlin=$80        * Command line image
  168.  
  169. *
  170. * CONTROL VARIABLES (used in stack computations)
  171. *
  172. * GOTSTACK: a boolean which is set TRUE if STACK in [-1..4], meaning "don't
  173. *        assemble the code keeping or returning STACK bytes."
  174. *
  175. * DOSHRINK: a boolean which is set FALSE if STACK is -1, meaning "don't
  176. *        shrink any memory back to the operating system."
  177. *
  178. gotstack    .equ    0    * set to 1 if STACK in [-1..4]
  179. doshrink    .equ    1    * default is 1; set to 0 if STACK = -1
  180.  
  181. * GEMDOS functions:
  182. cconws=$09        * Cconws(string): write to console
  183. mshrink=$4a        * Mshrink(newsize): shrink a block to a new size
  184. pterm=$4c        * Pterm(code): exit, return code to parent
  185.  
  186. .globl    __start
  187. .globl    __main
  188. .globl    __exit
  189. .globl    _brk
  190. .globl    __break
  191. .globl    ___cpmrv
  192. .globl    __base
  193. .globl    __sovf
  194. .globl    _crystal
  195. .globl    _ctrl_cnts
  196.  
  197.  
  198.     .text
  199. *
  200. *  Must be first object file in link statement
  201. *
  202.  
  203. __start:
  204.     move.l    sp,a1        * save our initial sp (used by ABORT)
  205.     move.l    4(sp),a0    * a0 = basepage address
  206.     move.l    a0,__base    * base = a0
  207.     move.l    p_bbase(a0),d0    * d0 = bss seg start
  208.     add.l    p_blen(a0),d0    * d0 += bss length  (d0 now = start of heap)
  209.     move.l    d0,__break    * __break = first byte of heap
  210.  
  211. *************************************************************************
  212. *                                    *
  213. *    Compute stack size based on MINSTACK, p_hitpa(a0), STACK,    *
  214. *    and __STKSIZ, as appropriate.  Place the SP where you want    *
  215. *    your stack to be. Note that a0 == __base, d0 == __break        *
  216. *                                    *
  217. *    At most one of the STACK code fragments will be assembled.    *
  218. *    If none of them are, then `gotstack' will still be 0, and    *
  219. *    the final block, saving STACK bytes, is used. Finally, if    *
  220. *    STACK wasn't -1 (meaning don't shrink at all), DOSHRINK        *
  221. *    gets control.  See doshrink for more.                *
  222. *                                    *
  223. *************************************************************************
  224.  
  225. *************************************************************************
  226. *        STACK = -1: keep all of memory                *
  227. *************************************************************************
  228.  
  229.     .ifeq    STACK+1        * if (STACK == -1)
  230. gotstack    .equ    1
  231. doshrink    .equ    0    * this PREVENTS doshrink from assembling.
  232.     move.l    p_hitpa(a0),sp    * place stack at top of tpa.
  233.     move.l    d0,d1        * check against MINSTACK
  234.     add.l    #MINSTACK,d1    * d1 = __break + MINSTACK;
  235.     cmp.l    sp,d1        * if (sp < __break + MINSTACK)
  236.     bhi    abort        *    goto abort;
  237.     .endc            * (this falls through to the __main call)
  238.  
  239. *************************************************************************
  240. *        STACK = 0: keep only MINSTACK bytes            *
  241. *************************************************************************
  242.  
  243.     .ifeq    STACK
  244. gotstack    .equ    1
  245.     move.l    #MINSTACK,sp    *    sp = __break+MINSTACK;
  246.     add.l    d0,sp
  247.     .endc            * (this falls through to doshrink)
  248.  
  249. *************************************************************************
  250. *        STACK = 1: keep 1/4 of available memory            *
  251. *************************************************************************
  252.  
  253.     .ifeq    STACK-1
  254. gotstack    .equ    1    *    /* keep 1/4 of available RAM */
  255.     move.l    p_hitpa(a0),d1    *    d1 = p_hitpa;
  256.     sub.l    d0,d1        *    d1 -= __break; /* d1 = free ram size */
  257.     lsr.l    #2,d1        *    d1 /= 4;
  258.     add.l    d0,d1        *    d1 += __break;     /* d1 = new sp */
  259.     move.l    d1,sp        *     sp = d1;
  260.     .endc            * } (this falls through to doshrink)
  261.  
  262. *************************************************************************
  263. *        STACK = 2: keep 2/4 of available memory            *
  264. *************************************************************************
  265.  
  266.     .ifeq    STACK-2        * if (STACK == 2) {    /* keep 1/2 */
  267. gotstack    .equ    1
  268.     move.l    p_hitpa(a0),d1    *    d1 = p_hitpa;
  269.     sub.l    d0,d1        *    d1 -= __break; /* d1 = free ram size */
  270.     lsr.l    #1,d1        *    d1 /= 2;
  271.     add.l    d0,d1        *    d1 += __break; /* d1 = new sp */
  272.     move.l    d1,sp        *     sp = d1;
  273.     .endc            * this falls through to doshrink
  274.  
  275. *************************************************************************
  276. *        STACK = 3: keep 3/4 of available memory            *
  277. *************************************************************************
  278.  
  279.     .ifeq    STACK-3        * if (STACK == 3) {    /* keep 3/4 */
  280. gotstack    .equ    1
  281.     move.l    p_hitpa(a0),d1    *    d1 = p_hitpa;
  282.     sub.l    d0,d1        *    d1 -= __break; /* d1 = free ram size */
  283.     lsr.l    #2,d1        *    d1 /= 4;
  284.     move.l    d1,d2        *    d2 = d1
  285.     add.l    d2,d1        *    d1 += d2;
  286.     add.l    d2,d1        *    d1 += d2; /* now d1 = 3*(d1/4) */
  287.     add.l    d0,d1        *    d1 += __break;     /* d1 = new sp */
  288.     move.l    d1,sp        *     sp = d1;
  289.     .endc            * this falls through to doshrink
  290.  
  291. *************************************************************************
  292. *        STACK = 4: keep or give up __STKSIZ bytes of memory.    *
  293. *************************************************************************
  294.  
  295.     .ifeq    STACK-4        * if (STACK == 4) {    /* keep __STKSIZ */
  296.     .globl __STKSIZ        * global variable holding stack size
  297. gotstack    .equ    1
  298.     move.l    #__STKSIZ,a1    * Check to see if __STKSIZ was undefined.
  299.     beq    keepmin        * if it's zero, keep the minimum stack.
  300.     move.l    (a1),d1
  301.     bmi    giveback    *    if (__STKSIZ < 0) goto giveback;
  302.     add.l    d0,d1        *    d1 = __base+__STKSIZ; /* new sp */
  303.     bra    gotd1
  304.  
  305. keepmin:            * __STKSIZ was undefined; keep minimum.
  306.     move.l    #MINSTACK,d1
  307.     add.l    d0,d1        *    d1 = __base + MINSTACK;
  308.     bra    gotd1        *    goto gotd1;
  309.  
  310. giveback:
  311.     add.l    p_hitpa(a0),d1    *    d1 += hitpa;
  312.  
  313. gotd1:    move.l    d1,sp        * gotd1: sp = d1;
  314.     .endc
  315.  
  316. *************************************************************************
  317. *        STACK is something else: keep (if STACK>0) or give    *
  318. *            back (if STACK<0) STACK bytes            *
  319. *************************************************************************
  320.  
  321.     .ifeq    gotstack    * it's a constant stack value (+ or -)
  322.  
  323.     move.l    #STACK,d1    *    /* if neg, give back STACK bytes */
  324.     bmi    giveback    *    if (STACK < 0) goto giveback;
  325.     add.l    d0,d1        *    d1 = __STKSIZ + __base; /* new sp */
  326.     bra    gotd1        *    goto gotd1;
  327.  
  328. giveback:            * giveback:
  329.     add.l    p_hitpa(a0),d1    *    d1 += hitpa;    /* d1 = new sp */
  330. gotd1:                * gotd1:
  331.     move.l    d1,sp        *    sp = d1;
  332.     .endc
  333.  
  334. *************************************************************************
  335. *                                    *
  336. * DOSHRINK: take SP as a requested stack pointer. Place it        *
  337. * between (__break+MINSTACK) and (p_hitpa(a0)-FUDGE).  If we can't,    *
  338. * abort. Otherwise, we return the remaining memory back to the o.s.    *
  339. * The reason we always shrink by at least FUDGE bytes is to work around    *
  340. * a bug in the XBIOS Malloc() routine: when there are fewer than 512    *
  341. * bytes in the largest free block, attempting a Pexec() breaks the    *
  342. * memory management system.  Since all models except -1 permit Pexec()    *
  343. * calls, we have to make sure they don't break, even if the Pexec()    *
  344. * fails.  Thus, FUDGE must be at least 512.                *
  345. *                                    *
  346. *************************************************************************
  347. *
  348. * PSEUDOCODE:
  349. * doshrink(sp)
  350. * {
  351. *    /* if too low, bump it up */
  352. *    if (sp < (__break + MINSTACK))
  353. *        sp = (__break + MINSTACK);
  354. *
  355. *    /* if too high, bump it down */
  356. *    if (sp > (hitpa - FUDGE)) {
  357. *        sp = (hitpa - FUDGE);
  358. *
  359. *        /* if now too low, there's not enough memory */
  360. *        if (sp < (__break + MINSTACK))
  361. *            goto abort;
  362. *    }
  363. *    Mshrink(0,__base,(sp - __base));
  364. * }
  365. *
  366. *************************************************************************
  367.  
  368.     .ifne    doshrink    * assemble this only if STACK != -1
  369.     move.l    d0,d1        *     d1 = __break;
  370.     add.l    #MINSTACK,d1    *     d1 += MINSTACK;
  371.     cmp.l    d1,sp        *     if ((__break+MINSTACK) < sp)
  372.     bhi    minok        *     goto minok;
  373.     move.l    d1,sp        *     else sp = (__break+MINSTACK)
  374. minok:                * minok:
  375.     move.l    p_hitpa(a0),d2    *     d2 = hitpa;
  376.     sub.l    #FUDGE,d2    *     d2 -= FUDGE;
  377.     cmp.l    d2,sp        *     if ((hitpa - FUDGE) > sp)
  378.     bcs    maxok        *    goto maxok;
  379. *                *     else {
  380.     move.l    d2,sp        *    sp = (hitpa - FUDGE);
  381.     cmp.l    d1,d2        *     if ((__break+MINSTACK) > (hitpa-FUDGE))
  382.     bcs    abort        *        goto abort;    /* BAD NEWS */
  383. *                *     }
  384. maxok:
  385.  
  386. *************************************************************************
  387. * STACK LOCATION HAS BEEN DETERMINED. Return unused memory to the o.s.    *
  388. *************************************************************************
  389.  
  390.     move.l    sp,d1        *     d1 = sp;
  391.     and.l    #-2,d1        *     /* ensure d1 is even */
  392.     move.l    d1,sp        *     sp = d1;
  393.     sub.l    a0,d1        *     d1 -= __base; /* d1 == size to keep */
  394.  
  395.     move.l    d1,-(sp)    * push the size to keep
  396.     move.l    a0,-(sp)    * and start of this block (our basepage)
  397.     clr.w    -(sp)        * and a junk word
  398.     move    #mshrink,-(sp)    * and the function code
  399.     trap    #1        * Mshrink(0,__base,(sp-base))
  400.     add.l    #12,sp        * clean the stack after ourselves
  401.     .endc
  402.  
  403. *************************************************************************
  404. *                                    *
  405. * Finally, the stack is set up. Now call _main(cmdline, length).    *
  406. *                                    *
  407. *************************************************************************
  408.  
  409.     move.l    __base,a0    * set up _main(cmdline,length)
  410.     lea.l    p_cmdlin(a0),a2    * a2 now points to command line
  411.     move.b    (a2)+,d0    * d0 = length; a2++;
  412.     ext.w    d0        * extend byte count into d0.w
  413.     move.w    d0,-(a7)    * push length
  414.     move.l    a2,-(a7)    * Push commnd
  415.     clr.l    a6        * Clear frame pointer
  416.     jsr    __main        * call main routine    NEVER RETURNS
  417.  
  418. ***********************************************************************
  419. *
  420. * _exit(code)    Terminate process, return code to the parent.
  421. *
  422. ***********************************************************************
  423.  
  424. __exit:
  425.     tst.l    (a7)+        * drop return PC off the stack, leaving code
  426.     move.w    #pterm,-(a7)    * push function number
  427.     trap    #1        * and trap.
  428.  
  429. *
  430. * abort: used if the stack setup above fails. Restores the initial sp,
  431. * prints a message, and quits with the error ENSMEM.
  432. *
  433. abort:                * print an abortive message and quit
  434.     move.l    a1,sp        * restore initial sp
  435.     pea.l    abortmsg    * push string address
  436.     move.w    #cconws,-(a7)    * and function code
  437.     trap    #1        * and trap to print message
  438.     addq.l    #6,a7        * clean off stack
  439.     move.w    #-39,-(a7)    * push error number -39: ENSMEM
  440.     jsr    __exit        * and exit with it.
  441. *
  442. *
  443. _brk:        
  444.     cmp.l    __break,sp    * compare current break with current stack
  445.     bcs    __sovf        * actual stack overflow!
  446.     movea.l    4(sp),a0    * get new break
  447.     move.l    a0,d0        * compare with stack, including 256-byte
  448.     adda.l    #$100,a0    * chicken factor
  449.     cmpa.l    a0,sp        * if (sp < a0+256)
  450.     bcs    badbrk        *     bad break;
  451.     move.l    d0,__break    * OK break: save the break
  452.     clr.l    d0        * Set OK return
  453.     rts            * return
  454.  
  455. badbrk:
  456.     move.l    #-1,d0        * Load return reg
  457.     rts            * Return
  458. *
  459. * This ___BDOS code is broken: it comes from the DRI standard library's
  460. * need to do OS calls in its startup code.  See below for the fix, and
  461. * thanks to Robert Royar at the University of Louisville.
  462. *.globl    ___BDOS
  463. *___BDOS:
  464. *    link    a6,#0        ; link
  465. *    move.w    8(sp),d0    ; Load func code
  466. *    move.l    10(sp),d1    ; Load Paramter
  467. *    trap    #2        ; Enter BDOS
  468. *    cmpa.l    __break,sp    ; Check for stack ovf
  469. *    bcs    __sovf        ; overflow! print msg and abort
  470. *    unlk    a6        ; no error; return
  471. *    rts            ; Back to caller
  472.  
  473. ************************ BEGIN NEW, FIXED ___BDOS ***********************
  474.  
  475. .globl ___BDOS
  476. ___BDOS:
  477.     link    a6,#-4
  478.     move.w    $8(a6),d0
  479.     cmpi.w    #9,d0        ; test func code: print string?
  480.     beq    togem
  481.     cmpi.w    #2,d0        ; conout (2), conin (1), or term (0)?
  482.     bcs    togem
  483.     cmpi.w    #26,d0        ; setDTA?
  484.     bne    bdos        ; no - give to bdos
  485. togem:
  486.     move.l    $a(a6),(sp)
  487.     move.w    d0,-(sp)
  488.     bsr    xgemdos
  489.     addq.l    #2,sp
  490.     bra    out
  491.  
  492. bdos:
  493.     move.l    $a(a6),d1
  494. *                ; d0 already has function code
  495.     trap    #2
  496.     cmpa.l    __break,sp    ; check for overflow
  497.     bcs    __sovf        ; OVERFLOW! report the error and abort
  498. out:
  499.     unlk    a6
  500.     rts
  501.  
  502. xgemdos:
  503.     move.l    (sp)+,biosret
  504.     trap    #1
  505.     move.l    biosret,-(sp)
  506.     rts
  507.  
  508. .bss
  509. biosret:    ds.l    1
  510. .text
  511.  
  512. **************************** end of fixed ___BDOS **********************
  513.  
  514. *
  515. * stack overflow! This external is called by salloc in gemlib as well as above
  516. *
  517. __sovf:
  518.     move.l    #ovf,-(sp)    * push message address
  519.     move.w    #cconws,-(sp)    * push fn code
  520.     trap    #1        * Issue message
  521.  
  522.     move.w    #1,-(a7)    * push return code (1)
  523.     move.w    #pterm,d0    * push function code (Pterm)
  524.     trap    #1        * call Pterm(1) (never returns)
  525.  
  526. *
  527. *    Block Fill function:
  528. *
  529. *    blkfill(dest,char,cnt);
  530. *
  531. *    BYTE    *dest;        * -> area to be filled
  532. *    BYTE    char;        * =  char to fill
  533. *    WORD    cnt;        * =  # bytes to fill
  534. *
  535.     .globl    _blkfill
  536. _blkfill:
  537.     move.l    4(a7),a0    * -> Output area
  538.     move.w    8(a7),d1    * =  output char
  539.     move.w    10(a7),d0    * =  output count
  540.     ext.l    d0        * make it long
  541.     subq.l    #1,d0        * decrement
  542.     ble    filldone    * Done if le
  543. fillit:    move.b    d1,(a0)+    * move a byte
  544.     dbra    d0,fillit    * Continue
  545. filldone: clr.l    d0        * always return 0
  546.     rts            *
  547.  
  548. *
  549. *    Index function to find out if a particular character is in a string.
  550. *
  551.     .globl    _index
  552.     .globl    _strchr
  553. _index:
  554. _strchr:
  555.     move.l    4(a7),a0    * a0 -> String
  556.     move.w    8(a7),d0    * D0 = desired character
  557. xindex:    tst.b    (a0)        * EOS?
  558.     bne    notend        * No, continue to look
  559.     clr.l    d0        * Not found
  560.     rts            * Quit
  561. notend:    cmp.b    (a0)+,d0    * check for character
  562.     bne    xindex        *    
  563.     move.l    a0,d0        * Found it
  564.     subq.l    #1,d0        * set return pointer
  565.     rts
  566.  
  567. *
  568. *    For GEMAES calls from AESBIND.ARC or cryslib.o
  569. *
  570. _crystal:
  571.     move.l    4(a7),d1
  572.     move.w    #200,d0
  573.     trap    #2
  574.     rts
  575.  
  576. *
  577. *    Data area
  578. *
  579.     .data
  580.     .globl    ___pname    * Program Name
  581.     .globl    ___tname    * Terminal Name
  582.     .globl    ___lname    * List device name
  583.     .globl    ___xeof        * ^Z byte
  584. ovf:        .dc.b    'Stack Overflow',13,10,0    * Overflow message
  585. ___pname:    .dc.b    'runtime',0    * Program name
  586. ___tname:    .dc.b    'CON:',0    * Console name
  587. ___lname:    .dc.b    'LST:',0    * List device name
  588. ___xeof:    .dc.b    $1a        * Control-Z
  589. abortmsg:    .dc.b    'Cannot initialize stack',13,10,0    * abort message
  590.  
  591. **********************************************************************
  592. *
  593. * BSS AREA
  594. **********************************************************************
  595.     .bss
  596.     .even
  597. __base:        .ds.l    1    * -> Base Page
  598. __break:    .ds.l    1    * Break location
  599. ___cpmrv:    .ds.w    1    * Last CP/M return val
  600.  
  601. *
  602. *    control array for vdibind
  603. *
  604.     .data
  605.         .even
  606. _ctrl_cnts:                 *    Application Manager
  607.     .dc.b    0, 1, 0            * func 010        
  608.         .dc.b    2, 1, 1            * func 011        
  609.         .dc.b    2, 1, 1         * func 012        
  610.     .dc.b    0, 1, 1            * func 013        
  611.     .dc.b    2, 1, 1            * func 014        
  612.     .dc.b    1, 1, 1            * func 015        
  613.     .dc.b    0, 0, 0            * func 016        
  614.     .dc.b    0, 0, 0            * func 017        
  615.     .dc.b    0, 0, 0            * func 008        
  616.     .dc.b    0, 1, 0            * func 019        
  617. *                             Event Manager
  618.     .dc.b    0, 1, 0            * func 020        
  619.     .dc.b    3, 5, 0            * func 021        
  620.     .dc.b    5, 5, 0            * func 022        
  621.     .dc.b    0, 1, 1            * func 023        
  622.     .dc.b    2, 1, 0            * func 024        
  623.     .dc.b    16, 7, 1         * func 025        
  624.     .dc.b    2, 1, 0            * func 026        
  625.     .dc.b    0, 0, 0            * func 027        
  626.     .dc.b    0, 0, 0            * func 028        
  627.     .dc.b    0, 0, 0            * func 009        
  628. *                             Menu Manager
  629.     .dc.b    1, 1, 1            * func 030        
  630.     .dc.b    2, 1, 1            * func 031        
  631.     .dc.b    2, 1, 1            * func 032        
  632.     .dc.b    2, 1, 1            * func 033        
  633.     .dc.b    1, 1, 2            * func 034        
  634.     .dc.b    1, 1, 1            * func 005        
  635.     .dc.b    0, 0, 0            * func 006        
  636.     .dc.b    0, 0, 0            * func 007        
  637.     .dc.b    0, 0, 0            * func 008        
  638.     .dc.b    0, 0, 0            * func 009        
  639. *                             Object Manager
  640.     .dc.b    2, 1, 1            * func 040        
  641.     .dc.b    1, 1, 1            * func 041        
  642.       .dc.b    6, 1, 1            * func 042        
  643.     .dc.b    4, 1, 1            * func 043        
  644.     .dc.b    1, 3, 1            * func 044        
  645.     .dc.b    2, 1, 1            * func 045        
  646.     .dc.b    4, 2, 1            * func 046        
  647.     .dc.b    8, 1, 1            * func 047        
  648.     .dc.b    0, 0, 0            * func 048        
  649.     .dc.b    0, 0, 0            * func 049        
  650. *                             Form Manager
  651.     .dc.b    1, 1, 1            * func 050        
  652.     .dc.b    9, 1, 1            * func 051        
  653.     .dc.b    1, 1, 1            * func 002        
  654.     .dc.b    1, 1, 0            * func 003        
  655.     .dc.b    0, 5, 1            * func 004        
  656.     .dc.b    0, 0, 0            * func 005        
  657.     .dc.b    0, 0, 0            * func 006        
  658.     .dc.b    0, 0, 0            * func 007        
  659.     .dc.b    0, 0, 0            * func 008        
  660.     .dc.b    0, 0, 0            * func 009        
  661. *                             Dialog Manager
  662.     .dc.b    0, 0, 0            * func 060        
  663.     .dc.b    0, 0, 0            * func 061        
  664.     .dc.b    0, 0, 0            * func 062        
  665.     .dc.b    0, 0, 0            * func 003        
  666.     .dc.b    0, 0, 0            * func 004        
  667.     .dc.b    0, 0, 0            * func 005        
  668.     .dc.b    0, 0, 0            * func 006        
  669.     .dc.b    0, 0, 0            * func 007        
  670.     .dc.b    0, 0, 0            * func 008        
  671.     .dc.b    0, 0, 0            * func 009        
  672. *                            Graphics Manager
  673.     .dc.b    4, 3, 0            * func 070        
  674.     .dc.b    8, 3, 0            * func 071        
  675.     .dc.b    6, 1, 0            * func 072        
  676.     .dc.b    8, 1, 0            * func 073        
  677.     .dc.b    8, 1, 0            * func 074        
  678.     .dc.b    4, 1, 1            * func 075        
  679.     .dc.b    3, 1, 1            * func 076        
  680.     .dc.b    0, 5, 0            * func 077        
  681.     .dc.b    1, 1, 1            * func 078        
  682.     .dc.b    0, 5, 0            * func 009        
  683. *                            Scrap Manager
  684.     .dc.b    0, 1, 1            * func 080        
  685.     .dc.b    0, 1, 1            * func 081        
  686.     .dc.b    0, 0, 0            * func 082        
  687.     .dc.b    0, 0, 0            * func 083        
  688.     .dc.b    0, 0, 0            * func 084        
  689.     .dc.b    0, 0, 0            * func 005        
  690.     .dc.b    0, 0, 0            * func 006        
  691.     .dc.b    0, 0, 0            * func 007        
  692.     .dc.b    0, 0, 0            * func 008        
  693.     .dc.b    0, 0, 0            * func 009        
  694. *                            fseler Manager
  695.     .dc.b    0, 2, 2            * func 090        
  696.     .dc.b    0, 0, 0            * func 091        
  697.     .dc.b    0, 0, 0            * func 092        
  698.     .dc.b    0, 0, 0            * func 003        
  699.     .dc.b    0, 0, 0            * func 004        
  700.     .dc.b    0, 0, 0            * func 005        
  701.     .dc.b    0, 0, 0            * func 006        
  702.     .dc.b    0, 0, 0            * func 007        
  703.     .dc.b    0, 0, 0            * func 008        
  704.     .dc.b    0, 0, 0         * func 009        
  705. *                            Window Manager
  706.     .dc.b    5, 1, 0            * func 100        
  707.     .dc.b    5, 1, 0            * func 101        
  708.     .dc.b    1, 1, 0            * func 102        
  709.     .dc.b    1, 1, 0            * func 103        
  710.     .dc.b    2, 5, 0            * func 104        
  711.     .dc.b    6, 1, 0            * func 105        
  712.     .dc.b    2, 1, 0            * func 106        
  713.     .dc.b    1, 1, 0            * func 107        
  714.     .dc.b    6, 5, 0            * func 108        
  715.     .dc.b    0, 0, 0         * func 009        
  716. *                            Resource Manger
  717.     .dc.b    0, 1, 1            * func 110        
  718.     .dc.b    0, 1, 0            * func 111        
  719.     .dc.b    2, 1, 0            * func 112        
  720.     .dc.b    2, 1, 1            * func 113        
  721.     .dc.b    1, 1, 1            * func 114        
  722.     .dc.b    0, 0, 0            * func 115        
  723.     .dc.b    0, 0, 0            * func 006
  724.     .dc.b    0, 0, 0            * func 007
  725.     .dc.b    0, 0, 0            * func 008
  726.     .dc.b    0, 0, 0            * func 009
  727. *                            Shell Manager
  728.     .dc.b    0, 1, 2            * func 120
  729.     .dc.b    3, 1, 2            * func 121
  730.     .dc.b    1, 1, 1            * func 122
  731.     .dc.b    1, 1, 1            * func 123
  732.     .dc.b    0, 1, 1            * func 124
  733.     .dc.b    0, 1, 2            * func 125
  734.  
  735.     .end
  736.