home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / vc98 / crt / src / platform / memicmp.asm < prev    next >
Assembly Source File  |  1998-06-17  |  7KB  |  262 lines

  1.         page        ,132
  2.         title        memicmp - compare blocks of memory, ignore case
  3. ;***
  4. ;memicmp.asm - compare memory, ignore case
  5. ;
  6. ;       Copyright (c) 1985-1997, Microsoft Corporation. All rights reserved.
  7. ;
  8. ;Purpose:
  9. ;       defines _memicmp() - compare two blocks of memory for lexical
  10. ;       order. Case is ignored in the comparison.
  11. ;
  12. ;*******************************************************************************
  13.  
  14.         .xlist
  15.         include cruntime.inc
  16.         .list
  17.  
  18.  
  19. ifdef _MT
  20.  
  21. ; Def and decls necessary to assert the lock for the LC_CTYPE locale category
  22.  
  23. _SETLOCALE_LOCK EQU     19
  24.  
  25. extrn   _lock:proc
  26. extrn   _unlock:proc
  27.  
  28. endif  ; _MT
  29.  
  30. ; Defs and decl necessary to test for the C locale.
  31.  
  32. _CLOCALEHANDLE  EQU     0
  33. LC_CTYPE        EQU     2 * 4
  34.  
  35.  
  36. extrn   __lc_handle:dword
  37.  
  38. ifdef _MT
  39. extrn   __setlc_active:dword
  40. extrn   __unguarded_readlc_active:dword
  41. endif  ; _MT
  42.  
  43.  
  44.  
  45. ifdef _MT
  46. crt_tolower EQU _tolower_lk
  47. else  ; _MT
  48. crt_tolower EQU tolower
  49. endif  ; _MT
  50.  
  51.  
  52. extrn   crt_tolower:proc
  53.  
  54.  
  55. page
  56. ;***
  57. ;int _memicmp(first, last, count) - compare two blocks of memory, ignore case
  58. ;
  59. ;Purpose:
  60. ;       Compares count bytes of the two blocks of memory stored at first
  61. ;       and last.  The characters are converted to lowercase before
  62. ;       comparing (not permanently), so case is ignored in the search.
  63. ;
  64. ;       Algorithm:
  65. ;       int
  66. ;       _memicmp (first, last, count)
  67. ;               char *first, *last;
  68. ;               unsigned count;
  69. ;               {
  70. ;               if (!count)
  71. ;                       return(0);
  72. ;               while (--count && tolower(*first) == tolower(*last))
  73. ;                       {
  74. ;                       first++;
  75. ;                       last++;
  76. ;                       }
  77. ;               return(tolower(*first) - tolower(*last));
  78. ;               }
  79. ;
  80. ;Entry:
  81. ;       char *first, *last - memory buffers to compare
  82. ;       unsigned count - maximum length to compare
  83. ;
  84. ;Exit:
  85. ;       returns <0 if first < last
  86. ;       returns 0 if first == last
  87. ;       returns >0 if first > last
  88. ;
  89. ;Uses:
  90. ;
  91. ;Exceptions:
  92. ;
  93. ;*******************************************************************************
  94.  
  95.         CODESEG
  96.  
  97.         public  _memicmp
  98. _memicmp proc \
  99.         uses edi esi ebx, \
  100.         first:ptr byte, \
  101.         last:ptr byte, \
  102.         count:IWORD
  103.  
  104.         mov     ecx,[count]     ; cx = count
  105.         or      ecx,ecx
  106.         jz      toend           ; if count=0, nothing to do
  107.  
  108.         mov     esi,[first]     ; si = first
  109.         mov     edi,[last]      ; di = last
  110.  
  111.         ; test locale
  112.  
  113.         lea     eax,__lc_handle
  114.         cmp     [eax + LC_CTYPE],_CLOCALEHANDLE
  115.  
  116.         jne     notclocale
  117.  
  118.         ; C locale
  119.  
  120.         mov     bh,'A'
  121.         mov     bl,'Z'
  122.         mov     dh,'a'-'A'      ; add to cap to make lower
  123.  
  124.         align   4
  125.  
  126. lupe:
  127.         mov     ah,[esi]        ; ah = *first
  128.         inc     esi             ; first++
  129.         mov     al,[edi]        ; al = *last
  130.         inc     edi             ; last++
  131.  
  132.         cmp     ah,al           ; test for equality BEFORE converting case
  133.         je      short dolupe
  134.  
  135.         cmp     ah,bh           ; ah < 'A' ??
  136.         jb      short skip1
  137.  
  138.         cmp     ah,bl           ; ah > 'Z' ??
  139.         ja      short skip1
  140.  
  141.         add     ah,dh           ; make lower case
  142.  
  143. skip1:
  144.         cmp     al,bh           ; al < 'A' ??
  145.         jb      short skip2
  146.  
  147.         cmp     al,bl           ; al > 'Z' ??
  148.         ja      short skip2
  149.  
  150.         add     al,dh           ; make lower case
  151.  
  152. skip2:
  153.         cmp     ah,al           ; *first == *last ??
  154.         jne     short differ    ; nope, found mismatched chars
  155.  
  156. dolupe:
  157.         dec     ecx
  158.         jnz     short lupe
  159.  
  160.         jmp     toend           ; cx = 0, return 0
  161.  
  162. differ:
  163.         mov     ecx,-1          ; assume last is bigger
  164.                                 ; *** can't use "or ecx,-1" due to flags ***
  165.         jb      toend           ; last is, in fact, bigger (return -1)
  166.         neg     ecx             ; first is bigger (return 1)
  167.  
  168.         jmp     toend
  169.  
  170.  
  171. notclocale:
  172.  
  173.         ; Not the C locale. Must call tolower/_tolower_lk to convert chars
  174.         ; to lower case.
  175.  
  176. ifdef _MT
  177. lock    inc     __unguarded_readlc_active   ; bump unguarded locale read flag
  178.         cmp     __setlc_active,0            ; is setlocale() active?
  179.         jg      short do_lock               ; yes, go assert lock
  180.         push    0                           ; local lock flag is 0
  181.         jmp     short end_lock
  182. do_lock:
  183. lock    dec     __unguarded_readlc_active   ; restore flag
  184.         mov     ebx,ecx                     ; save count in ebx
  185.         push    _SETLOCALE_LOCK
  186.         call    _lock
  187.         mov     [esp],1                     ; local lock flag is 1
  188.         mov     ecx,ebx                     ; restore count to ecx
  189. end_lock:
  190. endif  ; _MT
  191.  
  192.         xor     eax,eax
  193.         xor     ebx,ebx
  194.  
  195.         align   4
  196.  
  197. lupe2:
  198.         mov     al,[esi]        ; eax = *first
  199.         inc     esi             ; first++
  200.         mov     bl,[edi]        ; ebx = *last
  201.         inc     edi             ; last++
  202.  
  203.         cmp     al,bl           ; test for equality BEFORE converting case
  204.         je      short dolupe2
  205.  
  206.         push    ecx             ; save count
  207.  
  208.         push    eax
  209.         push    ebx
  210.  
  211.         call    crt_tolower     ; convert *last to lower case
  212.  
  213.         mov     ebx,eax
  214.         add     esp,4
  215.  
  216.         call    crt_tolower     ; convert *first to lower case
  217.  
  218.         add     esp,4
  219.  
  220.         pop     ecx             ; recover count
  221.  
  222.         cmp     al,bl           ; now equal?
  223.         jne     short differ2
  224.  
  225. dolupe2:
  226.         dec     ecx
  227.         jnz     lupe2
  228.  
  229.         jmp     short toend2
  230.  
  231. differ2:
  232.         mov     ecx,-1          ; return -1 if *first < *last
  233.         jb      short toend2
  234.  
  235.         neg     ecx             ; return 1
  236.  
  237. toend2:
  238.  
  239. ifdef _MT
  240.         pop     eax                         ; get local lock flag
  241.         or      eax,eax                     ; lock held?
  242.         jnz     short do_unlock             ; yes
  243. lock    dec     __unguarded_readlc_active   ; decrement unguarded locale
  244.                                             ; read flag
  245.         jmp     short end_unlock
  246. do_unlock:
  247.         mov     ebx,ecx                     ; save return value in ebx
  248.         push    _SETLOCALE_LOCK
  249.         call    _unlock
  250.         add     esp,4
  251.         mov     ecx,ebx                     ; restore return value to ecx
  252. end_unlock:
  253. endif  ; _MT
  254.  
  255. toend:
  256.         mov     eax,ecx         ; move return value to ax
  257.  
  258.         ret                     ; _cdecl return
  259.  
  260. _memicmp endp
  261.         end
  262.