home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Tricks of the Windows Gam…ming Gurus (2nd Edition)
/
Disc2.iso
/
vc98
/
crt
/
src
/
platform
/
stricmp.asm
< prev
next >
Wrap
Assembly Source File
|
1998-06-17
|
6KB
|
240 lines
page ,132
title stricmp
;***
;stricmp.asm - contains case-insensitive string comparision routine
; _stricmp/_strcmpi
;
; Copyright (c) 1985-1997, Microsoft Corporation. All rights reserved.
;
;Purpose:
; contains _stricmpi(), also known as _strcmpi()
;
;*******************************************************************************
.xlist
include cruntime.inc
.list
ifdef _MT
; Def and decls necessary to assert the lock for the LC_CTYPE locale category
_SETLOCALE_LOCK EQU 19
extrn _lock:proc
extrn _unlock:proc
endif ; _MT
; Defs and decl necessary to test for the C locale.
_CLOCALEHANDLE EQU 0
LC_CTYPE EQU 2 * 4
extrn __lc_handle:dword
ifdef _MT
extrn __setlc_active:dword
extrn __unguarded_readlc_active:dword
endif ; _MT
ifdef _MT
crt_tolower EQU _tolower_lk
else ; _MT
crt_tolower EQU tolower
endif ; _MT
extrn crt_tolower:proc
page
;***
;int _stricmp(dst, src), _strcmpi(dst, src) - compare strings, ignore case
;
;Purpose:
; _stricmp/_strcmpi perform a case-insensitive string comparision.
; For differences, upper case letters are mapped to lower case.
; Thus, "abc_" < "ABCD" since "_" < "d".
;
; Algorithm:
;
; int _strcmpi (char * dst, char * src)
; {
; int f,l;
;
; do {
; f = tolower(*dst);
; l = tolower(*src);
; dst++;
; src++;
; } while (f && f == l);
;
; return(f - l);
; }
;
;Entry:
; char *dst, *src - strings to compare
;
;Exit:
; AX = -1 if dst < src
; AX = 0 if dst = src
; AX = +1 if dst > src
;
;Uses:
; CX, DX
;
;Exceptions:
;
;*******************************************************************************
CODESEG
public _strcmpi ; alternate entry point for compatibility
_strcmpi proc
_strcmpi endp
public _stricmp
_stricmp proc \
uses edi esi ebx, \
dst:ptr, \
src:ptr
; load up args
mov esi,[src] ; esi = src
mov edi,[dst] ; edi = dst
; test locale
lea eax,__lc_handle
cmp [eax + LC_CTYPE],_CLOCALEHANDLE
jne notclocale
; C locale
mov al,-1 ; fall into loop
align 4
chk_null:
or al,al
jz short done
mov al,[esi] ; al = next source byte
inc esi
mov ah,[edi] ; ah = next dest byte
inc edi
cmp ah,al ; first try case-sensitive comparision
je short chk_null ; match
sub al,'A'
cmp al,'Z'-'A'+1
sbb cl,cl
and cl,'a'-'A'
add al,cl
add al,'A' ; tolower(*dst)
xchg ah,al ; operations on AL are shorter than AH
sub al,'A'
cmp al,'Z'-'A'+1
sbb cl,cl
and cl,'a'-'A'
add al,cl
add al,'A' ; tolower(*src)
cmp al,ah ; inverse of above comparison -- AL & AH are swapped
je short chk_null
; dst < src dst > src
sbb al,al ; AL=-1, CY=1 AL=0, CY=0
sbb al,-1 ; AL=-1 AL=1
done:
movsx eax,al ; extend al to eax
jmp short doret
notclocale:
; Not the C locale. Must call tolower/_tolower_lk to convert chars
; to lower case.
ifdef _MT
lock inc __unguarded_readlc_active ; bump unguarded locale read flag
cmp __setlc_active,0 ; is setlocale() active?
jg short do_lock ; yes, go assert lock
push 0 ; local lock flag is 0
jmp short end_lock
do_lock:
lock dec __unguarded_readlc_active ; restore flag
push _SETLOCALE_LOCK
call _lock
mov [esp],1 ; local lock flag is 1
end_lock:
endif ; _MT
mov eax,255
xor ebx,ebx
align 4
chk_null2:
or al,al ; not that if al == 0, then eax == 0!
jz short done2
mov al,[esi] ; al = next src byte
inc esi
mov bl,[edi] ; bl = next dst byte
inc edi
cmp al,bl ; first try case-sensitive comparision
je short chk_null2 ; match
push eax
push ebx
call crt_tolower ; convert dst char to lower case
mov ebx,eax
add esp,4
call crt_tolower ; convert src char to lower case
add esp,4
cmp bl,al
je chk_null2
sbb eax,eax
sbb eax,-1
done2:
ifdef _MT
mov ebx,eax ; save return value in ebx
pop eax ; get local lock flag
or eax,eax ; lock held?
jnz do_unlock ; yes
lock dec __unguarded_readlc_active
jmp short end_unlock
do_unlock:
push _SETLOCALE_LOCK
call _unlock
add esp,4
end_unlock:
mov eax,ebx ; recover return value
endif ; _MT
doret:
ret
_stricmp endp
end