home *** CD-ROM | disk | FTP | other *** search
/ High Voltage Shareware / high1.zip / high1 / DIR13 / OS2ASM.ZIP / STRINGS.ASM < prev   
Assembly Source File  |  1991-09-05  |  16KB  |  825 lines

  1. ;_ strings.asm     Modified by Joe Huffman November 6, 1990
  2. ;Copyright (C) 1985-1989 by Walter Bright
  3. ;All Rights Reserved
  4. ;Written by Walter Bright
  5.  
  6. ;CAUTION!  This code is highly optimized.  It does not fully utilize the
  7. ;macros 'uses' and 'unuse' for register preservation.  If registers other than
  8. ;EBX, ESI, and EDI (and of course EBP,DS, and ES) must be preserved examine 
  9. ;this module carefully.
  10.  
  11. include macros.asm
  12.  
  13. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  14. ; Compare a string.
  15. ; Use:
  16. ;    int strcmp(s1,s2)
  17. ; Returns:
  18. ;    > 0    if s1 > s2
  19. ;    = 0    if s1 == s2
  20. ;    < 0    if s1 < s2
  21. ;
  22.  
  23.     ifdef    Astrcmp
  24.     begcode strcmp
  25. public    _strcmp
  26. _strcmp proc    near
  27.     push    esi            ;save ESI
  28.     mov    edx,edi            ;save EDI
  29.  
  30. ife ESeqDS
  31.     mov    ax,ds
  32.     mov    es,ax
  33. endif
  34.  
  35.     mov    edi,P+SIZEPTR[esp]    ;get source pointer (s2)
  36.     mov    esi,P[esp]        ;get destination pointer (s1)
  37.  
  38.     clr    eax            ;scan for 0
  39.     mov    ecx,eax
  40.     dec    ecx            ;largest possible string (ECX = -1)
  41.     cld
  42.     repne    scasb
  43.     not    ecx            ;CX = string length of s2
  44.     sub    edi,ecx            ;point DI back to beginning
  45.     repe    cmpsb            ;compare string
  46.     je    short L1        ;strings are equal
  47.  
  48.     sbb    eax,eax
  49.     cmc
  50.     adc    eax,0
  51.  
  52. L1:
  53.     mov    edi,edx
  54.     pop    esi
  55.     ret
  56.  
  57. _strcmp endp
  58.     endcode strcmp
  59.     endif
  60.  
  61. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  62. ; Compare a string of at most n chars (unsigned).
  63. ; Use:
  64. ;    int strncmp(s1,s2,n)
  65. ; Returns:
  66. ;    > 0    if s1 > s2
  67. ;    = 0    if s1 == s2
  68. ;    < 0    if s1 < s2
  69. ;
  70.  
  71.     ifdef    Astrncmp
  72.     begcode strncmp
  73.     public    _strncmp
  74. _strncmp    proc    near
  75.     push    ebp
  76.     mov    ebp,esp
  77.     uses    <ecx,edx,esi,edi>
  78.  
  79. ife ESeqDS
  80.     mov    ax,ds
  81.     mov    es,ax
  82. endif
  83.  
  84.     mov    edi,P+SIZEPTR[ebp]    ;get source pointer (s2)
  85.     mov    esi,P[ebp]        ;get destination pointer (s1)
  86.     clr    eax            ;scan for 0
  87.     mov    ecx,eax
  88.     dec    ecx            ;largest possible string (ECX = -1)
  89.     cld
  90.     repne    scasb
  91.     not    ecx            ;ECX = string length of s2
  92.     sub    edi,ecx            ;point EDI back to beginning
  93.  
  94.     mov    edx,P+(2*SIZEPTR)[ebp]
  95.     _if    ecx b edx,L5
  96.     mov    ecx,edx            ;ECX = min(ECX,n)
  97.  
  98. L5:    tst    eax            ;Set ZF.
  99.     repe    cmpsb            ;compare string
  100.     je    short L3        ;strings are equal
  101.     sbb    eax,eax
  102.     cmc
  103.     adc    eax,0
  104. L3:
  105.     unuse    <edi,esi,edx,ecx>
  106.     pop    ebp
  107.     ret
  108. _strncmp    endp
  109.     endcode strncmp
  110.     endif
  111.  
  112. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  113. ; Compare an array of n bytes (unsigned).
  114. ; Use:
  115. ;    int memcmp(s1,s2,n)
  116. ; Returns:
  117. ;    > 0    if s1 > s2
  118. ;    = 0    if s1 == s2
  119. ;    < 0    if s1 < s2
  120. ;
  121.  
  122.     ifdef    Amemcmp
  123.     begcode memcmp
  124.     public    _memcmp
  125. _memcmp proc    near
  126.     push    ebp
  127.     mov    ebp,esp
  128.     uses    <ecx,esi,edi>
  129.  
  130. ife ESeqDS
  131.     mov    ax,ds
  132.     mov    es,ax
  133. endif
  134.  
  135.     mov    edi,P+SIZEPTR[ebp]    ;get source pointer (s2)
  136.     mov    esi,P[ebp]        ;get destination pointer (s1)
  137.     mov    ecx,P+(2*SIZEPTR)[ebp]    ;ECX = n
  138.     clr    eax
  139.     cld
  140.     repe    cmpsb            ;compare string
  141.     je    short L3        ;strings are equal
  142.     sbb    eax,eax
  143.     cmc
  144.     adc    eax,0
  145. L3:
  146.     unuse    <edi,esi,ecx>
  147.     pop    ebp
  148.     ret
  149. _memcmp endp
  150.     endcode memcmp
  151.     endif
  152.  
  153. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  154. ; Calculate length of string and return it.
  155. ;    int strlen(s)
  156.  
  157.     ifdef    Astrlen
  158.     begcode strlen
  159.     public     _strlen
  160.  
  161. _strlen proc    near
  162.     mov    edx,edi            ;save EDI
  163.     mov    edi,PS[esp]        ;EDI = s
  164.  
  165. ife ESeqDS
  166.     mov    ax,ds
  167.     mov    es,ax
  168. endif
  169.  
  170.     clr    eax            ;scan for 0
  171.     mov    ecx,eax
  172.     dec    ecx            ;largest possible string (ECX = -1)
  173.     cld
  174.     repne    scasb
  175.     mov    eax,ecx
  176.     not    eax            ;EAX = string length
  177.     dec    eax
  178.     mov    edi,edx            ;Restore EDI
  179.     ret
  180. _strlen endp
  181.     endcode strlen
  182.     endif
  183.  
  184. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  185. ; Cat s2 to s1 till a zero byte.
  186. ; Use:
  187. ;    char *strcat(s1,s2)
  188. ; Returns:
  189. ;    s1
  190. ;
  191.     ifdef    Astrcat
  192.     begcode strcat
  193.     public    _strcat
  194. _strcat proc    near
  195.     push    ebp
  196.     mov    ebp,esp
  197.     uses    <ecx,ebx,edx,esi,edi>
  198.  
  199.     mov    edi,P+SIZEPTR[ebp]    ;s2
  200.  
  201. ife ESeqDS
  202.     mov    ax,ds
  203.     mov    es,ax
  204. endif
  205.  
  206.     clr    eax            ;scan for 0
  207.     mov    ecx,eax
  208.     dec    ecx            ;largest possible string (ECX = -1)
  209.     cld
  210.     repne    scasb            ;find end of s1
  211.     not    ecx            ;ECX = strlen(s2) + 1 (for EOS)
  212.     sub    edi,ecx            ;back up EDI to start of s2
  213.  
  214.     mov    edx,ecx            ;EDX = strlen(s2)
  215.     mov    ecx,eax
  216.     dec    ecx            ;ECX = -1
  217.     mov    esi,edi
  218.     mov    edi,P[ebp]        ;EDI = s1
  219.     mov    ebx,edi            ;EBX = s1
  220.     repne    scasb
  221.     dec    edi            ;EDI -> EOS of s1
  222.     mov    ecx,edx            ;ECX = strlen(s2)
  223.     shr    ecx,2
  224.     rep    movsd
  225.     mov    ecx,3
  226.     and    ecx,edx
  227.     rep    movsb            ;transfer bytes (including EOS)
  228.     mov    eax,ebx            ;return pointer to s1
  229.  
  230.     unuse    <edi,esi,edx,ebx,ecx>
  231.     pop    ebp
  232.     ret
  233. _strcat endp
  234.     endcode strcat
  235.     endif
  236.  
  237. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  238. ; Cat s2 to s1 till a zero byte or n bytes are copied.
  239. ; Use:
  240. ;    char *strncat(char *s1,char *s2,unsigned n)
  241. ; Returns:
  242. ;    s1
  243. ;
  244.     ifdef    Astrncat
  245.     begcode strncat
  246.     public    _strncat
  247. _strncat    proc    near
  248.     push    ebp
  249.     mov    ebp,esp
  250.     uses    <ecx,edx,esi,edi>
  251.  
  252.     mov    esi,P+SIZEPTR[ebp]    ;get source pointer (s2)
  253.     mov    edi,P[ebp]        ;get destination pointer (s1)
  254.  
  255. ife ESeqDS
  256.     mov    ax,ds
  257.     mov    es,ax
  258. endif
  259.  
  260.     clr    eax            ;scan for 0
  261.     mov    ecx,eax
  262.     dec    ecx            ;largest possible string (ECX = -1)
  263.     cld
  264.     repne    scasb            ;find end of s1
  265.     dec    edi            ;point at terminating 0
  266.     mov    edx,edi            ;save end of s1
  267.     mov    edi,esi            ;EDI -> s2
  268.     mov    ecx,eax
  269.     dec    ecx            ;ECX = -1
  270.     repne    scasb
  271.     not    ecx
  272.     dec    ecx            ;ECX = strlen(s2)
  273.  
  274.     mov    edi,edx            ;EDI -> end of s1
  275.  
  276.     mov    edx,P+SIZEPTR+SIZEPTR[ebp]
  277.     _if    ecx b edx, L6
  278.     mov    ecx,edx            ;ECX = min(ECX,n)
  279. L6:    mov    edx,ecx
  280.     shr    ecx,2
  281.     rep    movsd
  282.     mov    cl,3
  283.     and    ecx,edx
  284.     rep    movsb            ;transfer bytes
  285.     stosb                ;terminate with a 0
  286.     mov    eax,P[ebp]        ;return pointer to s1
  287.  
  288.     unuse    <edi,esi,ecx,edx>
  289.     pop    ebp
  290.     ret
  291.  
  292. _strncat    endp
  293.     endcode strncat
  294.     endif
  295.  
  296. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  297. ; Copy s2 to s1 till a zero byte.
  298. ; Use:
  299. ;    char *strcpy(s1,s2)
  300. ;
  301.     ifdef    Astrcpy
  302.     begcode strcpy
  303.     public    _strcpy
  304. _strcpy proc    near
  305.     push    esi
  306.     mov    edx,edi
  307.     mov    edi,P+SIZEPTR[esp]    ;get source pointer (s2)
  308.     mov    esi,edi            ;save it
  309.  
  310. ife ESeqDS
  311.     mov    ax,ds
  312.     mov    es,ax
  313. endif
  314.  
  315.     clr    eax            ;scan for 0
  316.     mov    ecx,eax
  317.     dec    ecx            ;largest possible string (ECX = -1)
  318.     cld
  319.     repne    scasb            ;find end of s2
  320.     not    ecx            ;ECX = strlen(s2) + 1 (for EOS)
  321.     mov    eax,P[esp]        ;return value (s1)
  322.     mov    edi,eax            ;EDI -> s1
  323.     rep    movsb            ;transfer bytes (including EOS)
  324.     mov    edi,edx
  325.     pop    esi
  326.     ret
  327. _strcpy endp
  328.     endcode strcpy
  329.     endif
  330.  
  331. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  332. ; Copy s2 to s1 till a zero byte.
  333. ; Use:
  334. ;    char *stpcpy(char *s1,const char *s2)
  335. ; Returns:
  336. ;    pointer to terminating NUL
  337. ; Written by Bob Stout and Walter Bright
  338. ; Modified by Joe Huffman June 25, 1990
  339.  
  340.     ifdef    Astpcpy
  341.     begcode stpcpy
  342.     public    _stpcpy
  343. _stpcpy proc    near
  344.     push    esi
  345.     mov    edx,edi
  346.     mov    edi,P+SIZEPTR[esp]    ;get source pointer (s2)
  347.     mov    esi,edi            ;save it
  348.  
  349. ife ESeqDS
  350.     mov    ax,ds
  351.     mov    es,ax
  352. endif
  353.  
  354.     clr    eax            ;scan for 0
  355.     mov    ecx,eax
  356.     dec    ecx            ;largest possible string (ECX = -1)
  357.     cld
  358.     repne    scasb            ;find end of s2
  359.     not    ecx            ;ECX = strlen(s2) + 1 (for EOS)
  360.     mov    edi,P[esp]        ;EDI -> s1
  361.     mov    eax,ecx            ;return value
  362.     add    eax,edi
  363.     mov    edx,ecx
  364.     shr    ecx,2
  365.     rep    movsd
  366.     mov    cl,3
  367.     and    ecx,edx
  368.     rep    movsb            ;transfer bytes (including EOS)
  369.     mov    eax,edi
  370.     dec    eax            ;EAX = s1 + strlen(s2)
  371.     mov    edi,edx
  372.     pop    esi
  373.     ret
  374. _stpcpy endp
  375.     endcode stpcpy
  376.     endif
  377.  
  378. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  379. ; Copy exactly n chars from s2 to s1, padding with nulls if necessary.
  380. ; Use:
  381. ;    char *strncpy(s1,s2,n)
  382. ;
  383.     ifdef    Astrncpy
  384.     begcode strncpy
  385.     public    _strncpy
  386. _strncpy    proc    near
  387.     push    ebp
  388.     mov    ebp,esp
  389.     uses    <ebx,ecx,edx,esi,edi>
  390.  
  391.     mov    edi,P+SIZEPTR[ebp]    ;get source pointer
  392.     mov    ebx,edi            ;save it
  393.  
  394. ife ESeqDS
  395.     mov    ax,ds
  396.     mov    es,ax
  397. endif
  398.  
  399.     clr    eax            ;scan for 0
  400.     mov    ecx,eax
  401.     dec    ecx            ;largest possible string (ECX = -1)
  402.     cld
  403.     repne    scasb            ;find end of s2
  404.     not    ecx            ;ECX = strlen(s2) + 1 (for EOS)
  405.     mov    edx,P+(2*SIZEPTR)[ebp]    ;EDX = n
  406.     _if    edx a ecx, L7        ;if n > strlen(s2) + 1
  407.     mov    ecx,edx            ;ECX = min(ECX,n)
  408. L7:
  409.     mov    eax,ecx
  410.     sub    edx,ecx            ;EDX = # of nulls to pad
  411.     mov    esi,ebx            ;ESI -> s2
  412.     mov    edi,P[ebp]        ;EDI -> s1
  413.     mov    ebx,edi            ;Save s1 for return value.
  414.     shr    ecx,2
  415.     rep    movsd
  416.     mov    cl,3
  417.     and    ecx,eax
  418.     rep    movsb            ;transfer bytes (including EOS)
  419.     mov    ecx,edx            ;# of nulls to pad
  420.     clr    al
  421.     shr    ecx,2
  422.     rep    stosd
  423.     mov    cl,3
  424.     and    ecx,edx
  425.     rep    stosb
  426.     mov    eax,ebx            ;return value
  427.     unuse    <edi,esi,edx,ecx,ebx>
  428.     pop    ebp
  429.     ret
  430. _strncpy    endp
  431.     endcode strncpy
  432.     endif
  433.  
  434. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  435. ; Set n bytes in s to c.
  436. ;    char *memset(char *p,int c,int n)
  437. ; Returns:
  438. ;    p
  439.  
  440.     ifdef    Amemset
  441.     begcode memset
  442.     public    _memset
  443. _memset proc    near
  444.     push    ebp
  445.     mov    ebp,esp
  446.     uses    <ecx,edx,edi>
  447.  
  448. ife ESeqDS
  449.     mov    ax,ds
  450.     mov    es,ax
  451. endif
  452.  
  453.     mov    edi,P[ebp]            ;p
  454.     mov    ecx,P+SIZEPTR+4[ebp]        ;n
  455.     movzx    eax,byte ptr P+SIZEPTR[ebp]    ;c
  456.     cld
  457.  
  458. ;;;;;;;;;;;;;;;;;;;;;;;;;
  459. ;Calculation to determine method cutoff point.
  460. ;Bytes       EAX          AL
  461. ; n    30 + 5 * n/4    19 + 5 * n
  462. ;
  463. ;    30 + 5 * n/4 <= 19 + 5 * n
  464. ;    11 + 5 * n/4 <= 5 * n
  465. ;    5 * n - 5 * n/4 >= 11
  466. ;    5 * n * (.75)   >= 11
  467. ;    n         >= 2.93
  468. ;But since in order for EAX method to work it requires 4 or bytes, cutoff 
  469. ;should be for n >= 4.    This is a very small memory size and unlikely to
  470. ;occur.     We save another 3 clocks (and 7 bytes) if we don't do the cmp and
  471. ;jump at all!  The cost is:
  472. ;          30 + 0/5/10/15 for n = 0/1/2/3
  473. ;instead of:
  474. ;          14 + 0/5/10/15 for n = 0/1/2/3
  475. ;
  476. ;     cmp     ecx,4
  477. ;     jl     short_mem         ;(9/3)
  478.  
  479.     mov    ah,al            ;(2) Set up a 32 bit pattern.
  480.     mov    edx,eax            ;(2)
  481.     shl    edx,16            ;(3)
  482.     or    eax,edx            ;(2) EAX has the 32 bit pattern.
  483.  
  484.     mov    edx,ecx            ;(2) Save the count of bytes.
  485.     shr    ecx,2            ;(2) Number of dwords.
  486.     rep    stosd            ;(5 + 5n)
  487.     mov    cl,3            ;(2)
  488.     and    ecx,edx            ;(2) Fill in the remaining odd bytes.
  489.  
  490. short_mem:
  491.     rep    stosb            ;(5 + 5n)
  492.     mov    eax,P[ebp]
  493.     unuse    <edi,edx,ecx>
  494.     pop    ebp
  495.     ret
  496. _memset endp
  497.     endcode memset
  498.     endif
  499.  
  500. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  501. ; Copy n bytes from p2 to p1.
  502. ;    void *memcpy(void *p1,void *p2,n)
  503. ; Returns:
  504. ;    p1
  505.  
  506.     ifdef Amemcpy
  507.     public    _memcpy, _memmove
  508.     begcode memcpy
  509.  
  510. _memmove:    ;Alternate entry point.
  511. _memcpy proc    near
  512.     push    ebp
  513.     mov    ebp,esp
  514.     uses    <ecx,edx,edi,esi>
  515.  
  516.     mov    edi,P[ebp]        ;p1
  517.     mov    esi,P+SIZEPTR[ebp]    ;p2
  518.     mov    edx,P+(2*SIZEPTR)[ebp]    ;EDX = n
  519.  
  520. ife ESeqDS
  521.     mov    ax,ds
  522.     mov    es,ax
  523. endif
  524.  
  525.     mov    eax,3            ;Handy constant to have around.
  526.     cmp    esi,edi
  527.     jz    short memcpy_done    ;Do nothing if same.
  528.     ja    short memcpy_forward    ;if forward copy
  529.  
  530.     add    esi,edx            ;Adjust for a reverse copy.
  531.     dec    esi
  532.     add    edi,edx
  533.     dec    edi
  534.     mov    ecx,eax            ;Calculate mod4(n) (EAX = 3).
  535.     and    ecx,edx
  536.     std                ;reverse direction of copy
  537.     rep    movsb            ;Move 0->3 bytes.
  538.  
  539.     mov    ecx,edx            ;EDX has n.
  540.     shr    ecx,2            ;Compute number of dwords.
  541.  
  542.     sub    esi,eax            ;Adjust ESI and EDI by 3.
  543.     sub    edi,eax
  544.     rep    movsd
  545.     cld
  546.     jmps    memcpy_done
  547.  
  548. memcpy_forward:
  549.     mov    ecx,edx            ;EDX = n.
  550.     shr    ecx,2            ;Number of dwords
  551.     cld
  552.     rep    movsd            ;Transfer the dwords.
  553.     mov    ecx,eax            ;Compute remainder (EAX = 3).
  554.     and    ecx,edx            ;EDX has n.
  555.     rep    movsb            ;Transfer the bytes.
  556.  
  557. memcpy_done:
  558.     mov    eax,P[ebp]        ;Return value.
  559.     unuse    <esi,edi,edx,ecx>
  560.     pop    ebp
  561.     ret
  562.  
  563. _memcpy endp
  564.     endcode memcpy
  565.     endif
  566.  
  567. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  568. ;    void movedata(unsigned short srcseg,unsigned srcoff,
  569. ;        unsigned short destseg,unsigned destoff,size_t numbytes);
  570.  
  571.     ifdef Amovedata
  572.     begcode        movedata
  573.  
  574.     public    _movedata
  575. _movedata    proc    near
  576.     push    ebp
  577.     mov    ebp,esp
  578.     push    ds
  579.     push    es
  580.     uses    <esi,edi>
  581.  
  582.     mov    ds,P[ebp]
  583.     mov    esi,P+4[ebp]
  584.     mov    es,P+8[ebp]
  585.     mov    eax,P+16[ebp]    ;get numbytes
  586.     mov    edi,P+12[ebp]
  587.     mov    ecx,eax
  588.     shr    ecx,2        ;convert to dword count
  589.     repz    movsd
  590.  
  591.     mov    cl,3
  592.     and    ecx,eax        ;Compute remainder.
  593.     rep    movsb        ;move remainder bytes
  594.  
  595.     unuse    <edi,esi>
  596.     pop    es
  597.     pop    ds
  598.     pop    ebp
  599.     ret
  600. _movedata    endp
  601.     endcode movedata
  602.     endif
  603.  
  604. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  605. ; Return pointer to first occurrence of char c in string s.
  606. ;    char *strchr(const char *s, int c);
  607.  
  608.     ifdef    Aindex
  609.     begcode strchr
  610.     if 0
  611.     c_public index
  612. func    index
  613. c_endp    index
  614.     endif
  615.  
  616.     c_public strchr
  617. func    strchr
  618.     ife ESeqDS
  619.         mov    ax,ds
  620.         mov    es,ax
  621.     endif
  622.     mov    edx,edi            ;Save edi
  623.     mov    edi,PS[esp]        ;EDI = s
  624.     clr    eax
  625.     mov    ecx,eax
  626.     dec    ecx            ;ECX = -1
  627.     repne    scasb
  628.     not    ecx            ;ECX = length of s (including NULL)
  629.     sub    edi,ecx            ;EDI = s
  630.     mov    al,PS+SIZEPTR[esp]    ;AL = c
  631.     repne    scasb            ;scan for c
  632.     mov    eax,ecx            ;assume we didn't find it
  633.     jnz    short L8        ;didn't find it
  634.     mov    eax,edi            ;yes, found it
  635.     dec    eax
  636. L8:    mov    edi,edx            ;Restore edi
  637.     ret
  638. c_endp    strchr
  639.     endcode strchr
  640.     endif
  641.  
  642. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  643. ; Search for char c in first n bytes pointed to by p.
  644. ;    void *memchr(const void *p,int c,size_t n)
  645. ; Returns:
  646. ;    pointer to char found, else NULL.
  647.  
  648.     ifdef    Amemchr
  649.     begcode memchr
  650.     public    _memchr
  651.  
  652. _memchr proc    near
  653.     push    ebp
  654.     mov    ebp,esp
  655.     mov    ecx,P+SIZEPTR+4[ebp]    ;ECX = n
  656.     jecxz    short L9        ;return NULL
  657.     uses    <edi>
  658.  
  659. ife ESeqDS
  660.     mov    ax,ds
  661.     mov    es,ax
  662. endif
  663.  
  664.     mov    edi,P[ebp]        ;EDI = s
  665.     mov    al,P+SIZEPTR[ebp]    ;AL = c
  666.     repne    scasb            ;scan for c
  667.     mov    eax,ecx            ;assume we didn't find it
  668.     jnz    short L8        ;didn't find it (return NULL)
  669.     mov    eax,edi            ;yes, found it
  670.     dec    eax
  671. L8:    unuse    <edi>
  672.     pop    ebp
  673.     ret
  674.  
  675. L9:    mov    eax,ecx
  676.     pop    ebp
  677.     ret
  678. _memchr endp
  679.     endcode memchr
  680.     endif
  681.  
  682. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  683. ; Compare strings just like strcmp(), except that case is ignored.
  684.  
  685.     ifdef Astrcmpl
  686.     begcode strcmpl
  687.  
  688.     public    _stricmp
  689. _stricmp:
  690.  
  691.     public    _strcmpl
  692. _strcmpl    proc    near
  693.     push    ebp
  694.     mov    ebp,esp
  695.     mov    edx,esi
  696.     uses    <ecx,edi>
  697.     mov    esi,P[ebp]
  698.     mov    edi,P+SIZEPTR[ebp]
  699.  
  700. ife ESeqDS
  701.     mov    ax,ds
  702.     mov    es,ax
  703. endif
  704.  
  705.     _align
  706. L1:    lodsb                ;AL = *p1++
  707.     mov    cl,[edi]
  708.     inc    edi            ;CL = *p2++
  709.     _if    AL ne CL, L2        ;strings are different at this char
  710.     tst    AL            ;end of string?
  711.     jnz    short L1        ;no
  712.     jmps    L3
  713.  
  714. L2:    ;Perhaps when converted to lower case, they will be the same
  715.     _if    al b 'A', L3
  716.     _if    al a 'Z', L4        ;Already lower case?
  717.     add    al,'a' - 'A'        ;convert AL to lower case
  718. L4:    _if    cl b 'A', L3
  719.     _if    cl a 'Z', L5        ;Already lower case?
  720.     add    cl,'a' - 'A'        ;convert CL to lower case
  721. L5:    _if    al e cl, L1        ;same now, so continue looping
  722.  
  723. L3:    clr    ah
  724.     mov    ch,ah
  725.     movzx    eax,ax
  726.     movzx    ecx,cx
  727.     sub    eax,ecx
  728.  
  729.     unuse    <edi,ecx>
  730.     mov    esi,edx
  731.     pop    ebp
  732.     ret
  733. _strcmpl    endp
  734.     endcode strcmpl
  735.     endif
  736.  
  737. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  738. ; Compare strings just like memcmp(), except that case is ignored.
  739.  
  740.     ifdef Amemicmp
  741.     begcode memicmp
  742.     public    _memicmp
  743. _memicmp    proc    near
  744.     push    ebp
  745.     mov    ebp,esp
  746.     uses    <ecx,edx,esi,edi>
  747.     mov    esi,P[ebp]
  748.     mov    edi,P+SIZEPTR[ebp]
  749.     mov    ecx,P+SIZEPTR+SIZEPTR[ebp] ;ECX = numbytes
  750.     jecxz    short match
  751.  
  752.     mov    ah,'A'
  753.     mov    dh,'Z'
  754.  
  755. ife ESeqDS
  756.     mov    ax,ds
  757.     mov    es,ax
  758. endif
  759.  
  760.     _align
  761. L1:    lodsb                ;AL = *p1++
  762.     mov    dl,[edi]
  763.     inc    edi            ;DL = *p2++
  764.     _if    al ne dl, L2        ;strings are different at this char
  765.     loop    L1            ;try next char
  766.     jmps    match
  767.  
  768. L2:    ;Perhaps when converted to lower case, they will be the same
  769.     _if    al b ah, nomatch
  770.     _if    al a dh, L4
  771.     add    al,'a' - 'A'        ;convert AL to lower case
  772. L4:    _if    dl b ah, nomatch
  773.     _if    dl a dh, L5
  774.     add    dl,'a' - 'A'        ;convert DL to lower case
  775. L5:    _if    al ne dl, nomatch    ;different, we're done
  776.     loop    L1
  777. match:    mov    eax,ecx            ;return 0 in eax
  778.     unuse    <edi,esi,edx,ecx>
  779.     pop    ebp
  780.     ret
  781.  
  782. nomatch:
  783.     movzx    edx,dl
  784.     movzx    eax,al
  785.     sub    eax,edx
  786.     unuse    <edi,esi,edx,ecx>
  787.     pop    ebp
  788.     ret
  789. _memicmp    endp
  790.     endcode memicmp
  791.     endif
  792.  
  793.  
  794.     ifdef A_memint
  795. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  796. ; int *_memintset(int *, int value, size_t num)
  797. ; Set an array of ints to a value.  Return the pointer to the array.
  798. ;
  799.  
  800.     begcode _memint
  801.     public    __memintset
  802. __memintset    proc    near
  803.  
  804. ife ESeqDS
  805.     mov    ax,ds
  806.     mov    es,ax
  807. endif
  808.     mov    edx,edi            ;Save edi
  809.     mov    edi,PS[esp]
  810.  
  811.     mov    eax,PS + SIZEPTR[esp]     ;value
  812.     mov    ecx,PS + SIZEPTR + 4[esp];num
  813.     rep    stosd
  814.  
  815.     mov    edi,edx            ;Restore edi.
  816.     mov    eax,PS[esp]        ;Return value.
  817.     ret
  818.  
  819. __memintset    endp
  820.     endcode _memint
  821.     endif ;A_memint
  822.  
  823.     end
  824.  
  825.