home *** CD-ROM | disk | FTP | other *** search
/ Zodiac Super OZ / MEDIADEPOT.ISO / FILES / 13 / FREELI20.ZIP / 386lib2.asx < prev    next >
Text File  |  1996-07-01  |  64KB  |  2,409 lines

  1. ~~~C_STR1
  2. Ideal
  3.  
  4. Public      strlen,strcpy,strcat,strcmp
  5.  
  6. Model Tiny
  7. CodeSeg
  8. P386
  9.  
  10. ;****************** strlen() -- Get length of string
  11. ;int strlen(char *strp);
  12.  
  13. strp        equ bp+4
  14.  
  15. Proc        strlen
  16.  
  17.             push bp                 ;Set up stack frame
  18.             mov bp,sp
  19.             push si                 ;Save SI
  20.  
  21.             mov si,[strp]           ;SI = string pointer
  22.  
  23. p1_loop:    lodsb                   ;Load char
  24.             test al,al              ;Loop while not zero
  25.             jnz p1_loop
  26.  
  27.             sub si,[strp]           ;AX = length
  28.             dec si
  29.             xchg ax,si
  30.  
  31.             pop si                  ;Restore SI
  32.             pop bp                  ;Delete stack frame
  33.             ret 2                   ;Return
  34.  
  35. EndP        strlen
  36.  
  37. ;****************** strcpy() -- Copy a string
  38. ;void strcpy(char *str1, char *str2);
  39.  
  40. str1        equ bp+6
  41. str2        equ bp+4
  42.  
  43. Proc        strcpy
  44.  
  45.             push bp                 ;Set up stack frame
  46.             mov bp,sp
  47.             pusha                   ;Save all registers
  48.  
  49.             mov si,[str2]           ;SI = source
  50.             mov di,[str1]           ;DI = destination
  51.  
  52. p2_loop:    lodsb                   ;Load char
  53.             mov [di],al             ;Store char
  54.             inc di
  55.             test al,al              ;Loop while not zero
  56.             jnz p2_loop
  57.  
  58.             popa                    ;Restore registers
  59.             pop bp                  ;Delete stack frame
  60.             ret 4                   ;Return
  61.  
  62. EndP        strcpy
  63.  
  64. ;****************** strcat() -- Concatenate strings
  65. ;void strcat(char *str1, char *str2);
  66.  
  67. str1        equ bp+6
  68. str2        equ bp+4
  69.  
  70. Proc        strcat
  71.  
  72.             push bp                 ;Set up stack frame
  73.             mov bp,sp
  74.             pusha                   ;Save all registers
  75.  
  76.             mov si,[str1]           ;SI = destination
  77.  
  78. p3_cloop:   lodsb                   ;Load char
  79.             test al,al              ;Loop while not zero
  80.             jnz p3_cloop
  81.  
  82.             mov di,si               ;DI = destination
  83.             mov si,[str2]           ;SI = source
  84.             dec di
  85.  
  86. p3_loop:    lodsb                   ;Load char
  87.             mov [di],al             ;Store char
  88.             inc di
  89.             test al,al              ;Loop while not zero
  90.             jnz p3_loop
  91.  
  92.             popa                    ;Restore registers
  93.             pop bp                  ;Delete stack frame
  94.             ret 4                   ;Return
  95.  
  96. EndP        strcat
  97.  
  98. ;****************** strcmp() -- Compare strings
  99. ;void strcmp(char *str1, char *str2);
  100.  
  101. str1        equ bp+6
  102. str2        equ bp+4
  103.  
  104. Proc        strcmp
  105.  
  106.             push bp                 ;Set up stack frame
  107.             mov bp,sp
  108.             push si di              ;Save registers
  109.  
  110.             mov si,[str1]           ;SI = source
  111.             mov di,[str2]           ;DI = destination
  112.  
  113. p4_loop:    lodsb                   ;Load char 1
  114.             mov ah,[di]             ;Load char 2
  115.             inc di
  116.             cmp al,ah               ;Not equal?
  117.             jne p4_nope
  118.             test al,al              ;Loop while not zero
  119.             jnz p4_loop
  120.  
  121.             xor ax,ax               ;Equal, return 0
  122. p4_done:    pop di si               ;Restore registers
  123.             pop bp                  ;Delete stack frame
  124.             ret 4                   ;Return
  125.  
  126. p4_nope:    sub al,ah               ;Not equal, return difference
  127.             cbw                     ;in first unequal position
  128.             jmp p4_done
  129.  
  130. EndP        strcmp
  131.  
  132. End
  133.  
  134. ~~~C_STR2
  135. Ideal
  136.  
  137. Extrn       strlen:near
  138. Public      strchr,strstr
  139.  
  140. Model Tiny
  141. CodeSeg
  142. P386
  143.  
  144. ;****************** strchr() -- Search string for char
  145. ;int strchr(char *strp, int chr);
  146.  
  147. strp        equ bp+6
  148. chr         equ bp+4
  149.  
  150. Proc        strchr
  151.  
  152.             push bp                 ;Set up stack frame
  153.             mov bp,sp
  154.             push si                 ;Save SI
  155.  
  156.             mov si,[strp]           ;SI = string pointer
  157.             mov ah,[chr]            ;AH = char
  158.  
  159. p1_loop:    lodsb                   ;Load char
  160.             test al,al              ;Null, not found
  161.             jz p1_nope
  162.             cmp al,ah               ;Loop while not equal
  163.             jne p1_loop
  164.  
  165.             sub si,[strp]           ;AX = position of char
  166.             dec si
  167.             xchg ax,si
  168.  
  169. p1_done:    pop si                  ;Restore SI
  170.             pop bp                  ;Delete stack frame
  171.             ret 4                   ;Return
  172.  
  173. p1_nope:    mov ax,-1               ;Not found, return -1
  174.             jmp p1_done
  175.  
  176. EndP        strchr
  177.  
  178. ;****************** strstr() -- Search string for substring
  179. ;int strstr(char *strp, char *subp);
  180.  
  181. strp        equ bp+6
  182. subp        equ bp+4
  183.  
  184. Proc        strstr
  185.  
  186.             push bp                 ;Set up stack frame
  187.             mov bp,sp
  188.             push es                 ;Save registers
  189.             pusha
  190.  
  191.             push ds                 ;ES = DS
  192.             pop es
  193.  
  194.             mov si,[strp]           ;SI = string pointer
  195.             mov bx,[subp]           ;BX = substring pointer
  196.             push bx                 ;Get length of substring
  197.             call strlen             ;into DX
  198.             xchg dx,ax
  199.             mov ah,[bx]             ;AH = first char
  200.  
  201. p3_loop:    lodsb                   ;Load char
  202.             test al,al              ;Null, not found
  203.             jz p3_nope
  204.             cmp al,ah               ;Loop while not equal
  205.             jne p3_loop
  206.  
  207.             mov cx,dx               ;CX = length
  208.             mov di,bx               ;DI = substring
  209.             push si                 ;Save SI
  210.             dec si                  ;Push back char
  211.             repe cmpsb              ;Compare strings
  212.             pop si                  ;Restore SI
  213.             jne p3_loop             ;Loop if not equal
  214.  
  215.             sub si,[strp]           ;AX = position of char
  216.             dec si
  217.             mov es,si               ;Sneaky: save it in ES
  218.  
  219. p3_done:    popa                    ;Restore registers
  220.             mov ax,es               ;Return value in AX
  221.             pop es
  222.             pop bp                  ;Delete stack frame
  223.             ret 4                   ;Return
  224.  
  225. p3_nope:    mov ax,-1               ;Not found, return -1
  226.             mov es,ax
  227.             jmp p3_done
  228.  
  229. EndP        strstr
  230.  
  231. End
  232.  
  233. ~~~C_STR3
  234. Ideal
  235.  
  236. Public      stricmp,strlwr,strupr
  237.  
  238. Model Tiny
  239. CodeSeg
  240. P386
  241.  
  242. ;****************** stricmp() -- Compare strings, case insensitive
  243. ;void stricmp(char *str1, char *str2);
  244.  
  245. str1        equ bp+6
  246. str2        equ bp+4
  247.  
  248. Proc        stricmp
  249.  
  250.             push bp                 ;Set up stack frame
  251.             mov bp,sp
  252.             push si di              ;Save registers
  253.  
  254.             mov si,[str1]           ;SI = source
  255.             mov di,[str2]           ;DI = destination
  256.  
  257. p1_loop:    lodsb                   ;Load char 1
  258.             mov ah,[di]             ;Load char 2
  259.             inc di
  260.  
  261.             cmp al,'a'              ;Convert AL to uppercase
  262.             jb p1_setAH
  263.             cmp al,'z'
  264.             ja p1_setAH
  265.             sub al,20h
  266.  
  267. p1_setAH:   cmp ah,'a'              ;Convert AH to uppercase
  268.             jb p1_comp
  269.             cmp ah,'z'
  270.             ja p1_comp
  271.             sub ah,20h
  272.  
  273. p1_comp:    cmp al,ah               ;Equal?
  274.             jne p1_nope
  275.             test al,al              ;Loop while not zero
  276.             jnz p1_loop
  277.  
  278.             inc ax                  ;Equal, return 1
  279.  
  280. p1_done:    pop di si               ;Restore registers
  281.             pop bp                  ;Delete stack frame
  282.             ret 4                   ;Return
  283.  
  284. p1_nope:    xor ax,ax               ;Not equal, return 0
  285.             jmp p1_done
  286.  
  287. EndP        stricmp
  288.  
  289. ;****************** strlwr() -- Convert string to lowercase
  290. ;int strlwr(char *strp);
  291.  
  292. strp        equ bp+4
  293.  
  294. Proc        strlwr
  295.  
  296.             push bp                 ;Set up stack frame
  297.             mov bp,sp
  298.             pusha                   ;Save registers
  299.  
  300.             mov si,[strp]           ;SI = string pointer
  301.  
  302. p2_loop:    lodsb                   ;Load char
  303.             test al,al              ;Check for null
  304.             jz p2_done
  305.             cmp al,'A'              ;Check for uppercase
  306.             jb p2_loop
  307.             cmp al,'Z'
  308.             ja p2_loop
  309.             add al,20h              ;Convert to lowercase
  310.             mov [si-1],al           ;Store char
  311.             jmp p2_loop
  312.  
  313. p2_done:    popa                    ;Restore registers
  314.             pop bp                  ;Delete stack frame
  315.             ret 2                   ;Return
  316.  
  317. EndP        strlwr
  318.  
  319. ;****************** strupr() -- Convert string to uppercase
  320. ;int strupr(char *strp);
  321.  
  322. strp        equ bp+4
  323.  
  324. Proc        strupr
  325.  
  326.             push bp                 ;Set up stack frame
  327.             mov bp,sp
  328.             pusha                   ;Save registers
  329.  
  330.             mov si,[strp]           ;SI = string pointer
  331.  
  332. p3_loop:    lodsb                   ;Load char
  333.             test al,al              ;Check for null
  334.             jz p3_done
  335.             cmp al,'a'              ;Check for lowercase
  336.             jb p3_loop
  337.             cmp al,'z'
  338.             ja p3_loop
  339.             sub al,20h              ;Convert to uppercase
  340.             mov [si-1],al           ;Store char
  341.             jmp p3_loop
  342.  
  343. p3_done:    popa                    ;Restore registers
  344.             pop bp                  ;Delete stack frame
  345.             ret 2                   ;Return
  346.  
  347. EndP        strupr
  348.  
  349. End
  350.  
  351. ~~~C_STR4
  352. Ideal
  353.  
  354. Public      strrtrim,strltrim
  355.  
  356. Model Tiny
  357. CodeSeg
  358. P386
  359.  
  360. ;****************** strrtrim() -- Trim trailing spaces off a string
  361. ;int strrtrim(char *strp);
  362.  
  363. strp        equ bp+4
  364.  
  365. Proc        strrtrim
  366.  
  367.             push bp                 ;Set up stack frame
  368.             mov bp,sp
  369.             pusha                   ;Save registers
  370.  
  371.             mov si,[strp]           ;SI = string pointer
  372.             mov di,si               ;DI = SI
  373.  
  374. p1_loop:    lodsb                   ;Load char
  375.             test al,al              ;Check for null
  376.             jz p1_done
  377.             cmp al,' '              ;Check for space
  378.             je p1_loop
  379.             mov di,si               ;Set pointer
  380.             jmp p1_loop
  381.  
  382. p1_done:    mov [byte di+1],al      ;Terminate string
  383.             popa                    ;Restore registers
  384.             pop bp                  ;Delete stack frame
  385.             ret 2                   ;Return
  386.  
  387. EndP        strrtrim
  388.  
  389. ;****************** strltrim() -- Trim leading spaces off a string
  390. ;int strltrim(char *strp);
  391.  
  392. strp        equ bp+4
  393.  
  394. Proc        strltrim
  395.  
  396.             push bp                 ;Set up stack frame
  397.             mov bp,sp
  398.             pusha                   ;Save registers
  399.  
  400.             mov si,[strp]           ;SI, DI = string pointer
  401.             mov di,si
  402.  
  403. p2_loop:    lodsb                   ;Load char
  404.             test al,al              ;Check for null
  405.             jz p2_cont
  406.             cmp al,' '              ;Loop while space
  407.             je p2_loop
  408.  
  409. p2_cont:    dec si                  ;Move back one char
  410.             cmp si,di               ;No spaces, quit
  411.             je p2_done
  412.  
  413. p2_cloop:   lodsb                   ;Shift the string over
  414.             mov [di],al
  415.             inc di
  416.             test al,al
  417.             jnz p2_cloop
  418.  
  419. p2_done:    popa                    ;Restore registers
  420.             pop bp                  ;Delete stack frame
  421.             ret 2                   ;Return
  422.  
  423. EndP        strltrim
  424.  
  425. End
  426.  
  427. ~~~C_MEM1
  428. Ideal
  429.  
  430. Public      memcpy,memset
  431.  
  432. Model Tiny
  433. CodeSeg
  434. P386
  435.  
  436. ;****************** memcpy() -- Copy memory block
  437. ;void memcpy(void *p1, void *p2, int nbytes);
  438.  
  439. p1          equ bp+8
  440. p2          equ bp+6
  441. nbytes      equ bp+4
  442.  
  443. Proc        memcpy
  444.  
  445.             push bp                 ;Set up stack frame
  446.             mov bp,sp
  447.             push es                 ;Save registers
  448.             pusha
  449.  
  450.             push ds                 ;ES = DS
  451.             pop es
  452.  
  453.             mov si,[p2]             ;SI = source
  454.             mov di,[p1]             ;DI = destination
  455.             mov cx,[nbytes]         ;CX = count
  456.  
  457.             cmp di,si               ;Make forward moves
  458.             jb p1_go                ;in reverse
  459.             je p1_done
  460.  
  461.             std                     ;Set direction flag
  462.             add si,cx               ;Move offsets to end
  463.             add di,cx
  464.             dec si
  465.             dec di
  466.  
  467. p1_go:      rep movsb               ;Copy memory
  468.  
  469. p1_done:    cld                     ;Clear direction flag
  470.             popa                    ;Restore registers
  471.             pop es
  472.             pop bp                  ;Delete stack frame
  473.             ret 6                   ;Return
  474.  
  475. EndP        memcpy
  476.  
  477. ;****************** memset() -- Set memory block
  478. ;void memset(void *ptr, int nbytes, int chr);
  479.  
  480. ptr         equ bp+8
  481. nbytes      equ bp+6
  482. chr         equ bp+4
  483.  
  484. Proc        memset
  485.  
  486.             push bp                 ;Set up stack frame
  487.             mov bp,sp
  488.             push es                 ;Save registers
  489.             pusha
  490.  
  491.             push ds                 ;ES = DS
  492.             pop es
  493.  
  494.             mov di,[ptr]            ;DI = block
  495.             mov cx,[nbytes]         ;CX = count
  496.             mov al,[chr]            ;AL = char
  497.             rep stosb               ;Set memory
  498.  
  499.             popa                    ;Restore registers
  500.             pop es
  501.             pop bp                  ;Delete stack frame
  502.             ret 6                   ;Return
  503.  
  504. EndP        memset
  505.  
  506. End
  507.  
  508. ~~~C_MEM2
  509. Ideal
  510.  
  511. Public      memcmp,memchr
  512.  
  513. Model Tiny
  514. CodeSeg
  515. P386
  516.  
  517. ;****************** memcmp() -- Compare memory blocks
  518. ;void memcmp(void *p1, void *p2, int nbytes);
  519.  
  520. p1          equ bp+8
  521. p2          equ bp+6
  522. nbytes      equ bp+4
  523.  
  524. Proc        memcmp
  525.  
  526.             push bp                 ;Set up stack frame
  527.             mov bp,sp
  528.             push es                 ;Save registers
  529.             push cx si di
  530.  
  531.             push ds                 ;ES = DS
  532.             pop es
  533.  
  534.             mov si,[p2]             ;SI = source
  535.             mov di,[p1]             ;DI = destination
  536.             mov cx,[nbytes]         ;CX = count
  537.             repe cmpsb              ;Compare memory
  538.  
  539.             mov ax,1                ;Assume equal
  540.             je p1_done              ;Jump if equal
  541.  
  542.             xor ax,ax               ;Not equal, return 0
  543.  
  544. p1_done:    pop di si cx            ;Restore registers
  545.             pop es
  546.             pop bp                  ;Delete stack frame
  547.             ret 6                   ;Return
  548.  
  549. EndP        memcmp
  550.  
  551. ;****************** memchr() -- Scan memory for char
  552. ;void memchr(void *ptr, int nbytes, int chr);
  553.  
  554. ptr         equ bp+8
  555. nbytes      equ bp+6
  556. chr         equ bp+4
  557.  
  558. Proc        memchr
  559.  
  560.             push bp                 ;Set up stack frame
  561.             mov bp,sp
  562.             push es                 ;Save registers
  563.             push cx si di
  564.  
  565.             push ds                 ;ES = DS
  566.             pop es
  567.  
  568.             mov di,[ptr]            ;DI = block
  569.             mov cx,[nbytes]         ;CX = count
  570.             mov al,[chr]            ;AL = char
  571.             repne scasb             ;Scan memory
  572.             jne p2_nope             ;Jump if not found
  573.  
  574.             sub di,[ptr]            ;AX = position of char
  575.             dec di
  576.             xchg ax,di
  577.  
  578. p2_done:    pop di si cx            ;Restore registers
  579.             pop es
  580.             pop bp                  ;Delete stack frame
  581.             ret 6                   ;Return
  582.  
  583. p2_nope:    mov ax,-1               ;Not found, return -1
  584.             jmp p2_done
  585.  
  586. EndP        memchr
  587.  
  588. End
  589.  
  590. ~~~C_ISRCH
  591. Ideal
  592.  
  593. Public      isearch
  594.  
  595. Model Tiny
  596. P386
  597. CodeSeg
  598.  
  599. ;****************** isearch() -- Search a sorted array of integers
  600. ;int isearch(int *ary, int size, int elem);
  601.  
  602. ary         equ bp+8
  603. size        equ bp+6
  604. elem        equ bp+4
  605.  
  606. Proc        isearch
  607.  
  608.             push bp                 ;Set up stack frame
  609.             mov bp,sp
  610.             push bx cx dx si di     ;Save registers
  611.  
  612.             mov bx,[ary]            ;BX = array
  613.             xor cx,cx               ;CX = lower limit
  614.             mov dx,[size]           ;DX = upper limit
  615.             dec dx
  616.  
  617. p1_loop:    mov si,cx               ;SI = middle element
  618.             add si,dx
  619.             shr si,1
  620.             add si,si
  621.             mov ax,[bx+si]          ;Get element
  622.             shr si,1                ;Fix SI
  623.             cmp ax,[elem]           ;Check element
  624.             je p1_found             ;Equal?
  625.             jl p1_less              ;Too low?
  626.  
  627. p1_greater: mov di,si               ;Set first half
  628.             mov si,cx
  629.             jmp p1_cont
  630.  
  631. p1_less:    mov di,dx               ;Set second half
  632.             inc si
  633.  
  634. p1_cont:    cmp cx,dx               ;Min = Max, done
  635.             je p1_nope
  636.             mov cx,si               ;Set limits
  637.             mov dx,di
  638.             jmp p1_loop             ;Loop back
  639.  
  640. p1_found:   xchg ax,si              ;AX = result
  641.  
  642. p1_done:    pop di si dx cx bx      ;Restore registers
  643.             pop bp                  ;Delete stack frame
  644.             ret 6                   ;Return
  645.  
  646. p1_nope:    mov ax,-1               ;Not found, return -1
  647.             jmp p1_done
  648.  
  649. EndP        isearch
  650.  
  651. End
  652.  
  653. ~~~C_LSRCH
  654. Ideal
  655.  
  656. Public      lsearch
  657.  
  658. Model Tiny
  659. P386
  660. CodeSeg
  661.  
  662. ;****************** lsearch() -- Search a sorted array of longs
  663. ;int lsearch(long *ary, int size, long elem);
  664.  
  665. ary         equ bp+10
  666. size        equ bp+8
  667. elem        equ bp+4
  668.  
  669. Proc        lsearch
  670.  
  671.             push bp                 ;Set up stack frame
  672.             mov bp,sp
  673.             push es                 ;Save registers
  674.             pushad
  675.  
  676.             mov bx,[ary]            ;BX = array
  677.             xor cx,cx               ;CX = lower limit
  678.             mov dx,[size]           ;DX = upper limit
  679.             dec dx
  680.  
  681. p1_loop:    mov si,cx               ;SI = middle element
  682.             add si,dx
  683.             shr si,1
  684.             shl si,2
  685.             mov eax,[bx+si]         ;Get element
  686.             shr si,2                ;Fix SI
  687.             cmp eax,[elem]          ;Check element
  688.             je p1_done              ;Equal?
  689.             jl p1_less              ;Too low?
  690.  
  691. p1_greater: mov di,si               ;Set first half
  692.             mov si,cx
  693.             jmp p1_cont
  694.  
  695. p1_less:    mov di,dx               ;Set second half
  696.             inc si
  697.  
  698. p1_cont:    cmp cx,dx               ;Min = Max, done
  699.             je p1_nope
  700.             mov cx,si               ;Set limits
  701.             mov dx,di
  702.             jmp p1_loop             ;Loop back
  703.  
  704. p1_done:    mov es,si               ;ES = result
  705.             popad                   ;Restore registers
  706.             mov ax,es               ;AX = result
  707.             pop es                  ;Restore ES
  708.             pop bp                  ;Delete stack frame
  709.             ret 8                   ;Return
  710.  
  711. p1_nope:    mov si,-1               ;Not found, return -1
  712.             jmp p1_done
  713.  
  714. EndP        lsearch
  715.  
  716. End
  717.  
  718. ~~~C_XSRCH
  719. Ideal
  720.  
  721. Public      xsearch
  722.  
  723. Model Tiny
  724. P386
  725. CodeSeg
  726.  
  727. ;****************** xsearch() -- Search sorted array, generalized
  728. ;int xsearch(void **ary, int size, void *elem, void *func);
  729.  
  730. ary         equ bp+10
  731. size        equ bp+8
  732. elem        equ bp+6
  733. func        equ bp+4
  734.  
  735. Proc        xsearch
  736.  
  737.             push bp                 ;Set up stack frame
  738.             mov bp,sp
  739.             push bx cx dx si di     ;Save registers
  740.  
  741.             mov bx,[ary]            ;BX = array
  742.             xor cx,cx               ;CX = lower limit
  743.             mov dx,[size]           ;DX = upper limit
  744.             dec dx
  745.  
  746. p3_loop:    mov si,cx               ;SI = middle element
  747.             add si,dx
  748.             shr si,1
  749.             add si,si
  750.             mov ax,[bx+si]          ;Get element
  751.             shr si,1                ;Fix SI
  752.             push ax [word elem]     ;Check element
  753.             call [word func]
  754.             test ax,ax
  755.             je p3_found             ;Equal?
  756.             jl p3_less              ;Too low?
  757.  
  758. p3_greater: mov di,si               ;Set first half
  759.             mov si,cx
  760.             jmp p3_cont
  761.  
  762. p3_less:    mov di,dx               ;Set second half
  763.             inc si
  764.  
  765. p3_cont:    cmp cx,dx               ;Min = Max, done
  766.             je p3_nope
  767.             mov cx,si               ;Set limits
  768.             mov dx,di
  769.             jmp p3_loop             ;Loop back
  770.  
  771. p3_found:   xchg ax,si              ;AX = result
  772.  
  773. p3_done:    pop di si dx cx bx      ;Restore registers
  774.             pop bp                  ;Delete stack frame
  775.             ret 8                   ;Return
  776.  
  777. p3_nope:    mov ax,-1               ;Not found, return -1
  778.             jmp p3_done
  779.  
  780. EndP        xsearch
  781.  
  782. End
  783.  
  784. ~~~C_SSRCH
  785. Ideal
  786.  
  787. Extrn       strcmp:near
  788. Public      ssearch
  789.  
  790. Model Tiny
  791. P386
  792. CodeSeg
  793.  
  794. ;****************** ssearch() -- Search a sorted array of strings
  795. ;int ssearch(char **ary, int size, char *elem);
  796.  
  797. ary         equ bp+8
  798. size        equ bp+6
  799. elem        equ bp+4
  800.  
  801. Proc        ssearch
  802.  
  803.             push bp                 ;Set up stack frame
  804.             mov bp,sp
  805.             push bx cx dx si di     ;Save registers
  806.  
  807.             mov bx,[ary]            ;BX = array
  808.             xor cx,cx               ;CX = lower limit
  809.             mov dx,[size]           ;DX = upper limit
  810.             dec dx
  811.  
  812. p1_loop:    mov si,cx               ;SI = middle element
  813.             add si,dx
  814.             shr si,1
  815.             add si,si
  816.             mov ax,[bx+si]          ;Get element
  817.             shr si,1                ;Fix SI
  818.             push ax [word elem]     ;Check element
  819.             call strcmp
  820.             test ax,ax
  821.             je p1_found             ;Equal?
  822.             jl p1_less              ;Too low?
  823.  
  824. p1_greater: mov di,si               ;Set first half
  825.             mov si,cx
  826.             jmp p1_cont
  827.  
  828. p1_less:    mov di,dx               ;Set second half
  829.             inc si
  830.  
  831. p1_cont:    cmp cx,dx               ;Min = Max, done
  832.             je p1_nope
  833.             mov cx,si               ;Set limits
  834.             mov dx,di
  835.             dec di
  836.             jmp p1_loop             ;Loop back
  837.  
  838. p1_found:   xchg ax,si              ;AX = result
  839.  
  840. p1_done:    pop di si dx cx bx      ;Restore registers
  841.             pop bp                  ;Delete stack frame
  842.             ret 6                   ;Return
  843.  
  844. p1_nope:    mov ax,-1               ;Not found, return -1
  845.             jmp p1_done
  846.  
  847. EndP        ssearch
  848.  
  849. End
  850.  
  851. ~~~C_ISORT
  852. Ideal
  853.  
  854. Public      isort
  855.  
  856. Model Tiny
  857. P386
  858. CodeSeg
  859.  
  860. ;****************** isort() -- Sort an array of integers
  861. ;void isort(int *ary, int size);
  862.  
  863. ary         equ bp+6
  864. max         equ bp+4
  865.  
  866. Proc        isort
  867.  
  868.             push bp                 ;Set up stack frame
  869.             mov bp,sp
  870.             pusha                   ;Save all registers
  871.  
  872.             mov bx,[ary]            ;Call recursive routine
  873.             xor cx,cx
  874.             mov dx,[max]
  875.             dec dx
  876.             add dx,dx
  877.             call p1_qsort
  878.  
  879.             popa                    ;Restore registers
  880.             pop bp                  ;Delete stack frame
  881.             ret 4                   ;Return
  882.  
  883. p1_qsort:   cmp cx,dx               ;One element, return
  884.             je p1_ret
  885.             pusha
  886.  
  887.             mov ax,dx               ;Two elements, sort them
  888.             sub ax,cx
  889.             cmp ax,2
  890.             jne p1_cont
  891.  
  892.             mov si,cx               ;SI, DI = low, high
  893.             mov di,dx
  894.  
  895.             mov ax,[bx+si]          ;Check them
  896.             cmp ax,[bx+di]
  897.             jle p1_done
  898.  
  899.             xchg ax,[bx+di]         ;Switch them
  900.             mov [bx+si],ax
  901.             jmp p1_done
  902.  
  903. p1_cont:    mov si,cx               ;AX = middle element
  904.             add si,dx
  905.             shr si,2
  906.             add si,si
  907.             mov ax,[bx+si]
  908.  
  909.             mov si,cx               ;SI = low, DI = high
  910.             mov di,dx
  911.  
  912. p1_loop:    cmp si,dx               ;While [BX+SI] < AX and
  913.             jge p1_loop2            ; SI < DX, advance SI
  914.             cmp ax,[bx+si]
  915.             jle p1_loop2
  916.             add si,2
  917.             jmp p1_loop
  918.  
  919. p1_loop2:   cmp di,cx               ;While [BX+DI] > AX and
  920.             jle p1_cont2            ; DI > CX, advance DI
  921.             cmp ax,[bx+di]
  922.             jge p1_cont2
  923.             sub di,2
  924.             jmp p1_loop2
  925.  
  926. p1_cont2:   cmp si,di               ;Hit in middle, recurse
  927.             jge p1_rec
  928.  
  929.             push [word bx+si]       ;Swap elements
  930.             push [word bx+di]
  931.             pop [word bx+si]
  932.             pop [word bx+di]
  933.             add si,2                ;Advance SI, DI
  934.             sub di,2
  935.  
  936.             jmp p1_loop             ;Loop back
  937.  
  938. p1_rec:     cmp cx,si               ;If first half isn't empty,
  939.             je p1_skip1             ;recurse to sort it
  940.             xchg dx,di
  941.             call p1_qsort
  942.             xchg dx,di
  943.  
  944. p1_skip1:   cmp dx,di               ;If second half isn't empty,
  945.             je p1_done              ;recurse to sort it
  946.             xchg cx,si
  947.             call p1_qsort
  948.             xchg cx,si
  949.  
  950. p1_done:    popa                    ;Restore registers
  951. p1_ret:     ret                     ;Return
  952.  
  953. EndP        isort
  954.  
  955. End
  956.  
  957. ~~~C_LSORT
  958. Ideal
  959.  
  960. Public      lsort
  961.  
  962. Model Tiny
  963. P386
  964. CodeSeg
  965.  
  966. ;****************** lsort() -- Sort an array of longs
  967. ;void lsort(long *ary, int size);
  968.  
  969. ary         equ bp+6
  970. max         equ bp+4
  971. num         equ bp-4
  972.  
  973. Proc        lsort
  974.  
  975.             push bp                 ;Set up stack frame
  976.             mov bp,sp
  977.             pushad                  ;Save all registers
  978.  
  979.             mov bx,[ary]            ;Call recursive routine
  980.             xor cx,cx
  981.             mov dx,[max]
  982.             dec dx
  983.             shl dx,2
  984.             call p1_qsort
  985.  
  986.             popad                   ;Restore registers
  987.             pop bp                  ;Delete stack frame
  988.             ret 4                   ;Return
  989.  
  990. p1_qsort:   cmp cx,dx               ;One element, return
  991.             je p1_ret
  992.             pusha
  993.  
  994.             mov ax,dx               ;Two elements, sort them
  995.             sub ax,cx
  996.             cmp ax,4
  997.             jne p1_cont
  998.  
  999.             mov si,cx               ;SI, DI = low, high
  1000.             mov di,dx
  1001.  
  1002.             mov eax,[bx+si]         ;Check them
  1003.             cmp eax,[bx+di]
  1004.             jle p1_done
  1005.  
  1006.             xchg eax,[bx+di]        ;Switch them
  1007.             mov [bx+si],eax
  1008.             jmp p1_done
  1009.  
  1010. p1_cont:    mov si,cx               ;AX = middle element
  1011.             add si,dx
  1012.             shr si,3
  1013.             shl si,2
  1014.             mov eax,[bx+si]
  1015.  
  1016.             mov si,cx               ;SI = low, DI = high
  1017.             mov di,dx
  1018.  
  1019. p1_loop:    cmp si,dx               ;While [BX+SI] < EAX and
  1020.             jge p1_loop2            ; SI < DX, advance SI
  1021.             cmp eax,[bx+si]
  1022.             jle p1_loop2
  1023.             add si,4
  1024.             jmp p1_loop
  1025.  
  1026. p1_loop2:   cmp di,cx               ;While [BX+DI] > EAX and
  1027.             jle p1_cont2            ; DI > CX, advance DI
  1028.             cmp eax,[bx+di]
  1029.             jge p1_cont2
  1030.             sub di,4
  1031.             jmp p1_loop2
  1032.  
  1033. p1_cont2:   cmp si,di               ;Hit in middle, recurse
  1034.             jge p1_rec
  1035.  
  1036.             push [dword bx+si]      ;Swap elements
  1037.             push [dword bx+di]
  1038.             pop [dword bx+si]
  1039.             pop [dword bx+di]
  1040.             add si,4                ;Advance SI, DI
  1041.             sub di,4
  1042.  
  1043.             jmp p1_loop             ;Loop back
  1044.  
  1045. p1_rec:     cmp cx,si               ;If first half isn't empty,
  1046.             je p1_skip1             ;recurse to sort it
  1047.             xchg dx,di
  1048.             call p1_qsort
  1049.             xchg dx,di
  1050.  
  1051. p1_skip1:   cmp dx,di               ;If second half isn't empty,
  1052.             je p1_done              ;recurse to sort it
  1053.             xchg cx,si
  1054.             call p1_qsort
  1055.             xchg cx,si
  1056.  
  1057. p1_done:    popa                    ;Restore registers
  1058. p1_ret:     ret                     ;Return
  1059.  
  1060. EndP        lsort
  1061.  
  1062. End
  1063.  
  1064. ~~~C_SSORT
  1065. Ideal
  1066.  
  1067. Extrn       strcmp:near
  1068. Public      ssort
  1069.  
  1070. Model Tiny
  1071. P386
  1072. CodeSeg
  1073.  
  1074. ;****************** ssort() -- Sort an array of strings
  1075. ;void ssort(char **ary, int size);
  1076.  
  1077. ary         equ bp+6
  1078. max         equ bp+4
  1079.  
  1080. Proc        ssort
  1081.  
  1082.             push bp                 ;Set up stack frame
  1083.             mov bp,sp
  1084.             pusha                   ;Save all registers
  1085.  
  1086.             mov bx,[ary]            ;Call recursive routine
  1087.             xor cx,cx
  1088.             mov dx,[max]
  1089.             dec dx
  1090.             add dx,dx
  1091.             call p1_qsort
  1092.  
  1093.             popa                    ;Restore registers
  1094.             pop bp                  ;Delete stack frame
  1095.             ret 4                   ;Return
  1096.  
  1097. p1_qsort:   cmp cx,dx               ;One element, return
  1098.             jne $+3
  1099.             ret
  1100.             pusha
  1101.  
  1102.             mov ax,dx               ;Two elements, sort them
  1103.             sub ax,cx
  1104.             cmp ax,2
  1105.             jne p1_cont
  1106.  
  1107.             mov si,cx               ;SI, DI = low, high
  1108.             mov di,dx
  1109.  
  1110.             mov ax,[bx+si]          ;Check them
  1111.             push ax [word bx+di]
  1112.             call strcmp
  1113.             test ax,ax
  1114.             jle p1_done
  1115.  
  1116.             push [word bx+si]       ;Switch them
  1117.             push [word bx+di]
  1118.             pop [word bx+si]
  1119.             pop [word bx+di]
  1120.             jmp p1_done
  1121.  
  1122. p1_cont:    mov si,cx               ;AX = middle element
  1123.             add si,dx
  1124.             shr si,2
  1125.             add si,si
  1126.             mov ax,[bx+si]
  1127.  
  1128.             mov si,cx               ;SI = low, DI = high
  1129.             mov di,dx
  1130.  
  1131. p1_loop:    cmp si,dx               ;While [BX+SI] < AX and
  1132.             jge p1_loop2            ; SI < DX, advance SI
  1133.             push ax ax [word bx+si]
  1134.             call strcmp
  1135.             pop ax
  1136.             jle p1_loop2
  1137.             add si,2
  1138.             jmp p1_loop
  1139.  
  1140. p1_loop2:   cmp di,cx               ;While [BX+DI] > AX and
  1141.             jle p1_cont2            ; DI > CX, advance DI
  1142.             push ax ax [word bx+di]
  1143.             call strcmp
  1144.             pop ax
  1145.             jge p1_cont2
  1146.             sub di,2
  1147.             jmp p1_loop2
  1148.  
  1149. p1_cont2:   cmp si,di               ;Hit in middle, recurse
  1150.             jge p1_rec
  1151.  
  1152.             push [word bx+si]       ;Swap elements
  1153.             push [word bx+di]
  1154.             pop [word bx+si]
  1155.             pop [word bx+di]
  1156.             add si,2                ;Advance SI, DI
  1157.             sub di,2
  1158.  
  1159.             jmp p1_loop             ;Loop back
  1160.  
  1161. p1_rec:     cmp cx,si               ;If first half isn't empty,
  1162.             je p1_skip1             ;recurse to sort it
  1163.             xchg dx,di
  1164.             call p1_qsort
  1165.             xchg dx,di
  1166.  
  1167. p1_skip1:   cmp dx,di               ;If second half isn't empty,
  1168.             je p1_done              ;recurse to sort it
  1169.             xchg cx,si
  1170.             call p1_qsort
  1171.             xchg cx,si
  1172.  
  1173. p1_done:    popa                    ;Restore registers
  1174. p1_ret:     ret                     ;Return
  1175.  
  1176. EndP        ssort
  1177.  
  1178. End
  1179.  
  1180. ~~~C_XSORT
  1181. Ideal
  1182.  
  1183. Public      xsort
  1184.  
  1185. Model Tiny
  1186. P386
  1187. CodeSeg
  1188.  
  1189. ;****************** xsort() -- Sort array, generalized
  1190. ;void xsort(void **ary, int size, void *func);
  1191.  
  1192. ary         equ bp+8
  1193. max         equ bp+6
  1194. func        equ bp+4
  1195.  
  1196. Proc        xsort
  1197.  
  1198.             push bp                 ;Set up stack frame
  1199.             mov bp,sp
  1200.             pusha                   ;Save all registers
  1201.  
  1202.             mov bx,[ary]            ;Call recursive routine
  1203.             xor cx,cx
  1204.             mov dx,[max]
  1205.             dec dx
  1206.             add dx,dx
  1207.             call p1_qsort
  1208.  
  1209.             popa                    ;Restore registers
  1210.             pop bp                  ;Delete stack frame
  1211.             ret 4                   ;Return
  1212.  
  1213. p1_qsort:   cmp cx,dx               ;One element, return
  1214.             jne $+3
  1215.             ret
  1216.             pusha
  1217.  
  1218.             mov ax,dx               ;Two elements, sort them
  1219.             sub ax,cx
  1220.             cmp ax,2
  1221.             jne p1_cont
  1222.  
  1223.             mov si,cx               ;SI, DI = low, high
  1224.             mov di,dx
  1225.  
  1226.             mov ax,[bx+si]          ;Check them
  1227.             push ax [word bx+di]
  1228.             call [word func]
  1229.             test ax,ax
  1230.             jle p1_done
  1231.  
  1232.             push [word bx+si]       ;Switch them
  1233.             push [word bx+di]
  1234.             pop [word bx+si]
  1235.             pop [word bx+di]
  1236.             jmp p1_done
  1237.  
  1238. p1_cont:    mov si,cx               ;AX = middle element
  1239.             add si,dx
  1240.             shr si,2
  1241.             add si,si
  1242.             mov ax,[bx+si]
  1243.  
  1244.             mov si,cx               ;SI = low, DI = high
  1245.             mov di,dx
  1246.  
  1247. p1_loop:    cmp si,dx               ;While [BX+SI] < AX and
  1248.             jge p1_loop2            ; SI < DX, advance SI
  1249.             push ax ax [word bx+si]
  1250.             call [word func]
  1251.             pop ax
  1252.             jle p1_loop2
  1253.             add si,2
  1254.             jmp p1_loop
  1255.  
  1256. p1_loop2:   cmp di,cx               ;While [BX+DI] > AX and
  1257.             jle p1_cont2            ; DI > CX, advance DI
  1258.             push ax ax [word bx+di]
  1259.             call [word func]
  1260.             pop ax
  1261.             jge p1_cont2
  1262.             sub di,2
  1263.             jmp p1_loop2
  1264.  
  1265. p1_cont2:   cmp si,di               ;Hit in middle, recurse
  1266.             jge p1_rec
  1267.  
  1268.             push [word bx+si]       ;Swap elements
  1269.             push [word bx+di]
  1270.             pop [word bx+si]
  1271.             pop [word bx+di]
  1272.             add si,2                ;Advance SI, DI
  1273.             sub di,2
  1274.  
  1275.             jmp p1_loop             ;Loop back
  1276.  
  1277. p1_rec:     cmp cx,si               ;If first half isn't empty,
  1278.             je p1_skip1             ;recurse to sort it
  1279.             xchg dx,di
  1280.             call p1_qsort
  1281.             xchg dx,di
  1282.  
  1283. p1_skip1:   cmp dx,di               ;If second half isn't empty,
  1284.             je p1_done              ;recurse to sort it
  1285.             xchg cx,si
  1286.             call p1_qsort
  1287.             xchg cx,si
  1288.  
  1289. p1_done:    popa                    ;Restore registers
  1290. p1_ret:     ret                     ;Return
  1291.  
  1292. EndP        xsort
  1293.  
  1294. End
  1295.  
  1296. ~~~C_LSHL
  1297. Ideal
  1298.  
  1299. Public      lshl
  1300.  
  1301. Model Tiny
  1302. CodeSeg
  1303. P386
  1304.  
  1305. ;****************** lshl() -- Shift long integer to the left
  1306. ;long lshl(long x, int d);    Included for compatibility.
  1307.  
  1308. x           equ bp+6
  1309. d           equ bp+4
  1310.  
  1311. Proc        lshl
  1312.  
  1313.             push bp                 ;Set up stack frame
  1314.             mov bp,sp
  1315.             push ebx cx             ;Save registers
  1316.  
  1317.             mov ebx,[x]             ;EBX = x
  1318.             mov cl,[d]              ;CL = distance
  1319.             shl ebx,cl              ;Shift left
  1320.             xchg ax,bx              ;DX:AX = result
  1321.             shr ebx,16
  1322.             mov dx,bx
  1323.  
  1324.             pop cx ebx              ;Restore registers
  1325.             pop bp                  ;Delete stack frame
  1326.             ret 6                   ;Return
  1327.  
  1328. EndP        lshl
  1329.  
  1330. End
  1331.  
  1332. ~~~C_LSHR
  1333. Ideal
  1334.  
  1335. Public      lshr
  1336.  
  1337. Model Tiny
  1338. CodeSeg
  1339. P386
  1340.  
  1341. ;****************** lshr() -- Shift long integer to the right
  1342. ;long lshr(long x, int d);    Included for compatibility.
  1343.  
  1344. x           equ bp+6
  1345. d           equ bp+4
  1346.  
  1347. Proc        lshr
  1348.  
  1349.             push bp                 ;Set up stack frame
  1350.             mov bp,sp
  1351.             push ebx cx             ;Save registers
  1352.  
  1353.             mov ebx,[x]             ;EBX = x
  1354.             mov cl,[d]              ;CL = distance
  1355.             shr ebx,cl              ;Shift right
  1356.             xchg ax,bx              ;DX:AX = result
  1357.             shr ebx,16
  1358.             mov dx,bx
  1359.  
  1360.             pop cx ebx              ;Restore registers
  1361.             pop bp                  ;Delete stack frame
  1362.             ret 6                   ;Return
  1363.  
  1364. EndP        lshr
  1365.  
  1366. End
  1367.  
  1368. ~~~C_LSAR
  1369. Ideal
  1370.  
  1371. Public      lsar
  1372.  
  1373. Model Tiny
  1374. CodeSeg
  1375. P386
  1376.  
  1377. ;****************** lsar() -- Shift long integer to the right, signed
  1378. ;long lsar(long x, int d);    Included for compatibility.
  1379.  
  1380. x           equ bp+6
  1381. d           equ bp+4
  1382.  
  1383. Proc        lsar
  1384.  
  1385.             push bp                 ;Set up stack frame
  1386.             mov bp,sp
  1387.             push ebx cx             ;Save registers
  1388.  
  1389.             mov ebx,[x]             ;EBX = x
  1390.             mov cl,[d]              ;CL = distance
  1391.             sar ebx,cl              ;Shift right, signed
  1392.             xchg ax,bx              ;DX:AX = result
  1393.             shr ebx,16
  1394.             mov dx,bx
  1395.  
  1396.             pop cx ebx              ;Restore registers
  1397.             pop bp                  ;Delete stack frame
  1398.             ret 6                   ;Return
  1399.  
  1400. EndP        lsar
  1401.  
  1402. End
  1403.  
  1404. ~~~C_LMUL
  1405. Ideal
  1406.  
  1407. Public      lmul
  1408.  
  1409. Model Tiny
  1410. CodeSeg
  1411. P386
  1412.  
  1413. ;****************** lmul() -- Multiply long integers
  1414. ;long lmul(long x, long y);   Included for compatibility.
  1415.  
  1416. x           equ bp+8
  1417. y           equ bp+4
  1418.  
  1419. Proc        lmul
  1420.  
  1421.             push bp                 ;Set up stack frame
  1422.             mov bp,sp
  1423.             push ebx                ;Save registers
  1424.  
  1425.             mov ebx,[x]             ;EBX = x * y
  1426.             imul ebx,[y]
  1427.             xchg ax,bx              ;DX:AX = result
  1428.             shr ebx,16
  1429.             mov dx,bx
  1430.  
  1431.             pop ebx                 ;Restore registers
  1432.             pop bp                  ;Delete stack frame
  1433.             ret 8                   ;Return
  1434.  
  1435. EndP        lmul
  1436.  
  1437. End
  1438.  
  1439. ~~~C_LIMUL
  1440. Ideal
  1441.  
  1442. Public      limul
  1443.  
  1444. Model Tiny
  1445. CodeSeg
  1446. P386
  1447.  
  1448. ;****************** limul() -- Multiply long integers, signed
  1449. ;long limul(long x, long y);   Included for compatibility
  1450.  
  1451. x           equ bp+8
  1452. y           equ bp+4
  1453.  
  1454. Proc        limul
  1455.  
  1456.             push bp                 ;Set up stack frame
  1457.             mov bp,sp
  1458.             push ebx                ;Save registers
  1459.  
  1460.             mov ebx,[x]             ;EBX = x * y
  1461.             imul ebx,[y]
  1462.             xchg ax,bx              ;DX:AX = result
  1463.             shr ebx,16
  1464.             mov dx,bx
  1465.  
  1466.             pop ebx                 ;Restore registers
  1467.             pop bp                  ;Delete stack frame
  1468.             ret 8                   ;Return
  1469.  
  1470. EndP        limul
  1471.  
  1472. End
  1473.  
  1474. ~~~C_LDIV
  1475. Ideal
  1476.  
  1477. Public      ldiv
  1478.  
  1479. Model Tiny
  1480. CodeSeg
  1481. P386
  1482.  
  1483. ;****************** ldiv() -- Divide long integers
  1484. ;long ldiv(long x, long y);   Included for compatibility.
  1485.  
  1486. x           equ bp+8
  1487. y           equ bp+4
  1488.  
  1489. Proc        ldiv
  1490.  
  1491.             push bp                 ;Set up stack frame
  1492.             mov bp,sp
  1493.             push ebx ecx esi        ;Save registers
  1494.  
  1495.             mov ecx,edx             ;Save EDX:EAX
  1496.             xchg ebx,eax
  1497.             mov eax,[x]             ;EAX = x / y
  1498.             mov esi,[y]
  1499.             xor edx,edx
  1500.             div esi
  1501.             mov edx,ecx             ;Restore EDX:EAX
  1502.             xchg ebx,eax
  1503.             xchg ax,bx              ;DX:AX = result
  1504.             shr ebx,16
  1505.             mov dx,bx
  1506.  
  1507.             pop esi ecx ebx         ;Restore registers
  1508.             pop bp                  ;Delete stack frame
  1509.             ret 8                   ;Return
  1510.  
  1511. EndP        ldiv
  1512.  
  1513. End
  1514.  
  1515. ~~~C_LIDIV
  1516. Ideal
  1517.  
  1518. Public      lidiv
  1519.  
  1520. Model Tiny
  1521. CodeSeg
  1522. P386
  1523.  
  1524. ;****************** lidiv() -- Divide long integers, signed
  1525. ;long lidiv(long x, long y);   Included for compatibility.
  1526.  
  1527. x           equ bp+8
  1528. y           equ bp+4
  1529.  
  1530. Proc        lidiv
  1531.  
  1532.             push bp                 ;Set up stack frame
  1533.             mov bp,sp
  1534.             push ebx ecx esi        ;Save registers
  1535.  
  1536.             mov ecx,edx             ;Save EDX:EAX
  1537.             xchg ebx,eax
  1538.             mov eax,[x]             ;EAX = x / y
  1539.             mov esi,[y]
  1540.             cdq
  1541.             idiv esi
  1542.             mov edx,ecx             ;Restore EDX:EAX
  1543.             xchg ebx,eax
  1544.             xchg ax,bx              ;DX:AX = result
  1545.             shr ebx,16
  1546.             mov dx,bx
  1547.  
  1548.             pop esi ecx ebx         ;Restore registers
  1549.             pop bp                  ;Delete stack frame
  1550.             ret 8                   ;Return
  1551.  
  1552. EndP        lidiv
  1553.  
  1554. End
  1555.  
  1556. ~~~C_LMOD
  1557. Ideal
  1558.  
  1559. Public      lmod
  1560.  
  1561. Model Tiny
  1562. CodeSeg
  1563. P386
  1564.  
  1565. ;****************** lmod() -- Modulo on long integers
  1566. ;long lmod(long x, long y);   Included for compatibility.
  1567.  
  1568. x           equ bp+8
  1569. y           equ bp+4
  1570.  
  1571. Proc        lmod
  1572.  
  1573.             push bp                 ;Set up stack frame
  1574.             mov bp,sp
  1575.             push ebx ecx esi        ;Save registers
  1576.  
  1577.             mov ecx,edx             ;Save EDX:EAX
  1578.             xchg ebx,eax
  1579.             mov eax,[x]             ;EAX = x / y
  1580.             mov esi,[y]
  1581.             xor edx,edx
  1582.             div esi
  1583.             xchg edx,ecx            ;Restore EDX:EAX
  1584.             xchg ebx,eax
  1585.             xchg ax,cx              ;DX:AX = result
  1586.             shr ecx,16
  1587.             mov dx,cx
  1588.  
  1589.             pop esi ecx ebx         ;Restore registers
  1590.             pop bp                  ;Delete stack frame
  1591.             ret 8                   ;Return
  1592.  
  1593. EndP        lmod
  1594.  
  1595. End
  1596.  
  1597. ~~~C_LIMOD
  1598. Ideal
  1599.  
  1600. Public      limod
  1601.  
  1602. Model Tiny
  1603. CodeSeg
  1604. P386
  1605.  
  1606. ;****************** limod() -- Modulo on long integers, signed
  1607. ;long limod(long x, long y);   Included for compatibility.
  1608.  
  1609. x           equ bp+8
  1610. y           equ bp+4
  1611.  
  1612. Proc        limod
  1613.  
  1614.             push bp                 ;Set up stack frame
  1615.             mov bp,sp
  1616.             push ebx ecx esi        ;Save registers
  1617.  
  1618.             mov ecx,edx             ;Save EDX:EAX
  1619.             xchg ebx,eax
  1620.             mov eax,[x]             ;EAX = x / y
  1621.             mov esi,[y]
  1622.             cdq
  1623.             idiv esi
  1624.             xchg edx,ecx            ;Restore EDX:EAX
  1625.             xchg ebx,eax
  1626.             xchg ax,cx              ;DX:AX = result
  1627.             shr ecx,16
  1628.             mov dx,cx
  1629.  
  1630.             pop esi ecx ebx         ;Restore registers
  1631.             pop bp                  ;Delete stack frame
  1632.             ret 8                   ;Return
  1633.  
  1634. EndP        limod
  1635.  
  1636. End
  1637.  
  1638. ~~~C_FIXMUL
  1639. Ideal
  1640.  
  1641. Public      fixmul
  1642.  
  1643. Model Tiny
  1644. CodeSeg
  1645. P386
  1646.  
  1647. ;****************** fixmul() -- Multiply fixed point numbers
  1648. ;long fixmul(long x, long y);   48 clocks (486)
  1649.  
  1650. x           equ bp+8
  1651. y           equ bp+4
  1652.  
  1653. Proc        fixmul
  1654.  
  1655.             push bp                 ;Set up stack frame
  1656.             mov bp,sp
  1657.             push ebx ecx            ;Save registers
  1658.  
  1659.             mov ecx,edx             ;Save EDX:EAX
  1660.             xchg ebx,eax
  1661.             mov eax,[x]             ;EAX = x / y (fixed point)
  1662.             mov edx,[y]
  1663.             imul edx
  1664.             shrd eax,edx,16
  1665.             mov edx,ecx             ;Restore EDX:EAX
  1666.             xchg ebx,eax
  1667.             xchg ax,bx              ;DX:AX = result
  1668.             shr ebx,16
  1669.             mov dx,bx
  1670.  
  1671.             pop ecx ebx             ;Restore registers
  1672.             pop bp                  ;Delete stack frame
  1673.             ret 8                   ;Return
  1674.  
  1675. EndP        fixmul
  1676.  
  1677. End
  1678.  
  1679. ~~~C_FIXDIV
  1680. Ideal
  1681.  
  1682. Public      fixdiv
  1683.  
  1684. Model Tiny
  1685. CodeSeg
  1686. P386
  1687.  
  1688. ;****************** fixdiv() -- Divide fixed point numbers
  1689. ;long fixdiv(long x, long y);   57-86 clocks (486)
  1690.  
  1691. x           equ bp+8
  1692. y           equ bp+4
  1693.  
  1694. Proc        fixdiv
  1695.  
  1696.             push bp                 ;Set up stack frame
  1697.             mov bp,sp
  1698.             push ebx ecx esi        ;Save registers
  1699.  
  1700.             mov ecx,edx             ;Save EDX:EAX
  1701.             xchg ebx,eax
  1702.             mov eax,[x]             ;EAX = x / y (fixed point)
  1703.             mov esi,[y]
  1704.             cdq
  1705.             shld edx,eax,16
  1706.             shl eax,16
  1707.             idiv esi
  1708.             mov edx,ecx             ;Restore EDX:EAX
  1709.             xchg ebx,eax
  1710.             xchg ax,bx              ;DX:AX = result
  1711.             shr ebx,16
  1712.             mov dx,bx
  1713.  
  1714.             pop esi ecx ebx         ;Restore registers
  1715.             pop bp                  ;Delete stack frame
  1716.             ret 8                   ;Return
  1717.  
  1718. EndP        fixdiv
  1719.  
  1720. End
  1721.  
  1722. ~~~C_TRIG
  1723. Ideal
  1724.  
  1725. Extrn       fixdiv:near
  1726. Public      sine, cosine, tangent, cotangent
  1727. Public      secant, cosecant
  1728.  
  1729. Model Tiny
  1730. CodeSeg
  1731. P386
  1732.  
  1733. ;****************** TaylorSine() -- Calculate sine by Taylor series
  1734. ;long TaylorSine(long x);           Returns value in EBX
  1735.  
  1736. ; *──────────────────────────────────────────────────*
  1737. ; │               x^3     x^5     x^7     x^9        │
  1738. ; │ sin(x) = x - ───── + ───── - ───── + ───── - ... │
  1739. ; │               3 !     5 !     7 !     9 !        │
  1740. ; *──────────────────────────────────────────────────*
  1741.  
  1742. x           equ bp+4
  1743.  
  1744. Proc        TaylorSine
  1745.  
  1746.             push bp                 ;Set up stack frame
  1747.             mov bp,sp
  1748.             push eax ecx edx esi    ;Save registers
  1749.  
  1750.             mov eax,[x]             ;First term = x
  1751.             xor ebx,ebx             ;Result = 0
  1752.             mov esi,1               ;Count = 1
  1753.  
  1754. TS_loop:    add ebx,eax             ;Add in term
  1755.  
  1756.             imul [dword x]          ;term = last-term * x^2
  1757.             shrd eax,edx,16
  1758.             imul [dword x]
  1759.             shrd eax,edx,16
  1760.             add esi,2               ;n = n + 2
  1761.             mov ecx,esi             ;ECX = n * (n - 1)
  1762.             dec ecx
  1763.             imul ecx,esi
  1764.             cdq                     ;term = last-term * x^2 / n(n-1)
  1765.             idiv ecx
  1766.             neg eax                 ;Invert sign
  1767.  
  1768.             test eax,eax            ;Loop while not zero
  1769.             jnz TS_loop
  1770.  
  1771.             pop esi edx ecx eax     ;Restore registers
  1772.             pop bp                  ;Delete stack frame
  1773.             ret 4                   ;Return
  1774.  
  1775. EndP        TaylorSine
  1776.  
  1777. Pi          dd 0003243Fh            ;Pi   (3.243F6A88... hex)
  1778. TwoPi       dd 0006487Fh            ;Pi*2 (6.487ED511... hex)
  1779. HalfPi      dd 00019220h            ;Pi/2 (1.921FB544... hex)
  1780.  
  1781. ;****************** sine() -- Trigonometric sine function
  1782. ;long sine(long x);
  1783.  
  1784. x           equ bp+4
  1785.  
  1786. Proc        sine
  1787.  
  1788.             push bp                 ;Set up stack frame
  1789.             mov bp,sp
  1790.             push ebx                ;Save EBX
  1791.  
  1792.             mov ebx,[x]             ;EBX = x + Pi
  1793.             add ebx,[Pi]
  1794.             push ebx [TwoPi]        ;Divide by 2*Pi
  1795.             call fixdiv
  1796.             movsx ebx,dx            ;EBX = integer part
  1797.             imul ebx,[TwoPi]        ;Multiply by 2*Pi
  1798.  
  1799.             neg ebx                 ;EBX = x - EBX
  1800.             add ebx,[x]
  1801.  
  1802.             push ebx                ;Calculate sine
  1803.             call TaylorSine
  1804.             xchg ax,bx              ;Result in DX:AX
  1805.             shr ebx,16
  1806.             mov dx,bx
  1807.  
  1808.             pop ebx                 ;Restore EBX
  1809.             pop bp                  ;Delete stack frame
  1810.             ret 4                   ;Return
  1811.  
  1812. EndP        sine
  1813.  
  1814. ;****************** cosine() -- Trigonometric cosine function
  1815. ;long cosine(long x);
  1816.  
  1817. x           equ bp+4
  1818.  
  1819. Proc        cosine
  1820.  
  1821.             push bp                 ;Set up stack frame
  1822.             mov bp,sp
  1823.  
  1824.             mov dx,[x+2]            ;DX:AX = x
  1825.             mov ax,[x]
  1826.             add ax,[word HalfPi]    ; x + Pi+2
  1827.             adc dx,[word HalfPi+2]
  1828.             push dx ax              ;cos(x) = sin(x + Pi/4)
  1829.             call sine
  1830.  
  1831.             pop bp                  ;Delete stack frame
  1832.             ret 4                   ;Return
  1833.  
  1834. EndP        cosine
  1835.  
  1836. ;****************** tangent() -- Trigonometric tangent function
  1837. ;long tangent(long x);
  1838.  
  1839. x           equ bp+4
  1840.  
  1841. Proc        tangent
  1842.  
  1843.             push bp                 ;Set up stack frame
  1844.             mov bp,sp
  1845.             push bx cx              ;Save registers
  1846.  
  1847.             push [dword x]          ;CX:BX = sin(x)
  1848.             call sine
  1849.             mov cx,dx
  1850.             xchg bx,ax
  1851.             push [dword x]          ;DX:AX = cos(x)
  1852.             call cosine
  1853.             push cx bx dx ax        ;tan(x) = sin(x) / cos(x)
  1854.             call fixdiv
  1855.  
  1856.             pop cx bx               ;Restore registers
  1857.             pop bp                  ;Delete stack frame
  1858.             ret 4                   ;Return
  1859.  
  1860. EndP        tangent
  1861.  
  1862. ;****************** cotangent() -- Trigonometric cotangent function
  1863. ;long cotangent(long x);
  1864.  
  1865. x           equ bp+4
  1866.  
  1867. Proc        cotangent
  1868.  
  1869.             push bp                 ;Set up stack frame
  1870.             mov bp,sp
  1871.             push bx cx              ;Save registers
  1872.  
  1873.             push [dword x]          ;CX:BX = sin(x)
  1874.             call sine
  1875.             mov cx,dx
  1876.             xchg bx,ax
  1877.             push [dword x]          ;DX:AX = cos(x)
  1878.             call cosine
  1879.             push dx ax cx bx        ;cot(x) = cos(x) / sin(x)
  1880.             call fixdiv
  1881.  
  1882.             pop cx bx               ;Restore registers
  1883.             pop bp                  ;Delete stack frame
  1884.             ret 4                   ;Return
  1885.  
  1886. EndP        cotangent
  1887.  
  1888. ;****************** secant() -- Trigonometric secant function
  1889. ;long secant(long x);
  1890.  
  1891. x           equ bp+4
  1892.  
  1893. Proc        secant
  1894.  
  1895.             push bp                 ;Set up stack frame
  1896.             mov bp,sp
  1897.  
  1898.             push [dword x]          ;DX:AX = cos(x)
  1899.             call cosine
  1900.             push 1 0 dx ax          ;sec(x) = 1 / cos(x)
  1901.             call fixdiv
  1902.  
  1903.             pop bp                  ;Delete stack frame
  1904.             ret 4                   ;Return
  1905.  
  1906. EndP        secant
  1907.  
  1908. ;****************** cosecant() -- Trigonometric cosecant function
  1909. ;long cosecant(long x);
  1910.  
  1911. x           equ bp+4
  1912.  
  1913. Proc        cosecant
  1914.  
  1915.             push bp                 ;Set up stack frame
  1916.             mov bp,sp
  1917.  
  1918.             push [dword x]          ;DX:AX = cos(x)
  1919.             call sine
  1920.             push 1 0 dx ax          ;csc(x) = 1 / sin(x)
  1921.             call fixdiv
  1922.  
  1923.             pop bp                  ;Delete stack frame
  1924.             ret 4                   ;Return
  1925.  
  1926. EndP        cosecant
  1927.  
  1928. End
  1929.  
  1930. ~~~C_FIXTOA
  1931. Ideal
  1932.  
  1933. Public      fixtoa
  1934.  
  1935. Model Tiny
  1936. CodeSeg
  1937. P386
  1938.  
  1939. ;****************** fixtoa() -- Convert fixed point number to string
  1940. ;void fixtoa(int n, char *strp);
  1941.  
  1942. n           equ bp+6
  1943. strp        equ bp+4
  1944.  
  1945. Proc        fixtoa
  1946.  
  1947.             push bp                 ;Set up stack frame
  1948.             mov bp,sp
  1949.             pusha                   ;Save all registers
  1950.  
  1951.             mov di,[strp]           ;DI = string pointer
  1952.             mov dx,[n+2]            ;DX:AX = n
  1953.             mov ax,[n]
  1954.  
  1955.             test dx,dx              ;Negative?
  1956.             jge p1_noneg
  1957.             mov [byte di],'-'       ;Store minus sign
  1958.             inc di
  1959.             neg dx                  ;Make it positive
  1960.             neg ax
  1961.             sbb dx,0
  1962.  
  1963. p1_noneg:   push dx                 ;Save DX
  1964.             xor bx,bx               ;Zero rem flag
  1965.             add ax,ax               ;Shift out high bit
  1966.             adc bx,0                ;BX = rem flag
  1967.             shr ax,1                ;Restore AX
  1968.  
  1969.             mov cx,50000            ;AX = AX * 50000
  1970.             mul cx
  1971.             shr ax,15               ;AX = AX / 32768
  1972.             shl dx,1
  1973.             or ax,dx
  1974.             pop dx                  ;Restore DX
  1975.             push bx ax              ;Save BX, AX
  1976.  
  1977.             xchg dx,ax              ;Integer part in AX
  1978.  
  1979.             xor cx,cx               ;Zero CX
  1980.             mov si,10               ;SI = 10
  1981.  
  1982. p1_dloop:   xor dx,dx               ;Divide by 10
  1983.             div si
  1984.             mov bl,dl               ;Remainder in BL
  1985.             add bl,30h              ;Convert to digit
  1986.             push bx                 ;Push digit
  1987.             inc cx
  1988.             test ax,ax              ;Loop back
  1989.             jnz p1_dloop
  1990.  
  1991. p1_ploop:   pop ax                  ;Pop digit
  1992.             mov [di],al             ;Store digit
  1993.             inc di
  1994.             loop p1_ploop           ;Loop back
  1995.  
  1996.             mov [byte di],'.'       ;Store decimal point
  1997.             inc di
  1998.             pop ax bx               ;Restore low data
  1999.             xor dx,dx               ;Zero DX
  2000.             test bx,bx              ;Check for high part
  2001.             jz p1_nohigh
  2002.  
  2003.             add ax,50000            ;Add in 50000
  2004.             adc dx,0
  2005.  
  2006. p1_nohigh:  mov si,10               ;SI = 10
  2007.             mov cx,5                ;5 digits
  2008.             jmp p1_skip1
  2009.  
  2010. p1_dloopb:  xor dx,dx               ;Zero DX
  2011. p1_skip1:   div si                  ;Divide by 10
  2012.             mov bl,dl               ;Remainder in BL
  2013.             add bl,30h              ;Convert to digit
  2014.             push bx                 ;Push digit
  2015.             loop p1_dloopb          ;Loop back
  2016.  
  2017.             mov cx,5                ;5 digits
  2018.  
  2019. p1_ploopb:  pop ax                  ;Pop digit
  2020.             mov [di],al             ;Store digit
  2021.             inc di
  2022.             loop p1_ploopb          ;Loop back
  2023.  
  2024.             mov [byte di],0         ;Add the null byte
  2025.  
  2026. p1_done:    popa                    ;Restore registers
  2027.             pop bp                  ;Delete stack frame
  2028.             ret 6                   ;Return
  2029.  
  2030. EndP        fixtoa
  2031.  
  2032. End
  2033.  
  2034. ~~~C_ATOFIX
  2035. Ideal
  2036.  
  2037. Public      atofix
  2038.  
  2039. Model Tiny
  2040. CodeSeg
  2041. P386
  2042.  
  2043. ;****************** atofix() -- Convert string to fixed point number
  2044. ;long atofix(char *strp);
  2045.  
  2046. strp        equ bp+4
  2047.  
  2048. Proc        atofix
  2049.  
  2050.             push bp                 ;Set up stack frame
  2051.             mov bp,sp
  2052.             push bx cx si di bp     ;Save registers
  2053.  
  2054.             mov si,[strp]           ;SI = string
  2055.  
  2056.             xor ax,ax               ;AX = 0
  2057.             xor bh,bh               ;BH = 0
  2058.             mov cx,10               ;CX = 10
  2059.  
  2060. p1_ploop:   mov bl,[si]             ;Load char
  2061.             inc si
  2062.             cmp bl,' '              ;Loop while char is space
  2063.             je p1_ploop             ;(20h, or 09h thru 0Dh)
  2064.             cmp bl,9
  2065.             jna p1_go
  2066.             cmp bl,13
  2067.             jbe p1_ploop
  2068.  
  2069. p1_go:      xor bp,bp               ;BP = 0
  2070.             cmp bl,'+'              ;If char = '+', ignore
  2071.             je p1_loop
  2072.             cmp bl,'-'              ;If char <> '-', keep it
  2073.             jne p1_skip
  2074.             inc bp                  ;Set negative flag
  2075.  
  2076. p1_loop:    mov bl,[si]             ;Load char
  2077.             inc si
  2078.  
  2079. p1_skip:    xor dx,dx               ;Clear DX
  2080.             cmp bl,'.'              ;Decimal point, continue
  2081.             je p1_cont
  2082.             cmp bl,'9'              ;Not a digit, finish
  2083.             ja p1_finish
  2084.             sub bl,'0'
  2085.             jc p1_finish
  2086.  
  2087.             mul cx                  ;Multiply by 10
  2088.             add ax,bx               ;Add in digit...
  2089.             jmp p1_loop             ;Loop back
  2090.  
  2091. p1_cont:    push ax                 ;Save integer part
  2092.             xor ax,ax               ;Zero AX
  2093.             mov di,1                ;DI = 1
  2094.  
  2095. p1_floop:   mov bl,[si]             ;Load char
  2096.             inc si
  2097.  
  2098.             cmp bl,'9'              ;Not a digit, finish
  2099.             ja p1_ffinish
  2100.             sub bl,'0'
  2101.             jc p1_ffinish
  2102.  
  2103.             mul cx                  ;Multiply by 10
  2104.             add ax,bx               ;Add in digit...
  2105.             adc dx,0
  2106.             imul di,10              ;Multiply divisor by 10
  2107.             jnc p1_floop            ;Loop while < 5 digits
  2108.  
  2109.             shr dx,1                ;5 digits, divide by 2
  2110.             rcr ax,1                ;and set DI to 50000
  2111.             mov di,50000            ;instead of 100000
  2112.  
  2113. p1_ffinish: xchg dx,ax              ;Multiply by 65536
  2114.             xor ax,ax
  2115.             div di                  ;Divide by 10^digits
  2116.             xchg dx,ax              ;Fractional part in DX
  2117.             pop ax                  ;Restore integer part
  2118.  
  2119. p1_finish:  xchg dx,ax              ;DX:AX = number
  2120.  
  2121.             dec bp                  ;Positive, don't negate
  2122.             jl p1_done
  2123.  
  2124.             neg dx                  ;Negate the result
  2125.             neg ax
  2126.             sbb dx,0
  2127.  
  2128. p1_done:    pop bp di si cx bx      ;Restore registers
  2129.             pop bp                  ;Delete stack frame
  2130.             ret 2                   ;Return
  2131.  
  2132. EndP        atofix
  2133.  
  2134. End
  2135.  
  2136. ~~~C_BITS
  2137. Ideal
  2138.  
  2139. Public      bitcnt,highbit
  2140.  
  2141. Model Tiny
  2142. P386
  2143. CodeSeg
  2144.  
  2145. ;****************** bitcnt() -- Count set bits in integer
  2146. ;int bitcnt(int x);
  2147.  
  2148. x           equ bp+4
  2149.  
  2150. Proc        bitcnt
  2151.  
  2152.             push bp                 ;Set up stack frame
  2153.             mov bp,sp
  2154.             push bx cx              ;Save registers
  2155.  
  2156.             xor cx,cx               ;CX = 0
  2157.             mov ax,[x]              ;AX = number
  2158.             test ax,ax              ;Zero?
  2159.             jz p1_done
  2160.  
  2161. p1_loop:    mov bx,ax               ;Kill last bit
  2162.             dec bx
  2163.             and ax,bx
  2164.             loopnz p1_loop          ;Loop while not zero
  2165.  
  2166. p1_done:    sub ax,cx               ;Negative of CX
  2167.  
  2168.             pop cx bx               ;Restore registers
  2169.             pop bp                  ;Delete stack frame
  2170.             ret 2                   ;Return
  2171.  
  2172. EndP        bitcnt
  2173.  
  2174. ;****************** highbit() -- Find high bit in integer
  2175. ;int highbit(int x);             returns -1 if it was zero
  2176.  
  2177. x           equ bp+4
  2178.  
  2179. Proc        highbit
  2180.  
  2181.             push bp                 ;Set up stack frame
  2182.             mov bp,sp
  2183.  
  2184.             bsr ax,[x]              ;Scan for bit
  2185.             jnz $+5                 ;No bit set?
  2186.             mov ax,-1               ;Return -1
  2187.  
  2188.             pop bp                  ;Delete stack frame
  2189.             ret 2                   ;Return
  2190.  
  2191. EndP        highbit
  2192.  
  2193. End
  2194.  
  2195. ~~~C_SQRT
  2196. Ideal
  2197.  
  2198. Public      sqrt
  2199.  
  2200. Model Tiny
  2201. P386
  2202. CodeSeg
  2203.  
  2204. ;****************** sqrt() -- Returns the square root of a
  2205. ;                             long.  Result is an integer.
  2206. ;int sqrt(long num);          60-350 clocks (486)
  2207.  
  2208.  
  2209. num         equ bp+4
  2210.  
  2211. Proc        sqrt
  2212.  
  2213.             push bp                 ;Set up stack frame
  2214.             mov bp,sp
  2215.             push cx dx              ;Save registers
  2216.  
  2217.             mov ax,[num]            ;DX:AX = num
  2218.             mov dx,[num+2]
  2219.  
  2220.             mov cx,32               ;32 bits
  2221.  
  2222. p1_bloop:   add ax,ax               ;Find the highest set bit
  2223.             adc dx,dx
  2224.             jc p1_gotbit
  2225.             loop p1_bloop
  2226.  
  2227. p1_gotbit:  mov ax,1                ;CX = first guess 2^(log2(n)/2)
  2228.             shr cx,1
  2229.             shl ax,cl
  2230.             xchg cx,ax
  2231.  
  2232. p1_loop:    mov ax,[num]            ;DX:AX = num
  2233.             mov dx,[num+2]
  2234.             div cx                  ;AX = num/guess
  2235.             add cx,ax               ;CX = (guess+(num/guess))/2
  2236.             shr cx,1
  2237.             sub ax,cx               ;If the difference is 1
  2238.             cmp ax,1                ;or less, then done
  2239.             ja p1_loop              ;Loop back
  2240.  
  2241.             xchg ax,cx              ;AX = result
  2242.             pop dx cx               ;Restore registers
  2243.             pop bp                  ;Delete stack frame
  2244.             ret 4                   ;Return
  2245.  
  2246. EndP        sqrt
  2247.  
  2248. End
  2249.  
  2250. ~~~C_ROMAN
  2251. Ideal
  2252.  
  2253. Public      roman
  2254.  
  2255. Model Tiny
  2256. CodeSeg
  2257. P386
  2258.  
  2259. ;****************** roman() -- Convert integer to Roman Numerals
  2260.  
  2261. num         equ bp+6
  2262. buf         equ bp+4
  2263.  
  2264. Proc        roman
  2265.  
  2266.             push bp                 ;Set up stack frame
  2267.             mov bp,sp
  2268.             pusha                   ;Save all registers
  2269.  
  2270.             mov di,[buf]            ;DI = buffer
  2271.             mov dx,[num]            ;DX = number
  2272.             mov si,offset RNTbl_1   ;SI, BX = tables
  2273.             mov bx,offset RNTbl_2
  2274.  
  2275. p1_loop:    lodsw                   ;Load size
  2276.             test ax,ax              ;Done?
  2277.             jz p1_done
  2278.  
  2279. p1_iloop:   cmp dx,ax
  2280.             jl p1_lb
  2281.             mov cx,[bx]             ;AX = code
  2282.             mov [di],cl             ;Store first char
  2283.             inc di
  2284.  
  2285.             cmp ch,'.'              ;If second char, then
  2286.             je p1_ilb               ; store second char
  2287.             mov [di],ch
  2288.             inc di
  2289.  
  2290. p1_ilb:     sub dx,ax               ;Reduce number
  2291.             jmp p1_iloop            ;Loop back
  2292.  
  2293. p1_lb:      add bx,2                ;Advance pointer
  2294.             jmp p1_loop             ;Loop back
  2295.  
  2296. p1_done:    mov [di],al             ;Terminate string
  2297.  
  2298.             popa                    ;Restore registers
  2299.             pop bp                  ;Delete stack frame
  2300.             ret 4                   ;Return
  2301.  
  2302. EndP        roman
  2303.  
  2304. RNTbl_1     dw 1000,900,500,400,100
  2305.             dw 90,50,40,10,9,5,4,1,0
  2306.  
  2307. RNTbl_2     db 'M.CMD.CDC.XCL.XLX.IXV.IVI.'
  2308.  
  2309. End
  2310.  
  2311. ~~~C_CRC16
  2312. Ideal
  2313.  
  2314. Public      crc16
  2315.  
  2316. Model Tiny
  2317. CodeSeg
  2318. P386
  2319.  
  2320. ;****************** crc16() -- Calculate 16-bit CRC
  2321. ;int crc16(void *ptr, int cnt)
  2322.  
  2323. ptr         equ bp+6
  2324. cnt         equ bp+4
  2325.  
  2326. Proc        crc16
  2327.  
  2328.             push bp                 ;Set up stack frame
  2329.             mov bp,sp
  2330.             push bx cx dx si        ;Save registers
  2331.  
  2332.             mov si,[ptr]            ;SI = pointer
  2333.             mov bx,[cnt]            ;BX = count
  2334.  
  2335.             xor dx,dx               ;Start with 0
  2336.  
  2337. p1_loop:    lodsb                   ;Load byte
  2338.             xor dh,al               ;XOR into result
  2339.             mov cx,8                ;8 bits
  2340.  
  2341. p1_iloop:   add dx,dx               ;Shift left
  2342.             jnc $+5                 ;If bit = 1, then
  2343.             xor dx,1021h            ;XOR in CRC value
  2344.             loop p1_iloop           ;Loop back
  2345.  
  2346.             dec bx                  ;Byte loop
  2347.             jnz p1_loop
  2348.  
  2349.             xchg dx,ax              ;Result in AX
  2350.  
  2351. p1_done:    pop si dx cx bx         ;Restore registers
  2352.             pop bp                  ;Delete stack frame
  2353.             ret 4                   ;Return
  2354.  
  2355. EndP        crc16
  2356.  
  2357. End
  2358.  
  2359. ~~~C_CRC32
  2360. Ideal
  2361.  
  2362. Public      crc32
  2363.  
  2364. Model Tiny
  2365. CodeSeg
  2366. P386
  2367.  
  2368. ;****************** crc32() -- Calculate 32-bit CRC
  2369. ;long crc32(void *ptr, int cnt)
  2370.  
  2371. ptr         equ bp+6
  2372. cnt         equ bp+4
  2373.  
  2374. Proc        crc32
  2375.  
  2376.             push bp                 ;Set up stack frame
  2377.             mov bp,sp
  2378.             push bx cx si di        ;Save registers
  2379.  
  2380.             mov si,[ptr]            ;SI = pointer
  2381.             mov bx,[cnt]            ;BX = count
  2382.  
  2383.             xor dx,dx               ;Start with 0
  2384.             xor di,di
  2385.  
  2386. p1_loop:    lodsb                   ;Load byte
  2387.             xor dh,al               ;XOR into result
  2388.             mov cx,8                ;8 bits
  2389.  
  2390. p1_iloop:   add di,di               ;Shift left
  2391.             adc dx,dx
  2392.             jnc $+8                 ;If bit = 1, then
  2393.             xor dx,04C1h            ;XOR in CRC value
  2394.             xor di,1DB7h
  2395.             loop p1_iloop           ;Loop back
  2396.  
  2397.             dec bx                  ;Byte loop
  2398.             jnz p1_loop
  2399.  
  2400.             xchg di,ax              ;Result in DX:AX
  2401.  
  2402. p1_done:    pop di si cx bx         ;Restore registers
  2403.             pop bp                  ;Delete stack frame
  2404.             ret 4                   ;Return
  2405.  
  2406. EndP        crc32
  2407.  
  2408. End
  2409.