home *** CD-ROM | disk | FTP | other *** search
/ ftp.barnyard.co.uk / 2015.02.ftp.barnyard.co.uk.tar / ftp.barnyard.co.uk / cpm / commercial-software / programming / AZTEC302.ZIP / DOS11.ARC < prev    next >
Text File  |  1998-09-16  |  13KB  |  774 lines

  1. bdos.asm
  2. ; :ts=8
  3. ;Copyright (C) 1983 by Manx Software Systems
  4. codeseg    segment    para public 'code'
  5. dataseg    segment    para public 'data'
  6.     extrn    errno_:word
  7.     extrn    _Dmaseg_:word
  8. dataseg    ends
  9.     assume    cs:codeseg,ds:dataseg
  10.     public    bdos_
  11. bdos_    proc    near
  12.     mov    bx,sp
  13.     push    es
  14.     mov    ax,2[bx]
  15.     test    ah,ah
  16.     jnz    valok
  17.     xchg    ah,al
  18. valok:
  19.     mov    dx,4[bx]
  20.     mov    cx,6[bx]
  21.     int    21H
  22.     pop    es
  23.     and    ax,0ffH
  24.     ret
  25. ;
  26.     public    filerd_
  27. filerd_:        ;filerd(fcb, buffer, length)
  28.             ;struct fcb *fcb; char *buffer; int length;
  29.     mov    cl,27H
  30.     jmp    short iocommon
  31. ;
  32.     public    filewr_
  33. filewr_:        ;filewr(fcb, buffer, length)
  34.             ;struct fcb *fcb; char *buffer; int length;
  35.     mov    cl,28H
  36. iocommon:
  37.     mov    bx,sp
  38.     push    ds
  39.     mov    ah,1aH
  40.     mov    dx,4[bx]
  41.     mov    ds,_Dmaseg_
  42.     int    21H
  43.     pop    ds
  44.     mov    ah,cl
  45.     mov    dx,2[bx]
  46.     mov    cx,6[bx]
  47.     int    21H
  48.     and    ax,0ffH
  49.     mov    errno_,ax
  50.     jz    io_ok
  51.     cmp    al,1
  52.     je    io_ok
  53.     mov    ax,-1
  54.     ret
  55. io_ok:
  56.     mov    ax,cx
  57.     ret
  58. ;
  59.     public fcbinit_
  60. fcbinit_:
  61.     mov    bx,sp
  62.     push    di
  63.     push    si
  64.     mov    si,2[bx]    ;si contains name
  65.     mov    di,4[bx]    ;di contains fcb address
  66.     mov    ax,2900H    ; issue parse filename call
  67.     int    21H
  68.     and    ax,0ffH
  69.     cmp    byte ptr 1[di],' '
  70.     jne    nameok
  71.     mov    ax,-1
  72. nameok:
  73.     test    ax,ax
  74.     pop    si
  75.     pop    di
  76.     ret
  77. bdos_    endp
  78. codeseg    ends
  79.     end
  80. begin.asm
  81. ; Copyright (C) 1983 1984 by Manx Software Systems
  82. ; :ts=8
  83. codeseg    segment    para public 'code'
  84.     public    $MEMRY
  85.     public    _mbot_, sbot
  86. dataseg    segment    para public 'data'
  87. $MEMRY    dw    -1
  88.     public    errno_
  89. errno_    dw    0
  90.     public    _dsval_,_csval_
  91. _dsval_    dw    0
  92. _csval_    dw    0
  93.     public    _Dmaseg_
  94. _Dmaseg_ dw    0
  95. _mbot_    dw    0
  96. sbot    dw    0
  97.     extrn    _Uorg_:byte,_Uend_:byte
  98. dataseg    ends
  99.     public    exitad, exitcs
  100. exitad    dw    0
  101. exitcs    dw    0
  102.  
  103.     assume    cs:codeseg,ds:dataseg,es:dataseg,ss:dataseg
  104.     extrn Croot_:near
  105.     public    $begin
  106.     public    _exit_
  107. $begin    proc    far
  108.     mov    bp,dataseg
  109.     test    bp,bp
  110.     jnz    notcom
  111.     mov    bp,ds
  112. notcom:
  113.     mov    exitcs,ds
  114.     mov    bx,[2]    ;get top segment
  115.     sub    bx,bp        ;compute size of Data seg
  116.     cmp    bx,4096        ;check if greater than 64K
  117.     jbe    smallseg
  118.     mov    bx,4096
  119. smallseg:
  120.     mov    es,bp
  121.     mov    cl,4
  122.     shl    bx,cl
  123.     cli
  124.     mov    ss,bp
  125.     mov    sp,bx
  126.     sti
  127.     cld
  128. ;        clear uninitialized data
  129.     mov    di,offset _Uorg_
  130.     mov    cx,offset _Uend_
  131.     sub    cx,di
  132.     inc    cx
  133.     shr    cx,1
  134.     jcxz    noclear
  135.     sub    ax,ax
  136. rep    stosw
  137. noclear:
  138. ;
  139. no_args:
  140.     mov    cl,[80H]
  141.     sub    ch,ch
  142.     mov    si,81H
  143.     mov    ax,1
  144.     push    ax            ;first arg # for Croot
  145.     mov    di,es:$MEMRY
  146.     push    di            ;argp for Croot
  147.     jcxz    cpy_done
  148. rep    movsb                ;copy argument string to work buffer
  149. cpy_done:
  150.     sub    al,al
  151.     stosb            ;null terminate string
  152.     mov    ds,bp            ;set DS, now DS, SS, ES are equal
  153.     inc    di
  154.     and    di,0fffeH        ;adjust to word boundary
  155.     mov    $MEMRY,di    ;save memory allocation info for sbrk()
  156.     mov    _mbot_,di
  157.     mov    ax,sp
  158.     sub    ax,2048        ;allow 2Kb of stack space
  159.     mov    sbot,ax
  160.     mov    _dsval_,ds
  161.     mov    _Dmaseg_,ds
  162.     mov    _csval_,cs
  163.     call    Croot_        ;Croot(argp, first)
  164.     jmp    short exit
  165. _exit_:
  166.     pop    ax
  167.     pop    ax        ;fetch return code
  168.     test    ax,ax
  169.     jz    exit
  170.     int    23h        ;use int 23 handler for non-zero exits
  171. exit:
  172.     jmp    dword ptr exitad
  173. $begin    endp
  174. codeseg    ends
  175.     end    $begin
  176. close.c
  177. /* Copyright (C) 1982 by Manx Software Systems */
  178. #include "errno.h"
  179. #include "io.h"
  180.  
  181. extern int badfd();
  182.  
  183. close(fd)
  184. {
  185.     register struct channel *chp;
  186.  
  187.     if (fd < 0 || fd > MAXCHAN) {
  188.         errno = EBADF;
  189.         return -1;
  190.     }
  191.     chp = &chantab[fd];
  192.     fd = (*chp->c_close)(chp->c_arg);
  193.     chp->c_read = chp->c_write = chp->c_ioctl = chp->c_seek = 0;
  194.     chp->c_close = badfd;
  195.     return fd;
  196. }
  197.  
  198. croot.c
  199. /* Copyright (C) 1981,1982, 1983 by Manx Software Systems */
  200. #include "errno.h"
  201. #include "fcntl.h"
  202. #include "io.h"
  203.  
  204. badfd()
  205. {
  206.     errno = EBADF;
  207.     return -1;
  208. }
  209.  
  210. noper()
  211. {
  212.     return 0;
  213. }
  214.  
  215. int (*cls_)() = noper;
  216.  
  217. /*
  218.  * channel table: relates fd's to devices
  219.  */
  220. struct channel  chantab[] = {
  221.     { 2, 0, 1, 0, noper, 2 },
  222.     { 0, 2, 1, 0, noper, 2 },
  223.     { 0, 2, 1, 0, noper, 2 },
  224.     { 0, 0, 0, 0, badfd, 0 },
  225.     { 0, 0, 0, 0, badfd, 0 },
  226.     { 0, 0, 0, 0, badfd, 0 },
  227.     { 0, 0, 0, 0, badfd, 0 },
  228.     { 0, 0, 0, 0, badfd, 0 },
  229.     { 0, 0, 0, 0, badfd, 0 },
  230.     { 0, 0, 0, 0, badfd, 0 },
  231.     { 0, 0, 0, 0, badfd, 0 },
  232. };
  233.  
  234. #define MAXARGS 30
  235. static char *Argv[MAXARGS];
  236. static int Argc;
  237.  
  238. Croot(cp)
  239. register char *cp;
  240. {
  241.     register char *fname;
  242.     register int k;
  243.  
  244.     Argv[0] = "";
  245.     Argc = 1;
  246.     while (Argc < MAXARGS) {
  247.         while (*cp == ' ' || *cp == '\t')
  248.             ++cp;
  249.         if (*cp == 0)
  250.             break;
  251. #ifndef NOREDIR
  252.         if (*cp == '>') {        /* redirect output */
  253.             k = 1;
  254.             goto redirect;
  255.         } else if (*cp == '<') {    /* redirect input */
  256.             k = 0;
  257. redirect:
  258.             while (*++cp == ' ' || *cp == '\t')
  259.                 ;
  260.             fname = cp;
  261.             while (*++cp)
  262.                 if (*cp == ' ' || *cp == '\t') {
  263.                     *cp++ = 0;
  264.                     break;
  265.                 }
  266.             close(k);
  267.             if (k)
  268.                 k = creat(fname, 0666);
  269.             else
  270.                 k = open(fname, O_RDONLY);
  271.             if (k == -1)
  272.                 redir_err(fname);
  273.         } else
  274. #endif
  275.         {
  276.             Argv[Argc++] = cp;
  277.             while (*++cp)
  278.                 if (*cp == ' ' || *cp == '\t') {
  279.                     *cp++ = 0;
  280.                     break;
  281.                 }
  282.         }
  283.     }
  284.     main(Argc,Argv);
  285.     exit(0);
  286. }
  287.  
  288. #ifndef NOREDIR
  289. static redir_err(name)
  290. char *name;
  291. {
  292.     char buff[200];
  293.  
  294.     strcpy(buff, "Can't open file for redirection: ");
  295.     strcat(buff, name);
  296.     strcat(buff, "\n");
  297.     write(2, buff, strlen(buff));
  298.     exit(10);
  299. }
  300. #endif
  301.  
  302. exit(code)
  303. {
  304.     register int fd;
  305.  
  306.     (*cls_)();
  307.     for (fd = 0 ; fd < MAXCHAN ; )
  308.         close(fd++);
  309.     _exit(code);
  310. }
  311. csread.c
  312. /* Copyright (C) 1984 by Manx Software Systems */
  313.  
  314. extern unsigned _csval, _dsval, _Dmaseg;
  315.  
  316. _csread(fd, buff, len)
  317. char *buff;
  318. {
  319.     register ret;
  320.  
  321.     _Dmaseg = _csval;
  322.     ret = read(fd, buff, len);
  323.     _Dmaseg = _dsval;
  324.     return ret;
  325. }
  326. ioctl.c
  327. /* Copyright (C) 1984 by Manx Software Systems */
  328. #include "io.h"
  329. #include "errno.h"
  330. #include "sgtty.h"
  331.  
  332. #define TIME    10        /* number of iterations of raw_rd loop */
  333. #define MIN        1        /* minimum number of chars returned from read */
  334.  
  335. extern int (*Rd_tab[])();
  336. extern int (*Wrt_tab[])();
  337.  
  338. struct sgttyb Tty_ctl;
  339. extern char _Eol;
  340. extern int tty_rd();
  341. static int raw_rd(), raw_wr();
  342. static int rd_func, wrt_func;
  343.  
  344. ioctl(fd, cmd, arg)
  345. struct sgttyb *arg;
  346. {
  347.     register struct channel *chp;
  348.  
  349.     chp = &chantab[fd];
  350.     if (chp->c_ioctl == 0) {
  351.         errno = ENOTTY;
  352.         return -1;
  353.     }
  354.     switch (cmd) {
  355.     case TIOCGETP:
  356.         *arg = Tty_ctl;
  357.         break;
  358.     case TIOCSETP:
  359.         Tty_ctl = *arg;
  360.         Wrt_tab[2] = raw_wr;
  361.         Rd_tab[2] = raw_rd;
  362.         if (Tty_ctl.sg_flags&RAW) {
  363.             rd_func =
  364.             wrt_func = 6;
  365.             _Eol = '\r';
  366.             break;
  367.         } else if (Tty_ctl.sg_flags&CBREAK) {
  368.             rd_func = (Tty_ctl.sg_flags&ECHO) ? 1 : 6;
  369.             wrt_func = 2;
  370.         } else {
  371.             Rd_tab[2] = tty_rd;
  372.             wrt_func = 2;
  373.         }
  374.         if (Tty_ctl.sg_flags&CRMOD)
  375.             _Eol = '\n';
  376.         else
  377.             _Eol = '\r';
  378.     }
  379.     return 0;
  380. }
  381.  
  382. static
  383. raw_rd(x, buff, len)
  384. register char *buff;
  385. {
  386.     int c, i;
  387.     register int count;
  388.  
  389.     for (count = 0 ; count < len ; ) {
  390.         for (i = TIME ; i-- ; )
  391.             if ((c = bdos(rd_func,0xff)) != 0)
  392.                 goto have_char;
  393.         if (count < MIN)
  394.             continue;
  395.         break;
  396. have_char:
  397.         if (c == '\r')
  398.             c = _Eol;
  399.         *buff++ = c;
  400.         ++count;
  401.     }
  402.     return count;
  403. }
  404.  
  405. static
  406. raw_wr(kind, buff, len)
  407. register char *buff;
  408. {
  409.     register int count;
  410.  
  411.     for (count = len ; count-- ; ) {
  412.         if (*buff == '\n' && (Tty_ctl.sg_flags&CRMOD))
  413.             bdos(wrt_func,'\r');
  414.         bdos(wrt_func,*buff++);
  415.     }
  416.     return len;
  417. }
  418. isatty.c
  419. /* Copyright (C) 1983 by Manx Software Systems */
  420. #include "io.h"
  421. #include "errno.h"
  422.  
  423. isatty(fd)
  424. {
  425.     return chantab[fd].c_ioctl;
  426. }
  427.  
  428. lseek.c
  429. /* Copyright (C) 1982,1983 by Manx Software Systems and Thomas Fenwick */
  430. #include "io.h"
  431. #include "errno.h"
  432.  
  433. long lseek(fd, pos, how)
  434. long pos;
  435. {
  436.     register struct fcbtab *fp;
  437.  
  438.     if (fd < 0 || fd > MAXCHAN || chantab[fd].c_seek == 0) {
  439.         errno = EBADF;
  440.         return -1L;
  441.     }
  442.     fp = chantab[fd].c_arg;
  443.  
  444.     switch (how) {
  445.     case 2:
  446.         pos += fp->fcb.f_size;
  447.         break;
  448.     case 1:
  449.         pos += fp->fcb.f_record;
  450.     case 0:
  451.         break;
  452.  
  453.     default:
  454.         errno = EINVAL;
  455.         return -1L;
  456.     }
  457.  
  458.     if (pos < 0) {
  459.         fp->fcb.f_record = 0;
  460.         errno = EINVAL;
  461.         return -1L;
  462.     }
  463.     fp->fcb.f_record = pos;
  464.     return pos;
  465. }
  466.  
  467. open.c
  468. /* Copyright (C) 1982 by Manx Software Systems */
  469. #include "errno.h"
  470. #include "fcntl.h"
  471. #include "io.h"
  472.  
  473. #define MAXFILE    8    /* maximum number of open DISK files */
  474. int badfd(), noper();
  475. static int fileop();
  476.  
  477. static struct device condev = { 2, 2, 1, 0, noper };
  478. static struct device filedev= { 1, 1, 0, 1, fileop };
  479.  
  480. /*
  481.  * device table, contains names and pointers to device entries
  482.  */
  483. static struct devtabl devtabl[] = {
  484.     { "con:", &condev, 2 },
  485.     { "CON:", &condev, 2 },
  486.     { 0, &filedev, 0 }        /* this must be the last slot in the table! */
  487. };
  488.  
  489. creat(name, mode)
  490. char *name;
  491. {
  492.     return open(name, O_WRONLY|O_TRUNC|O_CREAT, mode);
  493. }
  494.  
  495. open(name, flag, mode)
  496. char *name;
  497. {
  498.     register struct devtabl *dp;
  499.     register struct channel *chp;
  500.     register struct device *dev;
  501.     int fd, mdmask;
  502.  
  503.     for (chp = chantab, fd = 0 ; fd < MAXCHAN ; ++chp, ++fd)
  504.         if (chp->c_close == badfd)
  505.             goto fndchan;
  506.     errno = EMFILE;
  507.     return -1;
  508.  
  509. fndchan:
  510.     for (dp = devtabl ; dp->d_name ; ++dp)
  511.         if (strcmp(dp->d_name, name) == 0)
  512.             break;
  513.     dev = dp->d_dev;
  514.     mdmask = (flag&3) + 1;
  515.     if (mdmask&1) {
  516.         if ((chp->c_read = dev->d_read) == 0) {
  517.             errno = EACCES;
  518.             return -1;
  519.         }
  520.     }
  521.     if (mdmask&2) {
  522.         if ((chp->c_write = dev->d_write) == 0) {
  523.             errno = EACCES;
  524.             return -1;
  525.         }
  526.     }
  527.     chp->c_arg = dp->d_arg;
  528.     chp->c_ioctl = dev->d_ioctl;
  529.     chp->c_seek = dev->d_seek;
  530.     chp->c_close = noper;
  531.     if ((*dev->d_open)(name, flag, mode, chp, dp) < 0) {
  532.         chp->c_close = badfd;
  533.         return -1;
  534.     }
  535.     return fd;
  536. }
  537.  
  538. static struct fcbtab fcbtab[MAXFILE];
  539.  
  540. static
  541. fileop(name,flag,mode,chp,dp)
  542. char *name; struct channel *chp; struct devtabl *dp;
  543. {
  544.     register struct fcbtab *fp;
  545.     static int filecl();
  546.  
  547.     for ( fp = fcbtab ; fp < fcbtab+MAXFILE ; ++fp )
  548.         if ( fp->flags == 0 )
  549.             goto havefcb;
  550.     errno = EMFILE;
  551.     return -1;
  552.  
  553. havefcb:
  554.     if ( fcbinit(name,&fp->fcb) ) {
  555.         errno = EINVAL;
  556.         return -1;
  557.     }
  558.     if (flag & O_TRUNC)
  559.         bdos(DELFIL, &fp->fcb);
  560.     if (bdos(OPNFIL,&fp->fcb) == 0xff) {
  561.         if ((flag&(O_TRUNC|O_CREAT)) == 0 || bdos(MAKFIL,&fp->fcb) == 0xff) {
  562.             errno = ENOENT;
  563.             return -1;
  564.         }
  565.     } else if ((flag&(O_CREAT|O_EXCL)) == (O_CREAT|O_EXCL)) {
  566.         errno = EEXIST;
  567.         return -1;
  568.     }
  569.     
  570.     fp->flags = 1;
  571.     fp->fcb.f_record = (flag&O_APPEND) ? fp->fcb.f_size : 0L;
  572.     fp->fcb.f_reclen = 1;
  573.     chp->c_arg = fp;
  574.     chp->c_close = filecl;
  575.     return 0;
  576. }
  577.  
  578. static
  579. filecl(fp)
  580. register struct fcbtab *fp;
  581. {
  582.     bdos(CLSFIL,&fp->fcb);
  583.     fp->flags = 0;
  584.     return 0;
  585. }
  586.  
  587. read.c
  588. /* Copyright (C) 1982, 1983 by Manx Software Systems */
  589. #include "io.h"
  590. #include "errno.h"
  591. #include "fcntl.h"
  592.  
  593. int badfd(), filerd(), tty_rd();
  594.  
  595. int (*Rd_tab[])() = {
  596.     badfd, filerd, tty_rd,
  597. };
  598. extern int errno;
  599.  
  600. read(fd, buff, len)
  601. char *buff;
  602. {
  603.     register struct channel *chp;
  604.  
  605.     if (fd < 0 || fd > MAXCHAN) {
  606.         errno = EBADF;
  607.         return -1;
  608.     }
  609.     chp = &chantab[fd];
  610.     return (*Rd_tab[chp->c_read])(chp->c_arg, buff, len);
  611. }
  612.  
  613. char _Eol = '\n';
  614.  
  615. tty_rd(x,buff,len)
  616. char *buff;
  617. {
  618.     static char buffer[258];
  619.     static int used;
  620.     register int l;
  621.  
  622.     if (buffer[1] == 0) {
  623.         buffer[0] = 255;
  624.         buffer[1] = buffer[2] = 0;
  625.         bdos(10,buffer);
  626.         bdos(2,'\n');
  627.         if (buffer[2] == 0x1a) {
  628.             buffer[1] = 0;
  629.             return 0;
  630.         }
  631.         buffer[++buffer[1] + 1] = _Eol;
  632.         used = 2;
  633.     }
  634.     if ((l = buffer[1]) > len)
  635.         l = len;
  636.     movmem(buffer+used, buff, l);
  637.     used += l;
  638.     buffer[1] -= l;
  639.     return l;
  640. }
  641.  
  642. rename.c
  643. rename(old, new)
  644. char *old, *new;
  645. {
  646.     char buff[60];
  647.  
  648.     fcbinit(new,buff);
  649.     bdos(19,buff);
  650.     fcbinit(old,buff);
  651.     fcbinit(new,buff+16);
  652.     bdos(23,buff);
  653. }
  654. unlink.c
  655. #include "io.h"
  656.  
  657. unlink(name)
  658. char *name;
  659. {
  660.     struct fcb delfcb;
  661.  
  662.     fcbinit(name,&delfcb);
  663.     return bdos(DELFIL,&delfcb);
  664. }
  665.  
  666. write.c
  667. /* Copyright (C) 1982, 1983 by Manx Software Systems */
  668. #include "io.h"
  669. #include "errno.h"
  670.  
  671. int filewr(), badfd(), conwr();
  672.  
  673. int (*Wrt_tab[])() = {
  674.     badfd, filewr, conwr,
  675. };
  676.  
  677. write(fd, buff, len)
  678. char *buff;
  679. {
  680.     register struct channel *chp;
  681.  
  682.     if (fd < 0 || fd > MAXCHAN) {
  683.         errno = EBADF;
  684.         return -1;
  685.     }
  686.     chp = &chantab[fd];
  687.     return (*Wrt_tab[chp->c_write])(chp->c_arg, buff, len);
  688. }
  689.  
  690. conwr(kind, buff, len)
  691. register char *buff;
  692. {
  693.     register int count;
  694.  
  695.     for (count = 0 ; count < len ; ++count)
  696.         bdos(kind, *buff++);
  697.     return count;
  698. }
  699.  
  700. sbrk.asm
  701. ; :ts=8
  702. ;Copyright (C) 1983 by Manx Software Systems
  703.     include lmacros.h
  704. dataseg    segment    word public 'data'
  705.     extrn    $MEMRY:word
  706.     extrn    _mbot_:word, sbot:word
  707.     extrn    errno_:word
  708. dataseg    ends
  709.     assume    ds:dataseg
  710. ;
  711. ; sbrk(size): return address of current top & bump by size bytes
  712. ;
  713.     procdef    sbrk,<<siz,word>>
  714.     push    di
  715.     mov    ax,siz
  716.     mov    di,$MEMRY
  717.     add    ax,di
  718.     push    ax
  719.     call    brk_
  720.     pop    cx
  721.     jnz    brk_error
  722.     mov    ax,di        ;return original value of the break
  723. ifdef LONGPTR
  724.     mov    dx,ds
  725.     pop    di
  726.     pret
  727. endif
  728. brk_error:
  729.     pop    di
  730. ifdef LONGPTR
  731.     mov    dx,ax
  732. endif
  733.     test    ax,ax        ;set flags for C
  734.     pret
  735.     pend    sbrk
  736. ;
  737. ; brk(addr):    set current top address to addr
  738. ;        returns 0 if ok, -1 if error
  739. ;
  740.     procdef brk,<<addr,word>>
  741.     mov    ax,addr
  742.     inc    ax
  743.     and    al,-2
  744.     cmp    ax,sbot            ;check for stack/heap overflow
  745.     jae    brk_ov
  746.     mov    bx,sp
  747.     cmp    ax,bx            ;double check with sp for saftey
  748.     jae    brk_ov
  749.     cmp    ax,_mbot_
  750.     jb    brk_ov
  751.     mov    $MEMRY,ax    ;new value is good so save it away
  752.     sub    ax,ax
  753.     pret
  754. ; invalid request
  755. brk_ov:
  756.     mov    errno_,-4
  757.     mov    ax,-1
  758.     test    ax,ax
  759.     pret
  760.     pend    brk
  761. ;
  762. ; rsvstk(size):        set saftey margin for stack
  763. ;            this will make sure that at least size
  764. ;            bytes of stack below the current level remain.
  765. ;
  766.     procdef    rsvstk,<<stksize,word>>
  767.     mov    ax,sp
  768.     sub    ax,stksize
  769.     mov    sbot,ax
  770.     pret
  771.     pend    rsvstk
  772.     finish
  773.     end
  774.