home *** CD-ROM | disk | FTP | other *** search
/ QBasic & Borland Pascal & C / Delphi5.iso / C / Samples / CASM.ARJ / STRINGS.ASM < prev    next >
Assembly Source File  |  1988-05-18  |  14KB  |  709 lines

  1. ;_ strings.asm   Tue May 17 1988   Modified by: Walter Bright */
  2. ;Copyright (C) 1985-1988 by Northwest Software
  3. ;All Rights Reserved
  4. ;Written by Walter Bright
  5.  
  6. include    macros.asm
  7.  
  8. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  9. ; Compare a string.
  10. ; Use:
  11. ;    int strcmp(s1,s2)
  12. ; Returns:
  13. ;    > 0    if s1 > s2
  14. ;    = 0    if s1 == s2
  15. ;    < 0    if s1 < s2
  16. ;
  17.  
  18.     ifdef    Astrcmp
  19.     begcode    strcmp
  20.     c_public    strcmp
  21. func    strcmp
  22.     mov    BX,SP
  23.     if SPTR
  24.     .save    SI
  25.     mov    DX,DI            ;save DI
  26.       ife ESeqDS
  27.     mov    AX,DS
  28.     mov    ES,AX
  29.       endif
  30.     mov     DI,P-2+2[BX]        ;get source pointer (s2)
  31.     mov     SI,P-2[BX]        ;get destination pointer (s1)
  32.     else
  33.     .save    <SI,DI>
  34.     mov    DX,DS
  35.     les     DI,SS:P-2+4[BX]        ;get source pointer (s2)
  36.     lds    SI,SS:P-2[BX]        ;get destination pointer (s1)
  37.     endif
  38.     clr    AX            ;scan for 0
  39.     mov    CX,-1            ;largest possible string
  40.     cld                ;direction flag = increment
  41.     repne    scasb
  42.     not    CX            ;CX = string length of s2
  43.     sub    DI,CX            ;point DI back to beginning
  44.     repe    cmpsb            ;compare string
  45.     je    L1            ;strings are equal
  46.     if 0
  47.     jae    L2            ;s1 < s2
  48.     inc    AX            ;s1 > s2
  49.     jmps    L1
  50.  
  51. L2:    dec    AX            ;AX = -1
  52.     else
  53.     sbb    AX,AX
  54.     cmc
  55.     adc    AX,0
  56.     endif
  57. L1:
  58.     if SPTR
  59.     mov    DI,DX
  60.     .restore SI
  61.     else
  62.     mov    DS,DX
  63.     .restore <DI,SI>
  64.     endif
  65.     ret                                        
  66. c_endp    strcmp
  67.     endcode    strcmp
  68.     endif
  69.  
  70. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  71. ; Compare a string of at most n chars (unsigned).
  72. ; Use:
  73. ;    int strncmp(s1,s2,n)
  74. ; Returns:
  75. ;    > 0    if s1 > s2
  76. ;    = 0    if s1 == s2
  77. ;    < 0    if s1 < s2
  78. ;
  79.  
  80.     ifdef    Astrncmp
  81.     begcode    strncmp
  82.     c_public    strncmp
  83. func    strncmp
  84.     push    BP                                 
  85.     mov     BP,SP                              
  86.     .save    <SI,DI>
  87.     if SPTR
  88.       ife ESeqDS
  89.     mov    AX,DS
  90.     mov    ES,AX
  91.       endif
  92.     mov     DI,P+2[BP]        ;get source pointer (s2)
  93.     mov     SI,P[BP]        ;get destination pointer (s1)
  94.     else
  95.     mov    BX,DS
  96.     les     DI,P+4[BP]        ;get source pointer (s2)
  97.     lds    SI,P[BP]        ;get destination pointer (s1)
  98.     endif
  99.     clr    AX            ;scan for 0
  100.     mov    CX,-1            ;largest possible string
  101.     cld                ;direction flag = increment
  102.     repne    scasb
  103.     not    CX            ;CX = string length of s2
  104.     sub    DI,CX            ;point DI back to beginning
  105.     if SPTR
  106.     .if    CX b P+4[BP], L5
  107.     mov    CX,P+4[BP]        ;CX = min(CX,n)
  108.     else
  109.     .if    CX b P+8[BP], L5
  110.     mov    CX,P+8[BP]        ;CX = min(CX,n)
  111.     endif
  112. L5:    repe    cmpsb            ;compare string
  113.     je    L3            ;strings are equal
  114.     if 0
  115.     jae    L4            ;s1 < s2
  116.     inc    AX            ;s1 > s2
  117.     jmps    L3
  118.  
  119. L4:    dec    AX            ;AX = -1
  120.     else
  121.     sbb    AX,AX
  122.     cmc
  123.     adc    AX,0
  124.     endif
  125. L3:
  126.     if LPTR
  127.     mov    DS,BX
  128.     endif
  129.     .restore <DI,SI>
  130.     pop     BP                                 
  131.     ret                                        
  132. c_endp    strncmp
  133.     endcode    strncmp
  134.     endif
  135.  
  136. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  137. ; Compare an array of n bytes (unsigned).
  138. ; Use:
  139. ;    int memcmp(s1,s2,n)
  140. ; Returns:
  141. ;    > 0    if s1 > s2
  142. ;    = 0    if s1 == s2
  143. ;    < 0    if s1 < s2
  144. ;
  145.  
  146.     ifdef    Amemcmp
  147.     begcode    memcmp
  148.     c_public    memcmp
  149. func    memcmp
  150.     push    BP                                 
  151.     mov     BP,SP                              
  152.     .save    <SI,DI>
  153.     if SPTR
  154.       ife ESeqDS
  155.     mov    AX,DS
  156.     mov    ES,AX
  157.       endif
  158.     mov    DI,P+2[BP]        ;get source pointer (s2)
  159.     mov     SI,P[BP]        ;get destination pointer (s1)
  160.     else
  161.     mov    BX,DS
  162.     les     DI,P+SIZEPTR[BP]    ;get source pointer (s2)
  163.     lds    SI,P[BP]        ;get destination pointer (s1)
  164.     endif
  165.     mov    CX,P+SIZEPTR+SIZEPTR[BP]        ;CX = n
  166.     clr    AX
  167.     cld
  168.     repe    cmpsb            ;compare string
  169.     je    L3            ;strings are equal
  170.     if 0
  171.     jae    L4            ;s1 < s2
  172.     inc    AX            ;s1 > s2
  173.     jmps    L3
  174.  
  175. L4:    dec    AX            ;AX = -1
  176.     else
  177.     sbb    AX,AX
  178.     cmc
  179.     adc    AX,0
  180.     endif
  181. L3:
  182.     if LPTR
  183.     mov    DS,BX
  184.     endif
  185.     .restore <DI,SI>
  186.     pop     BP                                 
  187.     ret                                        
  188. c_endp    memcmp
  189.     endcode    memcmp
  190.     endif
  191.  
  192. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  193. ; Calculate length of string and return it.
  194. ;    int strlen(s)
  195.  
  196.     ifdef    Astrlen
  197.     begcode    strlen
  198.     c_public    strlen
  199. func    strlen
  200.     mov    BX,SP
  201.     mov    DX,DI            ;save DI
  202.     if SPTR
  203.       ife ESeqDS
  204.     mov    AX,DS
  205.     mov    ES,AX
  206.       endif
  207.     mov     DI,P-2[BX]        ;DI = s
  208.     else
  209.     les    DI,SS:P-2[BX]
  210.     endif
  211.     clr    AX            ;scan for 0
  212.     mov    CX,-1            ;largest possible string
  213.     cld                ;direction flag = increment
  214.     repne    scasb
  215.     mov    AX,CX
  216.     not    AX            ;AX = string length
  217.     dec    AX
  218.     mov    DI,DX
  219.     ret                                        
  220. c_endp    strlen
  221.     endcode    strlen
  222.     endif
  223.  
  224. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  225. ; Cat s2 to s1 till a zero byte.
  226. ; Use:
  227. ;    char *strcat(s1,s2)
  228. ; Returns:
  229. ;    s1
  230. ;
  231.     ifdef    Astrcat
  232.     begcode    strcat
  233.     c_public    strcat
  234. func    strcat
  235.     push    BP                                 
  236.     mov     BP,SP                              
  237.     .save    <SI,DI>
  238.     if SPTR
  239.       ife ESeqDS
  240.     mov    AX,DS
  241.     mov    ES,AX
  242.       endif
  243.     mov     SI,P+2[BP]        ;get source pointer
  244.     mov     DI,P[BP]        ;get destination pointer
  245.     else
  246.     push    DS
  247.     les    DI,P[BP]        ;get destination pointer (s1)
  248.     endif
  249.     mov    BX,DI            ;save it
  250.     clr    AX            ;scan for 0
  251.     mov    CX,-1            ;largest possible string
  252.     cld                ;direction flag = increment
  253.     repne    scasb            ;find end of s1
  254.     dec    DI            ;DI -> EOS of s1
  255.     mov    DX,DI
  256.     if SPTR
  257.     mov    DI,SI            ;DI -> s2
  258.     else
  259.     les    DI,P+4[BP]        ;ES:DI = s2
  260.     endif
  261.     mov    CX,-1
  262.     repne    scasb
  263.     not    CX            ;CX = strlen(s2) + 1 (for EOS)
  264.     mov    DI,DX            ;DI -> end of s1
  265.     if SPTR
  266.     rep    movsb            ;transfer bytes (including EOS)
  267.     mov    AX,BX            ;return pointer to s1
  268.     else
  269.     mov    ES,P+2[BP]        ;ES:DI -> end of s1
  270.     lds     SI,P+4[BP]        ;get source pointer (s2)
  271.     rep    movsb            ;transfer bytes (including EOS)
  272.       ifdef MSC
  273.     mov    AX,BX
  274.     mov    DX,ES            ;DX,AX points to s1
  275.       else
  276.     mov    AX,ES            ;AX,BX points to s1
  277.       endif
  278.     pop    DS
  279.     endif
  280.     .restore <DI,SI>
  281.     pop    BP
  282.     ret                                        
  283. c_endp    strcat
  284.     endcode    strcat
  285.     endif
  286.  
  287. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  288. ; Cat s2 to s1 till a zero byte or n bytes are copied.
  289. ; Use:
  290. ;    char *strncat(char *s1,char *s2,unsigned n)
  291. ; Returns:
  292. ;    s1
  293. ;
  294.     ifdef    Astrncat
  295.     begcode    strncat
  296.     c_public    strncat
  297. func    strncat
  298.     push    BP                                 
  299.     mov     BP,SP                              
  300.     .save    <SI,DI>
  301.     if SPTR
  302.       ife ESeqDS
  303.     mov    AX,DS
  304.     mov    ES,AX
  305.       endif
  306.     mov     SI,P+2[BP]        ;get source pointer (s2)
  307.     mov     DI,P[BP]        ;get destination pointer (s1)
  308.     else
  309.     push    DS
  310.     les    DI,P[BP]        ;get destination pointer (s1)
  311.     mov    BX,DI            ;set up offset of return value (s1)
  312.     endif
  313.     clr    AX            ;scan for 0
  314.     mov    CX,-1            ;largest possible string
  315.     cld                ;direction flag = increment
  316.     repne    scasb            ;find end of s1
  317.     dec    DI            ;point at terminating 0
  318.     mov    DX,DI            ;save
  319.     if SPTR
  320.     mov    DI,SI            ;DI -> s2
  321.     else
  322.     les    DI,P+SIZEPTR[BP]    ;ES:DI -> s2
  323.     endif
  324.     mov    CX,-1
  325.     repne    scasb
  326.     not    CX
  327.     dec    CX            ;CX = strlen(s2)
  328.     .if    CX b P+SIZEPTR+SIZEPTR[BP], L6
  329.     mov    CX,P+SIZEPTR+SIZEPTR[BP]    ;CX = min(CX,n)
  330. L6:    mov    DI,DX            ;DI -> end of s1
  331.     if LPTR
  332.     mov    ES,P+2[BP]        ;ES = segment of s1
  333.     lds    SI,P+SIZEPTR[BP]    ;DS:SI -> s2
  334.     endif
  335.     rep    movsb            ;transfer bytes
  336.     stosb                ;terminate with a 0
  337.     if SPTR
  338.     mov    AX,P[BP]        ;return pointer to s1
  339.     else
  340.       ifdef MSC
  341.     mov    AX,BX
  342.     mov    DX,ES            ;DX,AX = s1
  343.       else
  344.     mov    AX,ES            ;AX,BX = s1
  345.       endif
  346.     pop    DS
  347.     endif
  348.     .restore <DI,SI>
  349.     pop    BP
  350.     ret                                        
  351. c_endp    strncat
  352.     endcode    strncat
  353.     endif
  354.  
  355. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  356. ; Copy s2 to s1 till a zero byte.
  357. ; Use:
  358. ;    char *strcpy(s1,s2)
  359. ;
  360.     ifdef    Astrcpy
  361.     begcode    strcpy
  362.     c_public    strcpy
  363. func    strcpy
  364.     if SPTR
  365.     mov     BX,SP                              
  366.     .save    SI
  367.     mov    DX,DI
  368.       ife ESeqDS
  369.     mov    AX,DS
  370.     mov    ES,AX
  371.       endif
  372.     mov     DI,P-2+2[BX]        ;get source pointer (s2)
  373.     mov    SI,DI            ;save it
  374.     clr    AX            ;scan for 0
  375.     mov    CX,-1            ;largest possible string
  376.     cld                ;direction flag = increment
  377.     repne    scasb            ;find end of s2
  378.     not    CX            ;CX = strlen(s2) + 1 (for EOS)
  379.     mov    DI,P-2[BX]        ;DI -> s1
  380.     mov    AX,DI            ;return value
  381.     rep    movsb            ;transfer bytes (including EOS)
  382.     mov    DI,DX
  383.     .restore SI
  384.     else
  385.     mov    BX,SP                              
  386.     .save    <SI,DI>
  387.     les    DI,SS:P-2+4[BX]        ;ES:DI = s2
  388.     clr    AX            ;scan for 0
  389.     mov    CX,-1            ;largest possible string
  390.     cld                ;direction flag = increment
  391.     repne    scasb            ;find end of s2
  392.     not    CX            ;CX = strlen(s2) + 1 (for EOS)
  393.     mov    DX,DS
  394.     les    DI,SS:P-2[BX]
  395.     lds    SI,SS:P-2+4[BX]
  396.     mov    AX,DI            ;return value is s1
  397.     rep    movsb
  398.     mov    DS,DX
  399.     .restore <DI,SI>
  400.     mov    DX,ES
  401.     endif
  402.     ret                                        
  403. c_endp    strcpy
  404.     endcode    strcpy
  405.     endif
  406.  
  407. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  408. ; Copy exactly n chars from s2 to s1, padding with nulls if necessary.
  409. ; Use:
  410. ;    char *strncpy(s1,s2,n)
  411. ;
  412.     ifdef    Astrncpy
  413.     begcode    strncpy
  414.     c_public    strncpy
  415. func    strncpy
  416.     push    BP                                 
  417.     mov     BP,SP                              
  418.     .save    <SI,DI>
  419.     if SPTR
  420.       ife ESeqDS
  421.     mov    AX,DS
  422.     mov    ES,AX
  423.       endif
  424.     mov     DI,P+2[BP]        ;get source pointer
  425.     mov    BX,DI            ;save it
  426.     else
  427.     les    DI,P+4[BP]
  428.     endif
  429.     clr    AX            ;scan for 0
  430.     mov    CX,-1            ;largest possible string
  431.     cld                ;direction flag = increment
  432.     repne    scasb            ;find end of s2
  433.     not    CX            ;CX = strlen(s2) + 1 (for EOS)
  434.     if SPTR
  435.     mov    DX,P+4[BP]        ;DX = n
  436.     else
  437.     mov    DX,P+8[BP]
  438.     endif
  439.     .if    DX ae CX, L7        ;if n >= strlen(s2) + 1
  440.     mov    CX,DX            ;CX = min(CX,n)
  441. L7:    sub    DX,CX            ;DX = # of nulls to pad
  442.     if SPTR
  443.     mov    DI,P[BP]        ;DI -> s1
  444.     mov    SI,BX            ;SI -> s2
  445.     else
  446.     push    DS
  447.     les    DI,P[BP]
  448.     mov    BX,DI            ;for return value
  449.     lds    SI,P+4[BP]
  450.     endif
  451.     rep    movsb            ;transfer bytes (including EOS)
  452.     mov    CX,DX            ;# of nulls to pad
  453.     clr    AL
  454.     rep    stosb
  455.     if SPTR
  456.     mov    AX,P[BP]        ;return value
  457.     else
  458.       ifdef MSC
  459.     mov    AX,BX
  460.     mov    DX,ES
  461.       else
  462.     mov    AX,ES
  463.       endif
  464.     pop    DS
  465.     endif
  466.     .restore <DI,SI>
  467.     pop    BP
  468.     ret                                        
  469. c_endp    strncpy
  470.     endcode    strncpy
  471.     endif
  472.  
  473. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  474. ; Set n bytes in s to c.
  475. ;    char *memset(char *p,int c,int n)
  476. ; Returns:
  477. ;    p
  478.  
  479.     ifdef    Amemset
  480.     begcode    memset
  481.     c_public    memset
  482. func    memset
  483.     push    BP
  484.     mov    BP,SP
  485.     .save    <DI>
  486.     if SPTR
  487.       ife ESeqDS
  488.     mov    AX,DS
  489.     mov    ES,AX
  490.       endif
  491.     mov    DI,P[BP]    ;p
  492.     mov    AL,P+2[BP]    ;c
  493.     mov    CX,P+4[BP]    ;n
  494.     cld
  495.     rep    stosb
  496.     mov    AX,P[BP]    ;original value of p
  497.     else
  498.     les    DI,P[BP]    ;p
  499.     mov    BX,DI
  500.     mov    AL,P+4[BP]    ;c
  501.     mov    CX,P+6[BP]    ;n
  502.     cld
  503.     rep    stosb
  504.       ifdef MSC
  505.     mov    AX,BX
  506.     mov    DX,ES        ;return original value of p in DX,AX
  507.       else
  508.     mov    AX,ES        ;return original value of p in AX,BX
  509.       endif
  510.     endif
  511.     .restore <DI>
  512.     pop    BP
  513.     ret
  514. c_endp    memset
  515.     endcode    memset
  516.     endif
  517.  
  518. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  519. ; Copy n bytes from p2 to p1.
  520. ;    void *memcpy(void *p1,void *p2,n)
  521. ; Returns:
  522. ;    p1
  523.  
  524.     ifdef Amemcpy
  525.     c_public    memcpy
  526.     begcode    memcpy
  527.  
  528.     c_public    memmove        ;alternate entry point
  529. func    memmove
  530. c_endp    memmove
  531.  
  532. func    memcpy
  533.     mov    BX,SP
  534.     if SPTR
  535.     mov    CX,P-2+SIZEPTR+SIZEPTR[BX]    ;CX = n
  536.       ife ESeqDS
  537.     mov    AX,DS
  538.     mov    ES,AX
  539.       endif
  540.     mov    DX,SI            ;save SI
  541.     mov    SI,P-2+SIZEPTR[BX]    ;p2
  542.     mov    AX,P-2[BX]        ;p1
  543.     else
  544.     mov    CX,SS:P-2+SIZEPTR+SIZEPTR[BX]    ;CX = n
  545.     .save    SI
  546.     mov    DX,DS
  547.     lds    SI,SS:P-2+SIZEPTR[BX]    ;DS:SI = p2
  548.     les    AX,SS:P-2[BX]        ;ES:DI = p1
  549.     endif
  550.     mov    BX,DI            ;save DI
  551.     mov    DI,AX            ;AX = original offset value of p1
  552.     .if    SI b DI, M1        ;if reverse copy is necessary
  553.     cld
  554.     shr    CX,1
  555.     jz    M2            ;if n is 0 or 1
  556.     rep    movsw
  557. M2:    jnc    M5            ;if n is even
  558.     movsb
  559. M5:
  560.     if SPTR
  561.     mov    SI,DX
  562.     else
  563.     mov    DS,DX
  564.     mov    DX,ES            ;DX:AX = original value of p1
  565.     .restore SI
  566.     endif
  567.     mov    DI,BX
  568.     ret
  569.  
  570. M1:    add    SI,CX
  571.     dec    SI
  572.     add    DI,CX
  573.     dec    DI
  574.     std                ;reverse direction of copy
  575.     shr    CX,1
  576.     jnc    M6
  577.     movsb
  578. M6:    jcxz    M7
  579.     dec    SI
  580.     dec    DI
  581.     rep    movsw
  582. M7:    cld
  583.     jmps    M5
  584.  
  585. c_endp    memcpy
  586.     endcode    memcpy
  587.     endif
  588.  
  589. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  590. ; Return pointer to first occurrence of char c in string s.
  591. ;    char *index(s,c)
  592. ;    char *s,c;
  593.  
  594.     ifdef    Aindex
  595.     begcode    strchr
  596.     c_public index,strchr
  597.  
  598. func    strchr
  599. c_endp    strchr
  600.  
  601. func    index
  602.     push    BP                                 
  603.     mov     BP,SP                              
  604.     .save    <DI>
  605.     cld
  606.     if SPTR
  607.       ife ESeqDS
  608.     mov    AX,DS
  609.     mov    ES,AX
  610.       endif
  611.     mov    DI,P[BP]        ;DI = s
  612.     else
  613.     les    DI,P[BP]        ;ES:DI = s
  614.     endif
  615.     clr    AX
  616.     mov    CX,-1
  617.     repne    scasb
  618.     not    CX            ;CX = length of s (including NULL)
  619.     sub    DI,CX            ;DI = s
  620.     if SPTR
  621.     mov    AL,P+2[BP]        ;AL = c
  622.     else
  623.     mov    AL,P+4[BP]        ;AL = c
  624.     endif
  625.     repne    scasb            ;scan for c
  626.     mov    AX,0            ;assume we didn't find it
  627.     if SPTR
  628.     jnz    L8            ;didn't find it
  629.     mov    AX,DI            ;yes, found it
  630.     dec    AX
  631.     else
  632.       ifdef MSC
  633.     cwd
  634.     jnz    L8
  635.     mov    DX,ES
  636.     mov    AX,DI
  637.     dec    AX
  638.       else
  639.     mov    BX,AX
  640.     jnz    L8
  641.     mov    AX,ES
  642.     mov    BX,DI
  643.     dec    BX
  644.       endif
  645.     endif
  646. L8:    .restore <DI>
  647.     pop    BP
  648.     ret     
  649. c_endp    index                                   
  650.     endcode    strchr
  651.     endif
  652.  
  653. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  654. ; Compare strings just like strcmp(), except that case is ignored.
  655.  
  656.     ifdef Astrcmpl
  657.     begcode    strcmpl
  658.     c_public    strcmpl
  659. func    strcmpl
  660.     push    BP
  661.     mov    BP,SP
  662.     .save    SI
  663.     if SPTR
  664.     mov    SI,P[BP]
  665.     mov    BX,P+SIZEPTR[BP]
  666.     else
  667.     push    DS
  668.     lds    SI,P[BP]        ;DS:SI -> p1
  669.     les    BX,P+SIZEPTR[BP]    ;ES:BX -> p2
  670.     endif
  671.     cld
  672. L1:    lodsb                ;AL = *p1++
  673.     if SPTR
  674.     mov    CL,[BX]
  675.     else
  676.     mov    CL,ES:[BX]
  677.     endif
  678.     inc    BX            ;CL = *p2++
  679.     .if    AL ne CL, L2        ;strings are different at this char
  680.     tst    AL            ;end of string?
  681.     jnz    L1            ;no
  682.     jmps    L3
  683.  
  684. L2:    ;Perhaps when converted to lower case, they will be the same
  685.     .if    AL b 'A', L4
  686.     .if    AL a 'Z', L4
  687.     add    AL,'a' - 'A'        ;convert AL to lower case
  688. L4:    .if    CL b 'A', L5
  689.     .if    CL a 'Z', L5
  690.     add    CL,'a' - 'A'        ;convert CL to lower case
  691. L5:    .if    AL e CL, L1        ;same now, so continue looping
  692.  
  693. L3:    clr    AH
  694.     clr    CH
  695.     sub    AX,CX
  696.     if LPTR
  697.     pop    DS
  698.     endif
  699.     .restore SI
  700.     pop    BP
  701.     ret
  702. c_endp    strcmpl
  703.     endcode    strcmpl
  704.     endif
  705.  
  706.     end
  707.  
  708.  
  709.