home *** CD-ROM | disk | FTP | other *** search
/ Columbia Kermit / kermit.zip / mskermit / msnut1.asm < prev    next >
Assembly Source File  |  2020-01-01  |  22KB  |  957 lines

  1.        NAME    msnut1
  2. ; File MSNUT1.ASM
  3. ; Provides various Intel 8088 level operations, including
  4. ; display facilities (via msg buffer or DOS) for char, strings, etc.
  5. ;
  6. ; Copyright 1991, University of Waterloo.
  7. ;    Copyright (C) 1982, 1997, Trustees of Columbia University in the 
  8. ;    City of New York.  The MS-DOS Kermit software may not be, in whole 
  9. ;    or in part, licensed or sold for profit as a software product itself,
  10. ;    nor may it be included in or distributed with commercial products
  11. ;    or otherwise distributed by commercial concerns to their clients 
  12. ;    or customers without written permission of the Office of Kermit 
  13. ;    Development and Distribution, Columbia University.  This copyright 
  14. ;    notice must not be removed, altered, or obscured.
  15. ; Written by Erick Engelke of the University of Waterloo, Waterloo, 
  16. ;  Ontario, Canada,
  17. ;  and by Joe R. Doupnik, Utah State University, 
  18. ;  jrd@cc.usu.edu, jrd@usu.Bitnet.
  19. ;
  20. ; Edit history
  21. ; 12 Jan 1995 version 3.14
  22. ; Last edit
  23. ; 12 Jan 1995
  24.  
  25. cr    equ    0dh
  26. lf    equ    0ah
  27. conout    equ    2
  28. dconio    equ    6
  29. dos    equ    21h
  30. ioctl    equ    44h
  31. allocmem equ    48h
  32. freemem    equ    49h
  33.  
  34. MSGBUFLEN equ    512            ; coordinate with msntnd.c
  35. BIOSCLK    equ    046ch
  36. HI_MAX    equ    018h
  37. LO_MAX    equ     0b0h
  38.  
  39. _TEXT    SEGMENT  WORD PUBLIC 'CODE'
  40. _TEXT    ENDS
  41. _DATA    SEGMENT  WORD PUBLIC 'DATA'
  42. _DATA    ENDS
  43. CONST    SEGMENT  WORD PUBLIC 'CONST'
  44. CONST    ENDS
  45. _BSS    SEGMENT  WORD PUBLIC 'BSS'
  46. _BSS    ENDS
  47. DGROUP    GROUP    CONST, _BSS, _DATA
  48.     ASSUME  CS: _TEXT, DS: DGROUP, SS: DGROUP
  49.  
  50.     include    mssdef.h
  51. data    segment
  52.     extrn    flags:byte
  53. data    ends
  54.  
  55. _DATA    SEGMENT
  56.     extrn    _doslevel:word, _msgcnt:word, _msgbuf:byte,_display_mode:byte
  57.     extrn    _tcpflag:byte, _dobinary:byte
  58. _DATA    ENDS
  59.  
  60. _TEXT    segment
  61.  
  62.         ; Compute 1's-complement sum of data buffer
  63.         ; unsigned checksum( unsigned word FAR *buf, unsigned cnt)
  64.  
  65.     public    _checksum
  66. _checksum proc    near
  67.     push    bp
  68.     mov    bp,sp
  69.     push    si
  70.     push    bx
  71.     push    cx
  72.     push    dx
  73.     push    DS
  74.         lds     si,[bp+4+0]        ; seg:offset of data to be checked
  75.     mov     cx,[bp+4+4]        ; cx = cnt
  76.     mov    bl,cl            ; save low order for odd byte length
  77.     shr     cx,1            ; group into words
  78.     xor    dx,dx            ; set checksum to 0
  79.         cld
  80.     jcxz    chk3            ; z = no words to do
  81.         clc
  82. chk1:    lodsw                ; add words
  83.     adc    dx,ax            ; with carry
  84.     loop    chk1
  85.                     ; resolve remainder
  86. chk2:    adc     dx,0
  87.         jc    chk2
  88. chk3:    and    bl,1
  89.     jz    chk5            ; z = even number of bytes
  90.         xor     ah,ah
  91.     lodsb                ; read odd byte + 0
  92.         add     dx,ax
  93. chk4:    adc     dx,0
  94.     jc    chk4
  95. chk5:    mov    ax,dx            ; result into ax
  96.         or      ax,ax            ; 0?
  97.     jnz    chk6            ; nz = no
  98.         mov     ax,0ffffh        ; then make it be -1
  99. chk6:    POP    DS
  100.     pop    dx
  101.     pop    cx
  102.     pop    bx
  103.     pop    si
  104.     pop    bp
  105.     ret
  106. _checksum endp
  107.  
  108. ;  ntohl(longword x)    32 bit network (big endian) to host (little endian)
  109. ;  htonl(longword x)    32 bit host (little endian) to network (big endian)
  110. ;  intel(longword x)
  111. ;  Reverse order of 4 byte groups between big and little endian forms
  112. ;
  113.     public    _intel, _ntohl, _htonl
  114.  
  115. _intel    proc    near
  116. _ntohl    equ    this byte
  117. _htonl    equ    this byte
  118.     push    bp
  119.     mov    bp,sp
  120.     mov    ax,[bp+4+2]        ; high order incoming, low outgoing
  121.     mov    dx,[bp+4+0]        ; low order incoming, high outgoing
  122.     xchg    al,ah
  123.     xchg    dl,dh
  124.     pop    bp
  125.     ret
  126. _intel    endp
  127.  
  128. ;  ntohs(word x)    16 bit network (big endian) to host (little endian)
  129. ;  htons(word x)    16 bit host (little endian) to network (big endian)
  130. ;  intel16(word x)
  131. ;  Reverse order of 2 byte groups between big and little endian forms
  132.     public    _intel16, _ntohs, _htons
  133. _intel16 proc    near
  134. _ntohs    equ    this byte
  135. _htons    equ    this byte
  136.     push    bp
  137.     mov    bp,sp
  138.     mov    ax,[bp+4+0]
  139.     xchg    al,ah
  140.     pop    bp
  141.     ret
  142. _intel16 endp
  143.  
  144.  
  145. ; int ourmod(int top, int bottom)
  146. ; Perform modulo function on 16 bit quantities
  147.     public    _ourmod
  148. _ourmod    proc    near
  149.     push    bp
  150.     mov    bp,sp
  151.     push    bx
  152.     mov    ax,[bp+4+0]        ; top number
  153.     mov    bx,[bp+4+2]        ; bottom number (radix)
  154.     xor    dx,dx
  155.     or    bx,bx            ; bottom is zero?
  156.     jz    ourmod1            ; z = yes, return zero
  157.     div    bx
  158. ourmod1:mov    ax,dx            ; return remainder
  159.     pop    bx
  160.     pop    bp
  161.     ret
  162. _ourmod    endp
  163.  
  164. ; int ourdiv(int top, int bottom)
  165. ; Perform 16 bit integer division
  166.     public    _ourdiv
  167. _ourdiv    proc    near
  168.     push    bp
  169.     mov    bp,sp
  170.     push    bx
  171.     mov    ax,[bp+4+0]        ; top
  172.     mov    bx,[bp+4+2]        ; bottom
  173.     xor    dx,dx
  174.     or    bx,bx            ; divide by zero?
  175.     jz    outdiv1            ; z = yes, divide by one
  176.     div    bx
  177. outdiv1:pop    bx
  178.     pop    bp            ; quotient is returned in ax
  179.     ret
  180. _ourdiv    endp
  181.  
  182. ; int ourlmod(long top, int bottom)
  183. ; Perform 32 bit integer modulo function
  184.     public    _ourlmod
  185. _ourlmod proc    near
  186.     push    bp
  187.     mov    bp,sp
  188.     push    bx
  189.     mov    ax,[bp+4+0]        ; top lower 16 bits
  190.     mov    dx,[bp+4+2]        ; top upper 16 bits
  191.     mov    bx,[bp+4+4]        ; bottom
  192.     or    bx,bx            ; zero?
  193.     jz    outlmo1            ; z = yes divide by 2^16 and quit
  194.     div    bx
  195. outlmo1:mov    ax,dx            ; return remainder in ax
  196.     pop    bx
  197.     pop    bp
  198.     ret
  199. _ourlmod endp
  200.  
  201. ; int ourldiv(long top, int bottom)
  202. ; Perform 32 bit integer division of 32 bit quotient by 16 bit divisor
  203.     public    _ourldiv
  204. _ourldiv proc    near
  205.     push    bp
  206.     mov    bp,sp
  207.     push    bx
  208.     mov    ax,[bp+4+0]        ; top lower 16 bits
  209.     mov    dx,[bp+4+2]        ; top upper 16 bits
  210.     mov    bx,[bp+4+4]        ; bottom
  211.     cmp    dx,bx            ; about to overflow?
  212.     jae    ourldiv1        ; ae = yes, return 0xffffh
  213.     div    bx
  214.     xor    dx,dx            ; clear remainder (high order ret)
  215.     pop    bx
  216.     pop    bp            ; quotient is returned in dx:ax
  217.     ret
  218. ourldiv1:mov    ax,0ffffh        ; overflow indication
  219.     xor    dx,dx            ; clear high order
  220.     pop    bx
  221.     pop    bp
  222.     ret
  223. _ourldiv endp
  224.  
  225. ; long ourlmul(long top, int bottom)
  226. ; Perform 32 bit integer multiplication of 32 bit multiplicand by 16 bit mult
  227.     public    _ourlmul
  228. _ourlmul proc    near
  229.     push    bp
  230.     mov    bp,sp
  231.     push    bx
  232.     push    cx
  233.     mov    ax,[bp+4+2]        ; top upper 16 bits
  234.     mov    bx,[bp+4+4]        ; bottom
  235.     mul    bx
  236.     mov    cx,ax            ; save product (no overflow noted)
  237.     mov    ax,[bp+4+0]        ; top lower 16 bits
  238.     mul    bx
  239.     adc    dx,cx            ; new upper 16 bits
  240.     pop    cx
  241.     pop    bx
  242.     mov    sp,bp
  243.     pop    bp            ; long product is returned in dx:ax
  244.     ret
  245. _ourlmul endp
  246.  
  247. ; void * bcopy(src, dest, count)
  248. ; void *dest, *src;
  249. ; size_t count;
  250. ; copy count bytes from src to dest
  251.     public    _bcopy
  252. _bcopy proc    near
  253.     push    bp
  254.     mov    bp,sp
  255.     push    es
  256.     push    si
  257.     push    di
  258.     push    cx
  259.     mov    ax,ds            ; set to same data segment
  260.     mov    es,ax
  261.     mov    si,[bp+4+0]        ; offset of source
  262.     mov    di,[bp+4+2]        ; offset of destination
  263.     mov    cx,[bp+4+4]        ; count
  264.     cld
  265.     push    di            ; push dest address for return
  266.     jcxz    bcopy2            ; z = nothing to copy
  267.     or    si,si            ; is source NULL?
  268.     jz    bcopy2            ; z = yes, don't do a thing
  269.     or    di,di            ; is destination NULL?
  270.     jz    bcopy2            ; z = yes, don't do a thing
  271.     cmp    si,di            ; is source after destination?
  272.     ja    bcopy1            ; a = yes, no overlap problem
  273.     je    bcopy2            ; e = same place, do nothing
  274.     add    di,cx            ; start at the ends
  275.     dec    di
  276.     add    si,cx
  277.     dec    si
  278.     std                ; work backward
  279. bcopy1:    rep    movsb
  280. bcopy2:    pop    ax            ; recover return destination
  281.     cld
  282.     pop    cx
  283.     pop    di
  284.     pop    si
  285.     pop    es
  286.     mov    sp,bp
  287.     pop    bp
  288.     ret
  289. _bcopy endp
  290.  
  291. ; void * bcopyff(src, dest, count)
  292. ; void * FAR dest, * FAR src;
  293. ; size_t count;
  294. ; copy count bytes from src to dest
  295.     public    _bcopyff
  296. _bcopyff proc    near
  297.     push    bp
  298.     mov    bp,sp
  299.     push    es
  300.     push    ds
  301.     push    si
  302.     push    di
  303.     push    cx
  304.     push    dx
  305.     lds    si,dword ptr [bp+4+0]    ; source
  306.     les    di,dword ptr [bp+4+4]    ; destination
  307.     mov    cx,[bp+4+8]        ; count
  308.     cld
  309.     jcxz    bcopyff2        ; z = nothing to copy
  310.     mov    ax,ds
  311.     mov    dx,es
  312.     or    ax,ax            ; is source NULL?
  313.     jz    bcopyff2        ; z = yes, don't do a thing
  314.     or    dx,dx            ; is destination NULL?
  315.     jz    bcopyff2        ; z = yes, don't do a thing
  316.     cmp    ax,dx            ; is source seg after destination?
  317.     ja    bcopyff1        ; a = yes, no overlap problem
  318.     jb    bcopyff3        ; b = no, no overlap the other way
  319.     cmp    si,di            ; is source offset after destination?
  320.     ja    bcopyff1        ; a = yes, no overlap problem
  321.     je    bcopyff2        ; e = same place, do nothing
  322. bcopyff3:add    di,cx            ; start at the ends
  323.     dec    di
  324.     add    si,cx
  325.     dec    si
  326.     std                ; work backward
  327. bcopyff1:rep    movsb
  328. bcopyff2:xor    ax,ax            ; say null destination
  329.     cld
  330.     pop    dx
  331.     pop    cx
  332.     pop    di
  333.     pop    si
  334.     pop    ds
  335.     pop    es
  336.     mov    sp,bp
  337.     pop    bp
  338.     ret
  339. _bcopyff endp
  340.  
  341.  
  342. ; void * memset(dest, c, count)
  343. ; void *dest;
  344. ; char c;
  345. ; size_t count;
  346. ; Store count copies of byte c in destination area dest
  347.     public    _memset
  348. _memset    proc    near
  349.     push    bp
  350.     mov    bp,sp
  351.     push    es
  352.     push    di
  353.     push    cx
  354.     mov    ax,ds            ; setup data segment
  355.     mov    es,ax
  356.     mov    di,[bp+4+0]        ; offset of destination
  357.     or    di,di            ; is it NULL?
  358.     jz    memset1            ; z = yes, don't do a thing
  359.     push    di            ; save dest for return
  360.     mov    al,[bp+4+2]        ; byte of character c
  361.     mov    ah,al
  362.     mov    cx,[bp+4+4]        ; count
  363.     jcxz    memset1            ; z = do nothing
  364.     cld
  365.     shr    cx,1
  366.     jnc    memset2
  367.     stosb
  368. memset2:rep    stosw
  369.     pop    ax            ; return pointer to destination
  370. memset1:pop    cx
  371.     pop    di
  372.     pop    es
  373.     mov    sp,bp
  374.     pop    bp
  375.     ret
  376. _memset    endp
  377.  
  378. ; Allocate size bytes from DOS free memory.
  379. ; void FAR * malloc(size_t size)
  380. ; Returns FAR pointer in dx:ax, or 0L if failure. Size is an unsigned int.
  381.     public    _malloc
  382. _malloc    proc    near
  383.     push    bp
  384.     mov    bp,sp
  385.     push    bx
  386.     push    cx
  387.     mov    bx,[bp+4+0]        ; bytes wanted
  388.     add    bx,15            ; round up
  389.     mov    cl,4
  390.     shr    bx,cl            ; convert to # of paragraphs
  391.     mov    cx,bx            ; remember quantity wanted
  392.     mov    ah,allocmem        ; DOS memory allocator
  393.     int    dos            ; returns segment in ax
  394.     jc    malloc1            ; c = fatal error
  395.     cmp    cx,bx            ; paragraphs wanted vs delivered
  396.     je    malloc2            ; e = got the block
  397.     push    es            ; insufficient, return it
  398.     mov    es,ax            ; identify the block
  399.     mov    ah,freemem        ; free the unwanted block
  400.     int    dos
  401.     pop    es
  402. malloc1:xor    ax,ax            ; return 0L on failure
  403. malloc2:mov    dx,ax            ; segment
  404.     xor    ax,ax            ; offset
  405.     pop    cx
  406.     pop    bx
  407.     pop    bp
  408.     ret
  409. _malloc    endp
  410.  
  411. ; Free a block of memory allocated from the DOS memory pool.
  412. ; void free(FAR * memblock);
  413.     public    _free
  414. _free    proc    near
  415.     push    bp
  416.     mov    bp,sp
  417.     push    ax
  418.     push    es
  419.     mov    ax,[bp+4+2]        ; get high order (segment) arg
  420.     or    ax,ax            ; NULL?
  421.     jz    free1            ; z = yes, leave it alone
  422.     mov    es,ax            ; identify the block
  423.     mov    ah,freemem        ; free the unwanted block
  424.     int    dos
  425. free1:    pop    es
  426.     pop    ax
  427.     pop    bp
  428.     ret
  429. _free    endp
  430.  
  431. ; Copy bytes from src buffer to dest buffer. Src has srclen bytes present,
  432. ; dest buffer can hold destlen bytes. Convert CR NUL to CR en route.
  433. ; Report count of bytes destcnt placed in dest, last read byte in last_read,
  434. ; and return int bytes read from source. s->last_read is to track CR NUL
  435. ; across arriving packets.
  436. ; int 
  437. ; destuff(FAR * src, srclen, FAR * dest, destlen, * destcnt, * last_read)
  438. ;        0    4             6     10         12           14
  439.     public    _destuff
  440. _destuff proc    near
  441.     push    bp
  442.     mov    bp,sp
  443.     mov    al,_dobinary        ; save as stack word so we can use
  444.     xor    ah,ah            ; ds and es for far pointers
  445.     push    ax            ; [bp-2] temp storage of _dobinary
  446.     push    es
  447.     push    bx
  448.     push    cx
  449.     push    dx
  450.     push    si
  451.     push    di
  452.     push    ds
  453.     mov    cx,[bp+4+4]        ; srclen
  454.     mov    ax,[bp+4+10]        ; destlen
  455.     cmp    ax,cx            ; destlen > srclen?
  456.     ja    destuf1            ; a = yes, use srclen
  457.     mov    cx,ax            ; use destlen as the shorter
  458. destuf1:lds    si,dword ptr [bp+4+0]    ; src
  459.     les    di,dword ptr [bp+4+6]    ; dest
  460.     xor    ax,ax            ; bytes read
  461.     xor    dx,dx            ; bytes written
  462.     mov    bx,es            ; check for NULL
  463.     or    bx,bx            ; NULL?
  464.     jz    destufx            ; z = yes, return 0
  465.     mov    bx,ds            ; check for NULL
  466.     or    bx,bx
  467.     jz    destufx            ; z = NULL
  468.     push    ds
  469.     mov    bx,DGROUP        ; get ds reg back to Dgroup for a sec
  470.     mov    ds,bx
  471.     mov    bx,[bp+4+14]        ; &s->last_read, last read byte
  472.     mov    ah,ds:[bx]        ; last read byte
  473.     pop    ds
  474.     jcxz    destufx            ; z = empty string, return -1
  475.     cld
  476.     mov    bx,[bp+4+4]        ; srclen
  477. destuf3:lodsb                ; read source
  478.     dec    bx            ; chars left in source
  479.     or    al,al            ; NUL?
  480.     jnz    destuf4            ; nz = no
  481.     cmp    ah,CR            ; last read was Carriage return?
  482.     jne    destuf4            ; ne = no
  483.     cmp    word ptr [bp-2],0    ; doing binary mode (_dobinary)?
  484.     je    destuf5            ; e = no, NVT-ASCII, skip NUL
  485. destuf4:stosb                ; write destination
  486.     inc    dx            ; chars written to dest
  487. destuf5:mov    ah,al            ; remember last read byte
  488.     or    bx,bx            ; any source left?
  489.     jz    destuf6            ; z = no, stop now
  490.     loop    destuf3
  491.  
  492. destuf6:mov    cx,[bp+4+4]        ; srclen
  493.     sub    cx,bx            ; return count of bytes read
  494. destufx:pop    ds            ; restore addressablity
  495.     mov    bx,[bp+4+14]        ; &s->last_read
  496.     mov    ds:[bx],ah        ; store last read character
  497.     mov    bx,[bp+4+12]        ; &destcnt, count of bytes written
  498.     mov    ds:[bx],dx
  499.     mov    ax,cx            ; return count of bytes consumed
  500.     pop    di
  501.     pop    si
  502.     pop    dx
  503.     pop    cx
  504.     pop    bx
  505.     pop    es
  506.     add    sp,2            ; temp storage area
  507.     pop    bp
  508.     ret
  509. _destuff endp
  510.  
  511.  
  512. ; int fstchr(const char FAR * p, word len, byte c)
  513. ; Finds first occurence of unsigned byte in low part of c and returns
  514. ; the number of bytes preceeding it in the buffer, or len if not found.
  515.     public    _fstchr
  516. _fstchr proc    near
  517.     push    bp
  518.     mov    bp,sp
  519.     push    es
  520.     push    bx
  521.     push    cx
  522.     push    di
  523.     les    di,dword ptr [bp+4+0]    ; Far string address
  524.     mov    bx,es            ; check for NULL
  525.     mov    ax,-1            ; error return value
  526.     or    bx,bx            ; NULL?
  527.     jz    fstchr1            ; z = yes, return -1
  528.     mov    bx,di            ; remember starting offset
  529.     mov    cx,[bp+4+4]        ; number of bytes to examine
  530.     jcxz    fstchr1            ; z = empty string, return -1
  531.     mov    ax,[bp+4+6]        ; pattern is in al
  532.     cld
  533.     repne    scasb
  534.     mov    ax,di            ; ending place
  535.     jne    fstchr2            ; ne = not found
  536.     dec    ax            ; minus auto inc of rep
  537. fstchr2:sub    ax,bx            ; minus starting offset
  538. fstchr1:pop    di
  539.     pop    cx
  540.     pop    bx
  541.     pop    es
  542.     pop    bp
  543.     ret
  544. _fstchr endp
  545.  
  546. ;  Timer routines - use set_*timeout to receive a clock value which
  547. ;                   can later be tested by calling chk_timeout with
  548. ;                   that clock value to determine if a timeout has
  549. ;                   occurred.  chk_timeout returns 0 if NOT timed out.
  550. ;  Usage:   long set_timeout( int seconds );
  551. ;           long set_ttimeout( int bios_ticks );
  552. ;           int chk_timeout( long value );
  553. ;
  554. ;  (c) 1990 University of Waterloo,
  555. ;           Faculty of Engineering,
  556. ;           Engineering Microcomputer Network Development Office
  557. ;  Rewritten by Joe Doupnik, Jan 1994
  558. ;
  559. ; Return Bios clock ticks at argument Bios ticks from the present
  560.     public    _set_ttimeout
  561. _set_ttimeout proc    near
  562.     push    bp
  563.     mov    bp,sp
  564.     push    es
  565.     push    bx
  566.     push    cx
  567.     xor     ax,ax
  568.         mov     es,ax
  569. _set_ttimeout1:
  570.     mov    cx,es:[biosclk+0]
  571.     mov    dx,es:[biosclk+2]
  572.     in    al,61h            ; pause
  573.     in    al,61h
  574.     mov    ax,es:[biosclk+0]
  575.     mov    bx,es:[biosclk+2]
  576.     cmp    ax,cx
  577.     jne    _set_ttimeout1        ; ne = time jumped
  578.     cmp    bx,dx
  579.     jne    _set_ttimeout1        ; ne = time jumped
  580.     mov    ax,[bp+4+0]
  581.     cwd                ; sign extend ax to dx
  582.         add     ax,cx
  583.         adc     dx,bx
  584.     pop    cx            ; end critical section
  585.     pop    bx
  586.     pop    es
  587.     pop    bp
  588.     ret
  589. _set_ttimeout endp
  590.  
  591. ; Return Bios clock ticks at argument seconds from the present
  592.     public    _set_timeout
  593. _set_timeout proc near
  594.     push    bp
  595.     mov    bp,sp
  596.     push    es
  597.     push    cx
  598.     xor    ax,ax            ; reference low memory
  599.     mov    es,ax
  600.     mov    ax,[bp+4+0]        ; seconds
  601.     xor    dx,dx
  602.     mov    cx,1165
  603.     mul    cx            ; 1165/64 = 18.203...
  604.     mov    cx,6
  605. tmp:    shr    dx,1
  606.     rcr    ax,1
  607.     loop    tmp
  608.     push    ax
  609.     push    dx
  610.  
  611. _set_timeout1:
  612.     mov    cx,es:[biosclk+0]
  613.     mov    dx,es:[biosclk+2]
  614.     in    al,61h
  615.     in    al,61h
  616.     mov    ax,es:[biosclk+0]
  617.     mov    bx,es:[biosclk+2]
  618.     cmp    ax,cx
  619.     jne    _set_timeout1        ; time jumped
  620.     cmp    bx,dx
  621.     jne    _set_timeout1        ; time jumped
  622.     pop    dx
  623.     pop    ax
  624.     add    ax,cx
  625.     adc    dx,bx
  626.     pop    cx            ; end critical section
  627.     pop    es
  628.     pop    bp
  629.     ret
  630. _set_timeout    endp
  631.  
  632. ; Return 1 for timed-out if argument Bios clock ticks is older (smaller) 
  633. ; than the current Bios clock time, else return 0 for not-timed-out.
  634.     public    _chk_timeout
  635. _chk_timeout    proc near
  636.     push    bp
  637.     mov    bp,sp
  638.     push    cx
  639.     push    es
  640.     xor    ax,ax
  641.     mov    es,ax
  642. _chk_timeout1:
  643.     mov    cx,es:[biosclk+0]
  644.     mov    dx,es:[biosclk+2]
  645.     in    al,61h
  646.     in    al,61h
  647.     mov    ax,es:[biosclk+0]
  648.     mov    bx,es:[biosclk+2]
  649.     cmp    ax,cx
  650.     jne    _chk_timeout1        ; time jumped
  651.     cmp    bx,dx
  652.     jne    _chk_timeout1        ; time jumped
  653.  
  654.     pop    es
  655.     mov    ax,[bp+4+0]        ; timeout value
  656.     mov    dx,[bp+4+2]
  657.     cmp    dx,bx            ; if timeout < clock, has expired
  658.         jb    ret_tru            ; b = timed out
  659.     ja    ret_fal            ; a = not timed out
  660.     cmp    ax,cx
  661.         jb    ret_tru            ; b = timed out
  662.                     ; may have gone over by one day
  663.     sub    ax,LO_MAX
  664.     sbb    dx,HI_MAX
  665.     jc    ret_fal            ; c = nope, timeout is today
  666.                     ; test timeout new values
  667.     cmp    dx,bx
  668.     jb    ret_tru            ; b = timed out
  669.     ja    ret_fal            ; a = not timed out
  670.     cmp    ax,cx
  671.     jae    ret_fal            ; ae = not timed out
  672. ret_tru:mov    ax,1            ; say have timed out
  673.     pop    cx
  674.     pop    bp
  675.     ret
  676.  
  677. ret_fal:xor    ax,ax            ; say have not timed out
  678.     pop    cx
  679.     pop    bp
  680.     ret
  681. _chk_timeout    endp
  682.  
  683. ; void _chkstk()
  684. ; Stack checker
  685. ; {
  686. ;  ;
  687. ; }
  688.     public    __chkstk, __aNchkstk
  689. __chkstk proc    near            ; MSC v5.1
  690. __aNchkstk equ    this byte        ; MSC v6.00
  691.     pop    bx            ; pop return address
  692.     sub    sp,ax            ; down adjust stack pointer
  693.     jmp    bx            ; return the no-stack way
  694. __chkstk endp
  695.  
  696. ; Check real console for ^C. Return 1 if so, else do nothing and return 0.
  697. ; Do nothing and return 0 if not at DOS level or stdin is not a device.
  698.     public    _chkcon
  699. _chkcon    proc    near
  700.     push    bx
  701.     push    dx
  702.     push    es
  703.     mov    bx,seg data
  704.     mov    es,bx
  705.     cmp    es:flags.cxzflg,'C'    ; ^C seen ?
  706.     pop    es
  707.     je    chkcon1            ; e = yes
  708.     cmp    _doslevel,0        ; outside DOS level?
  709.     je    chkcon2            ; e = yes, do nothing here
  710.     test    _tcpflag,2         ; running on Int 8h?
  711.     jnz    chkcon2            ; nz = yes
  712.     xor    bx,bx            ; handle 0 is stdin
  713.     xor    al,al            ; get device info
  714.     mov    ah,ioctl
  715.     int    dos            ; is stdin a device, not a disk file?
  716.     rcl    dl,1            ; put ISDEV bit into the carry bit
  717.     jnc    chkcon2            ; nc, a disk file so do not read here
  718.     mov    dl,0ffh
  719.     mov    ah,dconio        ; read console
  720.     int    dos
  721.     jz    chkcon2            ; z = nothing there
  722.     and    al,1fh            ; make char a control code
  723.     cmp    al,'C'-40h        ; Control-C?
  724.     jne    chkcon2            ; ne = no
  725. chkcon1:mov    ax,1            ; return 1, ^C sensed
  726.     pop    dx
  727.     pop    bx
  728.     ret
  729. chkcon2:xor    ax,ax            ; return 0, no ^C
  730.     pop    dx
  731.     pop    bx
  732.     ret
  733. _chkcon    endp
  734.  
  735. ; Microsoft C v7.0 direct support. Shift left dx:ax by cx. No C calling conv.
  736. ; Long shift left
  737.     public    __aNlshl
  738. __aNlshl proc    near
  739.     jcxz    lshift2            ; z = no shift
  740. lshift1:shl    ax,1
  741.     rcl    dx,1
  742.     loop    lshift1
  743. lshift2:ret
  744. __aNlshl endp
  745.  
  746. ; Microsoft C v7.0 direct support. Shift rgt dx:ax by cx. No C calling conv.
  747. ; Unsigned long shift right
  748.     public    __aNulshr
  749. __aNulshr proc    near
  750.     jcxz    rshift2            ; z = no shift
  751. rshift1:shr    dx,1
  752.     rcr    ax,1
  753.     loop    rshift1
  754. rshift2:ret
  755. __aNulshr endp
  756.  
  757. ; void 
  758. ; outch(char ch)
  759. ; Sends character to the screen via the msgbuf buffer if operating at
  760. ; interrupt level, or via DOS if operating at task level.
  761.     public    _outch
  762. _outch    proc    near
  763.     push    bp
  764.     mov    bp,sp
  765.     push    ax
  766.     cmp    _display_mode,0        ; quiet screen?
  767.     je    outch3            ; e = yes
  768.     mov    ax,[bp+4]        ; get the character
  769.     cmp    _doslevel,0        ; at DOS task level?
  770.     je    outch1            ; e = no
  771.     test    _tcpflag,2         ; running on Int 8h?
  772.     jnz    outch1            ; nz = yes
  773.     mov    ah,conout        ; use DOS
  774.     push    dx
  775.     mov    dl,al
  776.     int    dos
  777.     pop    dx
  778.     jmp    short outch3
  779. outch1:    cmp    _msgcnt,MSGBUFLEN    ; is buffer filled?
  780.     jae    outch3            ; ae = yes, discard this byte
  781.     push    bx
  782.     mov    bx,_msgcnt
  783.     mov    _msgbuf[bx],al
  784.     inc    _msgcnt
  785.     pop    bx
  786. outch3:    pop    ax
  787.     mov    sp,bp
  788.     pop    bp
  789.     ret
  790. _outch    endp
  791.  
  792.  
  793. ; void 
  794. ; outsn(char * string, int count)
  795. ; display counted string
  796.     public    _outsn
  797. _outsn    proc    near
  798.     push    bp
  799.     mov    bp,sp
  800.     push    ax
  801.     push    si
  802.     mov    si,[bp+4]        ; string address
  803.     mov    cx,[bp+4+2]        ; string length
  804.     cld
  805. outsn1:    lodsb
  806.     or    al,al
  807.         jz      outsn2
  808.     push    ax            ; push arg
  809.         call    _outch
  810.     pop    ax            ; clean stack
  811.     loop    outsn1
  812. outsn2:    pop    si
  813.     pop    ax
  814.     mov    sp,bp
  815.     pop    bp
  816.     ret
  817. _outsn    endp
  818.  
  819. ; void 
  820. ; outs(char * string)
  821. ; display asciiz string
  822.     public    _outs
  823. _outs    proc    near
  824.     push    bp
  825.     mov    bp,sp
  826.     push    ax
  827.     push    si
  828.     mov    si,[bp+4]        ; asciiz string address
  829.     cld
  830. outs1:    lodsb
  831.         or      al,al            ; terminator ?
  832.     jz     outs2            ; z = yes
  833.     push    ax            ; push arg
  834.     call    _outch
  835.     pop    ax            ; clean stack
  836.     jmp    short outs1
  837. outs2:    pop    si
  838.     pop    ax
  839.     mov    sp,bp
  840.     pop    bp
  841.     ret
  842. _outs    endp
  843.  
  844. ; void
  845. ; outhex(char c)
  846. ; display char in hex
  847.     public _outhex
  848. _outhex    proc    near
  849.     push    bp
  850.     mov    bp,sp
  851.     push    ax
  852.         mov     ax,[bp+4]        ; incoming character
  853.     push    cx
  854.         mov     cl,4
  855.         shr     al,cl
  856.     pop    cx
  857.         call    outh
  858.         mov     ax,[bp+4]
  859.         call    outh
  860.     pop    ax
  861.     mov    sp,bp
  862.     pop    bp
  863.     ret
  864.  
  865. ; worker for outhex
  866. outh    proc    near
  867.     and     al,0fh
  868.         cmp     al,9
  869.         jbe     outh1
  870.         add     al,'A' - '9' - 1
  871. outh1:    add     al,'0'
  872.         push    ax
  873.         call    _outch
  874.         pop     ax
  875.         ret
  876. outh    endp
  877. _outhex    endp
  878.  
  879. ; output a string of hex chars
  880. ; void
  881. ; outhexes(char * string, int count )
  882.     public    _outhexes
  883. _outhexes proc    near
  884.     push    bp
  885.     mov    bp,sp
  886.     push    ax
  887.     push    cx
  888.     push    si            ; preserve such things
  889.     mov    si,[bp+4]        ; get string pointer
  890.     mov    cx,[bp+4+2]        ; get char count
  891.     jcxz    outhexs2        ; z = nothing
  892.     cld
  893. outhexs1:lodsb                ; read a byte
  894.     push    cx            ; save loop counter
  895.     push    ax
  896.     call    _outhex            ; display as hex pair
  897.     add    sp,2            ; clean stack
  898.     pop    cx
  899.     loop    outhexs1        ; do count's worth
  900. outhexs2:pop    si
  901.     pop    cx
  902.     pop    ax
  903.     mov    sp,bp
  904.     pop    bp
  905.     ret
  906. _outhexes endp
  907.  
  908. ; void
  909. ; outdec(int c)
  910. ; display int in decimal
  911.     public    _outdec
  912. _outdec    proc    near
  913.     push    bp
  914.     mov    bp,sp
  915.     push    ax
  916.     push    cx
  917.     push    dx
  918.     mov    ax,[bp+4]
  919.     or    ax,ax        ; negative?
  920.     jge    outdec1        ; ge = no
  921.     mov    dl,'-'        ; display minus sign
  922.     push    dx        ; push arg
  923.     call    _outch
  924.     add    sp,2        ; clean stack
  925.     neg    ax        ; make positive
  926. outdec1:call    outdec2        ; do display recursively
  927.     pop    dx
  928.     pop    cx
  929.     pop    ax
  930.     mov    sp,bp
  931.     pop    bp
  932.     ret
  933.  
  934. outdec2    proc    near        ; internal worker, ax has input value
  935.     xor    dx,dx        ; clear high word of numerator
  936.     mov    cx,10
  937.     div    cx        ; (ax / cx), remainder = dx, quotient = ax
  938.     push    dx        ; save remainder for outputting later
  939.     or    ax,ax        ; any quotient left?
  940.     jz    outdec3        ; z = no
  941.     call    outdec2        ; yes, recurse
  942.     jmp    short outdec3    ; present to avoid MASM bug
  943. outdec3:
  944.     pop    dx        ; get remainder
  945.     add    dl,'0'        ; make digit printable
  946.     push    dx        ; push arg for _outch
  947.     call    _outch        ; display the char
  948.     pop    dx        ; clean stack
  949.     ret
  950. outdec2    endp
  951.  
  952. _outdec    endp
  953. filler    db    64 dup (0)
  954. _TEXT    ends
  955.         end
  956.