diff options
Diffstat (limited to 'private/crt32/string/i386')
27 files changed, 3201 insertions, 0 deletions
diff --git a/private/crt32/string/i386/memccpy.asm b/private/crt32/string/i386/memccpy.asm new file mode 100644 index 000000000..728f4ce23 --- /dev/null +++ b/private/crt32/string/i386/memccpy.asm @@ -0,0 +1,103 @@ + page ,132 + title memccpy - copy bytes until character found +;*** +;memccpy.asm - copy bytes until a character is found +; +; Copyright (c) 1985-1991, Microsoft Corporation. All rights reserved. +; +;Purpose: +; defines _memccpy() - copies bytes until a specifed character +; is found, or a maximum number of characters have been copied. +; +;Revision History: +; 05-16-84 RN initial version +; 05-17-88 SJM Add model-independent (large model) ifdef +; 08-04-88 SJM convert to cruntime/ add 32-bit support +; 08-23-88 JCR Minor 386 adjustments +; 10-25-88 JCR General cleanup for 386-only code +; 03-23-90 GJF Changed to _stdcall. Also, fixed the copyright. +; 01-17-91 GJF ANSI naming. +; 05-10-91 GJF Back to _cdecl, sigh... +; 10-27-92 SKS Avoid using a MASM keyword ("C") as a parameter name +; +;******************************************************************************* + + .xlist + include cruntime.inc + .list + +page +;*** +;char *_memccpy(dest, src, _c, count) - copy bytes until character found +; +;Purpose: +; Copies bytes from src to dest until count bytes have been +; copied, or up to and including the character _c, whichever +; comes first. +; +; Algorithm: +; char * +; _memccpy (dest, sorc, _c, count) +; char *dest, *sorc, _c; +; unsigned int count; +; { +; while (count && (*dest++ = *sorc++) != _c) +; count--; +; +; return(count ? dest : NULL); +; } +; +;Entry: +; char *dest - pointer to memory to receive copy +; char *src - source of bytes +; char _c - character to stop copy at +; int count - max number of bytes to copy +; +;Exit: +; returns pointer to byte immediately after _c in dest; +; returns NULL if _c was never found +; +;Uses: +; +;Exceptions: +; +;******************************************************************************* + + CODESEG + + public _memccpy +_memccpy proc \ + uses edi esi, \ + dest:ptr byte, \ + sorc:ptr byte, \ + _c:byte, \ + count:IWORD + + mov edi,dest ; di = dest + mov esi,sorc ; si = source + + mov ah,_c ; ah = byte to look for + mov ecx,count ; cx = max byte count + jecxz short retnull ; don't do loop if nothing to move + +lupe: + lodsb ; get byte into al and kick si + stosb ; store byte from al and kick di + cmp al,ah ; see if we just moved the byte + je short toend ; end of string + + loop lupe ; dec cx & jmp to lupe if nonzero + ; else drop out & return NULL +retnull: + xor edi,edi ; null pointer +toend: + mov eax,edi ; return value + +ifdef _STDCALL_ + ret 2*DPSIZE + 2*ISIZE ; _stdcall return +else + ret ; _cdecl return +endif + +_memccpy endp + end diff --git a/private/crt32/string/i386/memchr.asm b/private/crt32/string/i386/memchr.asm new file mode 100644 index 000000000..3e20583c2 --- /dev/null +++ b/private/crt32/string/i386/memchr.asm @@ -0,0 +1,96 @@ + page ,132 + title memchr - search memory for a given character +;*** +;memchr.asm - search block of memory for a given character +; +; Copyright (c) 1985-1991, Microsoft Corporation. All rights reserved. +; +;Purpose: +; defines memchr() - search memory until a character is +; found or a limit is reached. +; +;Revision History: +; 05-16-84 RN initial version +; 07-20-87 SKS rewritten for speed +; 05-17-88 SJM Add model-independent (large model) ifdef +; 08-04-88 SJM convert to cruntime/ add 32-bit support +; 08-23-88 JCR 386 cleanup +; 10-25-88 JCR General cleanup for 386-only code +; 03-23-90 GJF Changed to _stdcall. Also, fixed the copyright. +; 05-10-91 GJF Back to _cdecl, sigh... +; +;******************************************************************************* + + .xlist + include cruntime.inc + .list + +page +;*** +;char *memchr(buf, chr, cnt) - search memory for given character. +; +;Purpose: +; Searched at buf for the given character, stopping when chr is +; first found or cnt bytes have been searched through. +; +; Algorithm: +; char * +; memchr (buf, chr, cnt) +; char *buf; +; int chr; +; unsigned cnt; +; { +; while (cnt && *buf++ != c) +; cnt--; +; return(cnt ? --buf : NULL); +; } +; +;Entry: +; char *buf - memory buffer to be searched +; char chr - character to search for +; unsigned cnt - max number of bytes to search +; +;Exit: +; returns pointer to first occurence of chr in buf +; returns NULL if chr not found in the first cnt bytes +; +;Uses: +; +;Exceptions: +; +;******************************************************************************* + + CODESEG + + public memchr +memchr proc \ + buf:ptr, \ + chr:byte, \ + cnt:IWORD + + xor eax,eax ; return NULL if cnt == 0 + + mov ecx,(cnt) ; cx = count + jecxz short empty + + push edi ; Preserve DI + + mov edi,buf ; di = buffer + mov al,chr ; al = search char + + repne scasb ; scan for byte + mov eax,0 ; assume not found (ax=NULL) + jne short done ; not found -- return NULL + lea eax,[edi-1] ; found - return address of matching byte +done: + pop edi ; Restore DI +empty: + +ifdef _STDCALL_ + ret DPSIZE + 2*ISIZE ; _stdcall return +else + ret ; _cdecl return +endif + +memchr endp + end diff --git a/private/crt32/string/i386/memcmp.asm b/private/crt32/string/i386/memcmp.asm new file mode 100644 index 000000000..cd419fd2e --- /dev/null +++ b/private/crt32/string/i386/memcmp.asm @@ -0,0 +1,101 @@ + page ,132 + title memcmp - compare to blocks of memory +;*** +;memcmp.asm - compare two blocks of memory +; +; Copyright (c) 1985-1991, Microsoft Corporation. All rights reserved. +; +;Purpose: +; defines memcmp() - compare two memory blocks lexically and +; find their order. +; +;Revision History: +; 05-16-83 RN initial version +; 07-20-87 SKS rewritten for speed +; 05-17-88 SJM Add model-independent (large model) ifdef +; 08-04-88 SJM convert to cruntime/ add 32-bit support +; 08-23-88 JCR 386 cleanup +; 10-25-88 JCR General cleanup for 386-only code +; 03-23-90 GJF Changed to _stdcall. Also, fixed the copyright. +; 05-10-91 GJF Back to _cdecl, sigh... +; +;******************************************************************************* + + .xlist + include cruntime.inc + .list + +page +;*** +;int memcmp(buf1, buf2, count) - compare memory for lexical order +; +;Purpose: +; Compares count bytes of memory starting at buf1 and buf2 +; and find if equal or which one is first in lexical order. +; +; Algorithm: +; int +; memcmp (buf1, buf2, count) +; char *buf1, *buf2; +; unsigned count; +; { +; if (!count) +; return(0); +; while (--count && *buf1 == *buf2) +; { +; buf1++; +; buf2++; +; } +; return(*buf1 - *buf2); +; } +; +;Entry: +; char *buf1, *buf2 - pointers to memory sections to compare +; unsigned count - length of sections to compare +; +;Exit: +; returns -1 if buf1 < buf2 +; returns 0 if buf1 == buf2 +; returns +1 if buf1 > buf2 +; +;Uses: +; +;Exceptions: +; +;******************************************************************************* + + CODESEG + + public memcmp +memcmp proc \ + uses edi esi, \ + buf1:ptr byte, \ + buf2:ptr byte, \ + count:IWORD + + mov esi,buf1 ; si = buf1 + mov edi,buf2 ; di = buf2 + +; +; choose ds:si=buf1 and es:di=buf2 so that the CARRY flag +; gets the right way by the REP CMPSB instruction below. +; + xor eax,eax + mov ecx,count + jecxz short done + + repe cmpsb ; compare while equal, at most "count" bytes + je short done ; buf1 == buf2? (AX = 0) + ; buf1 < buf2 buf1 > buf2 + sbb eax,eax ; AX=-1, CY=1 AX=0, CY=0 + sbb eax,-1 ; AX=-1 AX=1 +done: + +ifdef _STDCALL_ + ret 2*DPSIZE + ISIZE ; _stdcall return +else + ret ; _cdecl return +endif + +memcmp endp + end diff --git a/private/crt32/string/i386/memcpy.asm b/private/crt32/string/i386/memcpy.asm new file mode 100644 index 000000000..4cde3cf72 --- /dev/null +++ b/private/crt32/string/i386/memcpy.asm @@ -0,0 +1,354 @@ + page ,132 + title memcpy - Copy source memory bytes to destination +;*** +;memcpy.asm - contains memcpy and memmove routines +; +; Copyright (c) 1986-1991, Microsoft Corporation. All right reserved. +; +;Purpose: +; memcpy() copies a source memory buffer to a destination buffer. +; Overlapping buffers are not treated specially, so propogation may occur. +; memmove() copies a source memory buffer to a destination buffer. +; Overlapping buffers are treated specially, to avoid propogation. +; +;Revision History: +; 02-06-87 JCR Added memmove entry +; 04-08-87 JCR Conditionalized memmove/memcpy entries +; 06-30-87 SKS Rewritten for speed and size +; 08-21-87 SKS Fix return value for overlapping copies +; 05-17-88 SJM Add model-independent (large model) ifdef +; 08-04-88 SJM convert to cruntime/ add 32-bit support +; 08-19-88 JCR Minor 386 corrections/enhancements +; 10-25-88 JCR General cleanup for 386-only code +; 03-23-90 GJF Changed to _stdcall. Also, fixed the copyright. +; 05-10-91 GJF Back to _cdecl, sigh... +; 11-13-92 SRW Make it fast with unaligned arguments +; +;******************************************************************************* + + .xlist + include cruntime.inc + .list + +M_EXIT macro + mov eax,[dst] ; return pointer to destination +ifdef _STDCALL_ + ret 2*DPSIZE + ISIZE ; _stdcall return +else + ret ; _cdecl return +endif + endm ; M_EXIT + + CODESEG + +page +;*** +;memcpy - Copy source buffer to destination buffer +; +;Purpose: +; memcpy() copies a source memory buffer to a destination memory buffer. +; This routine does NOT recognize overlapping buffers, and thus can lead +; to propogation. +; For cases where propogation must be avoided, memmove() must be used. +; +; Algorithm: +; +; void * memcpy(void * dst, void * src, size_t count) +; { +; void * ret = dst; +; +; /* +; * copy from lower addresses to higher addresses +; */ +; while (count--) +; *dst++ = *src++; +; +; return(ret); +; } +; +;memmove - Copy source buffer to destination buffer +; +;Purpose: +; memmove() copies a source memory buffer to a destination memory buffer. +; This routine recognize overlapping buffers to avoid propogation. +; For cases where propogation is not a problem, memcpy() can be used. +; +; Algorithm: +; +; void * memmove(void * dst, void * src, size_t count) +; { +; void * ret = dst; +; +; if (dst <= src || dst >= (src + count)) { +; /* +; * Non-Overlapping Buffers +; * copy from lower addresses to higher addresses +; */ +; while (count--) +; *dst++ = *src++; +; } +; else { +; /* +; * Overlapping Buffers +; * copy from higher addresses to lower addresses +; */ +; dst += count - 1; +; src += count - 1; +; +; while (count--) +; *dst-- = *src--; +; } +; +; return(ret); +; } +; +; +;Entry: +; void *dst = pointer to destination buffer +; const void *src = pointer to source buffer +; size_t count = number of bytes to copy +; +;Exit: +; Returns a pointer to the destination buffer in AX/DX:AX +; +;Uses: +; CX, DX +; +;Exceptions: +;******************************************************************************* + +ifdef MEM_MOVE + _MEM_ equ <memmove> +else + _MEM_ equ <memcpy> +endif + +% public _MEM_ +_MEM_ proc \ + uses edi esi, \ + dst:ptr byte, \ + src:ptr byte, \ + count:IWORD + + ; destination pointer + ; source pointer + ; number of bytes to copy + + mov esi,[src] ; esi = source + mov edi,[dst] ; edi = dest + mov ecx,[count] ; ecx = number of bytes to move + +; +; Check for overlapping buffers: +; If (dst <= src) Or (dst >= src + Count) Then +; Do normal (Upwards) Copy +; Else +; Do Downwards Copy to avoid propagation +; + + cmp edi,esi ; dst <= src ? + jbe short CopyUp ; yes, copy toward higher addresses + + mov eax,esi + add eax,ecx + cmp edi,eax ; dst >= (src + count) ? + jnae CopyDown ; no, copy toward lower addresses + +; +; Copy toward higher addresses. +; +CopyUp: + +; +; The algorithm for forward moves is to align the destination to a dword +; boundary and so we can move dwords with an aligned destination. This +; occurs in 3 steps. +; +; - move x = ((4 - Dest & 3) & 3) bytes +; - move y = ((L-x) >> 2) dwords +; - move (L - x - y*4) bytes +; + test edi,11b ; destination dword aligned? + jnz short byterampup ; if we are not dword aligned already, align + + mov edx,ecx ; byte count + and edx,11b ; trailing byte count + shr ecx,2 ; shift down to dword count + rep movsd ; move all of our dwords + + jmp dword ptr TrailingVecs[edx*4] + + align @WordSize +TrailingVecs dd Trail0, Trail1, Trail2, Trail3 + + align @WordSize +Trail3: + mov ax,[esi] + mov [edi],ax + mov al,[esi+2] + mov [edi+2],al + + M_EXIT + + align @WordSize +Trail2: + mov ax,[esi] + mov [edi],ax + + M_EXIT + + align @WordSize +Trail1: + mov al,[esi] + mov [edi],al + +Trail0: + M_EXIT + +; +; Code to do optimal memory copies for non-dword-aligned destinations. +; + align @WordSize +byterampup: + +; The following length check is done for two reasons: +; +; 1. to ensure that the actual move length is greater than any possiale +; alignment move, and +; +; 2. to skip the multiple move logic for small moves where it would +; be faster to move the bytes with one instruction. +; +; Leading bytes could be handled faster via split-out optimizations and +; a jump table (as trailing bytes are), at the cost of size. +; +; At this point, ECX is the # of bytes to copy, and EDX is the # of leading +; bytes to copy. +; + cmp ecx,12 ; check for reasonable length + jbe short ShortMove ; do short move if appropriate + mov edx,edi + neg edx + and edx,11b ; # of leading bytes + sub ecx,edx ; subtract out leading bytes + mov eax,ecx ; # of bytes remaining after leading + mov ecx,edx ; # of leading bytes + rep movsb ; copy leading bytes + mov ecx,eax ; compute number of dwords to move + and eax,11b ; # of trailing bytes + shr ecx,2 ; # of whole dwords + rep movsd ; move whole dwords + jmp dword ptr TrailingVecs[eax*4] ; copy trailing bytes + +; +; Simple copy, byte at a time. This could be faster with a jump table and +; split-out optimizations, copying as much as possible a dword/word at a +; time and using MOV with displacements, but such short cases are unlikely +; to be called often (it seems silly to call a function to copy less than +; three dwords). +; + align @WordSize +ShortMove: + rep movsb + + M_EXIT + +; +; Copy down to avoid propogation in overlapping buffers. +; + align @WordSize +CopyDown: + std ; Set Direction Flag = Down + add esi,ecx ; point to byte after end of source buffer + add edi,ecx ; point to byte after end of dest buffer +; +; See if the destination start is dword aligned +; + + test edi,11b + jnz short byterampup_copydown ; not dword aligned +; +; Destination start is dword aligned +; + mov edx,ecx ; set aside count of bytes to copy + and edx,11b ; # of trailing bytes to copy + sub esi,4 ; point to start of first dword to copy + sub edi,4 ; point to start of first dword to copy to + shr ecx,2 ; dwords to copy + rep movsd ; copy as many dwords as possible + jmp dword ptr TrailingVecs_copydown[edx*4] ;do any trailing bytes + + align @WordSize +TrailingVecs_copydown label dword + dd Trail0_copydown + dd Trail1_copydown + dd Trail2_copydown + dd Trail3_copydown + + align @WordSize +Trail3_copydown: + mov ax,[esi+2] + mov [edi+2],ax + mov al,[esi+1] + mov [edi+1],al + cld ; Set Direction Flag = Up + + M_EXIT + + align @WordSize +Trail2_copydown: + mov ax,[esi+2] + mov [edi+2],ax + cld ; Set Direction Flag = Up + + M_EXIT + + align @WordSize +Trail1_copydown: + mov al,[esi+3] + mov [edi+3],al +Trail0_copydown: + cld ; Set Direction Flag = Up + + M_EXIT + +; +; Destination start is not dword aligned. +; +; Leading bytes could be handled faster via split-out optimizations and +; a jump table (as trailing bytes are), at the cost of size. +; +; At this point, ECX is the # of bytes to copy, and EDX is the # of leading +; bytes to copy. +; + align @WordSize +byterampup_copydown: + dec esi ; point to first leading src byte + dec edi ; point to first leading dest byte + cmp ecx,12 ; check for reasonable length + jbe short ShortMove_copydown ; do short move if appropriate + neg edx + and edx,11b + sub ecx,edx ; # of bytes after leading bytes + mov eax,ecx ; set aside # of bytes remaining + mov ecx,edx ; # of leading bytes + rep movsb ; copy leading odd bytes + mov ecx,eax ; # of remaining bytes + and eax,11b ; # of trailing bytes + sub esi,3 ; point to start of first whole src dword + sub edi,3 ; point to start of first whole dest dword + shr ecx,2 ; # of whole dwords + rep movsd ; copy whole dwords + jmp dword ptr TrailingVecs_copydown[eax*4] + + align @WordSize +ShortMove_copydown: + rep movsb + cld ; Set Direction Flag = Up + + M_EXIT + +_MEM_ endp + end + + diff --git a/private/crt32/string/i386/memicmp.asm b/private/crt32/string/i386/memicmp.asm new file mode 100644 index 000000000..e87427660 --- /dev/null +++ b/private/crt32/string/i386/memicmp.asm @@ -0,0 +1,132 @@ + page ,132 + title memicmp - compare blocks of memory, ignore case +;*** +;memicmp.asm - compare memory, ignore case +; +; Copyright (c) 1985-1991, Microsoft Corporation. All rights reserved. +; +;Purpose: +; defines _memicmp() - compare two blocks of memory for lexical +; order. Case is ignored in the comparison. +; +;Revision History: +; 05-16-83 RN initial version +; 05-17-88 SJM Add model-independent (large model) ifdef +; 08-04-88 SJM convert to cruntime/ add 32-bit support +; 08-23-88 JCR Cleanup... +; 10-25-88 JCR General cleanup for 386-only code +; 03-23-90 GJF Changed to _stdcall. Also, fixed the copyright. +; 01-17-91 GJF ANSI naming. +; 05-10-91 GJF Back to _cdecl, sigh... +; +;******************************************************************************* + + .xlist + include cruntime.inc + .list + +page +;*** +;int _memicmp(first, last, count) - compare two blocks of memory, ignore case +; +;Purpose: +; Compares count bytes of the two blocks of memory stored at first +; and last. The characters are converted to lowercase before +; comparing (not permanently), so case is ignored in the search. +; +; Algorithm: +; int +; _memicmp (first, last, count) +; char *first, *last; +; unsigned count; +; { +; if (!count) +; return(0); +; while (--count && tolower(*first) == tolower(*last)) +; { +; first++; +; last++; +; } +; return(tolower(*first) - tolower(*last)); +; } +; +;Entry: +; char *first, *last - memory buffers to compare +; unsigned count - maximum length to compare +; +;Exit: +; returns <0 if first < last +; returns 0 if first == last +; returns >0 if first > last +; +;Uses: +; +;Exceptions: +; +;******************************************************************************* + + CODESEG + + public _memicmp +_memicmp proc \ + uses edi esi ebx, \ + first:ptr byte, \ + last:ptr byte, \ + count:IWORD + + mov esi,[first] ; si = first + mov edi,[last] ; di = last + + mov ecx,[count] ; cx = count + jecxz short toend ; if count=0, nothing to do + + mov bh,'A' + mov bl,'Z' + mov dh,'a'-'A' ; add to cap to make lower + +lupe: + mov ah,[esi] ; ah = *first + mov al,[edi] ; al = *last + inc esi ; first++ + inc edi ; last++ + cmp ah,bh ; ah < 'A' ?? + jb short skip1 + + cmp ah,bl ; ah > 'Z' ?? + ja short skip1 + + add ah,dh ; make lower case + +skip1: + cmp al,bh ; al < 'A' ?? + jb short skip2 + + cmp al,bl ; al > 'Z' ?? + ja short skip2 + + add al,dh ; make lower case + +skip2: + cmp ah,al ; *first == *last ?? + jne short differ ; nope, found mismatched chars + + loop lupe + jmp short toend ; cx = 0, return 0 + +differ: + mov ecx,-1 ; assume last is bigger + ; *** can't use "or ecx,-1" due to flags *** + jb short toend ; last is, in fact, bigger (return -1) + neg ecx ; first is bigger (return 1) + +toend: + mov eax,ecx ; move return value to ax + +ifdef _STDCALL_ + ret 2*DPSIZE + ISIZE ; _stdcall return +else + ret ; _cdecl return +endif + +_memicmp endp + end diff --git a/private/crt32/string/i386/memmove.asm b/private/crt32/string/i386/memmove.asm new file mode 100644 index 000000000..39863a1db --- /dev/null +++ b/private/crt32/string/i386/memmove.asm @@ -0,0 +1,19 @@ +;*** +;memmove.asm - +; +; Copyright (c) 1991-1992, Microsoft Corporation. All rights reserved. +; +;Purpose: +; memmove() copies a source memory buffer to a destination buffer. +; Overlapping buffers are treated specially, to avoid propogation. +; +; NOTE: This stub module scheme is compatible with NT build +; procedure. +; +;Revision History: +; 09-25-91 JCR Stub module created. +; +;******************************************************************************* + +MEM_MOVE EQU 1 +INCLUDE I386\MEMCPY.ASM diff --git a/private/crt32/string/i386/memset.asm b/private/crt32/string/i386/memset.asm new file mode 100644 index 000000000..6a6f2ca58 --- /dev/null +++ b/private/crt32/string/i386/memset.asm @@ -0,0 +1,127 @@ + page ,132 + title memset - set sections of memory all to one byte +;*** +;memset.asm - set a section of memory to all one byte +; +; Copyright (c) 1985-1991, Microsoft Corporation. All rights reserved. +; +;Purpose: +; contains the memset() routine +; +;Revision History: +; 05-07-84 RN initial version +; 06-30-87 SKS faster algorithm +; 05-17-88 SJM Add model-independent (large model) ifdef +; 08-04-88 SJM convert to cruntime/ add 32-bit support +; 08-19-88 JCR Enable word alignment code for all models/CPUs, +; Some code improvement +; 10-25-88 JCR General cleanup for 386-only code +; 10-27-88 JCR More optimization (dword alignment, no ebx usage, etc) +; 03-23-90 GJF Changed to _stdcall. Also, fixed the copyright. +; 05-10-91 GJF Back to _cdecl, sigh... +; +;******************************************************************************* + + .xlist + include cruntime.inc + .list + +page +;*** +;char *memset(dst, val, count) - sets "count" bytes at "dst" to "val" +; +;Purpose: +; Sets the first "count" bytes of the memory starting +; at "dst" to the character value "val". +; +; Algorithm: +; char * +; memset (dst, val, count) +; char *dst; +; char val; +; unsigned int count; +; { +; char *start = dst; +; +; while (count--) +; *dst++ = val; +; return(start); +; } +; +;Entry: +; char *dst - pointer to memory to fill with val +; char val - value to put in dst bytes +; int count - number of bytes of dst to fill +; +;Exit: +; returns dst, with filled bytes +; +;Uses: +; +;Exceptions: +; +;******************************************************************************* + + CODESEG + + public memset +memset proc \ + uses edi, \ + dst:ptr byte, \ + value:byte, \ + count:IWORD + + mov ecx,[count] ; cx = count + jecxz short toend ; if no work to do + + ; set all 4 bytes of eax to [value] + mov al,[value] ; the byte value to be stored + mov ah,al ; store it as a word + mov edx,eax ; lo 16 bits dx=ax=val/val + ror eax,16 ; move val/val to hi 16-bits + mov ax,dx ; eax = all 4 bytes = [value] + +; Align address on dword boundary + + mov edi,[dst] ; di = dest pointer + mov edx,edi ; dx = di = *dst + neg edx + and edx,(ISIZE-1) ; dx = # bytes before dword boundary + jz short dwords ; jump if address already aligned + + cmp ecx,edx ; count >= # leading bytes?? + jb short tail ; nope, just move ecx bytes + + sub ecx,edx ; cx = adjusted count (for later) + xchg ecx,edx ; cx = leading byte count / dx = adjusted count + rep stosb ; store leading bytes + mov ecx,edx ; cx = count of remaining bytes + ;jecxz short toend ; jump out if nothing left to do + +; Move dword-sized blocks + +dwords: + mov edx,ecx ; save original count + shr ecx,ISHIFT ; cx = dword count + rep stos IWORD ptr [edi] ; fill 'em up + mov ecx,edx ; retrieve original byte count + +; Move remaining bytes + +tail: ; store remaining 1,2, or 3 bytes + and ecx,(ISIZE-1) ; get byte count + rep stosb ; store remaining bytes, if necessary + +; Done + +toend: + mov eax,[dst] ; return dest pointer + +ifdef _STDCALL_ + ret DPSIZE + 2*ISIZE ; _stdcall return +else + ret ; _cdecl return +endif + +memset endp + end diff --git a/private/crt32/string/i386/strcat.asm b/private/crt32/string/i386/strcat.asm new file mode 100644 index 000000000..9781440c1 --- /dev/null +++ b/private/crt32/string/i386/strcat.asm @@ -0,0 +1,155 @@ + page ,132 + title strcat - concatenate (append) one string to another +;*** +;strcat.asm - contains strcat() and strcpy() routines +; +; Copyright (c) 1985-1991, Microsoft Corporation. All rights reserved. +; +;Purpose: +; STRCAT concatenates (appends) a copy of the source string to the +; end of the destination string, returning the destination string. +; +;Revision History: +; 04-21-87 SKS Rewritten to be fast and small, added file header +; 05-17-88 SJM Add model-independent (large model) ifdef +; 07-27-88 SJM Rewritten to be 386-specific and to include strcpy +; 08-29-88 JCR 386 cleanup... +; 10-07-88 JCR Correct off-by-1 strcat bug; optimize ecx=-1 +; 10-25-88 JCR General cleanup for 386-only code +; 03-23-90 GJF Changed to _stdcall. Also, fixed the copyright. +; 05-10-91 GJF Back to _cdecl, sigh... +; +;******************************************************************************* + + .xlist + include cruntime.inc + .list + + +page +;*** +;char *strcat(dst, src) - concatenate (append) one string to another +; +;Purpose: +; Concatenates src onto the end of dest. Assumes enough +; space in dest. +; +; Algorithm: +; char * strcat (char * dst, char * src) +; { +; char * cp = dst; +; +; while( *cp ) +; ++cp; /* Find end of dst */ +; while( *cp++ = *src++ ) +; ; /* Copy src to end of dst */ +; return( dst ); +; } +; +;Entry: +; char *dst - string to which "src" is to be appended +; const char *src - string to be appended to the end of "dst" +; +;Exit: +; The address of "dst" in AX/DX:AX +; +;Uses: +; BX, CX, DX +; +;Exceptions: +; +;******************************************************************************* + +page +;*** +;char *strcpy(dst, src) - copy one string over another +; +;Purpose: +; Copies the string src into the spot specified by +; dest; assumes enough room. +; +; Algorithm: +; char * strcpy (char * dst, char * src) +; { +; char * cp = dst; +; +; while( *cp++ = *src++ ) +; ; /* Copy src over dst */ +; return( dst ); +; } +; +;Entry: +; char * dst - string over which "src" is to be copied +; const char * src - string to be copied over "dst" +; +;Exit: +; The address of "dst" in AX/DX:AX +; +;Uses: +; BX, CX, DX +; +;Exceptions: +;******************************************************************************* + + + CODESEG + +% public strcat, strcpy ; make both functions available + +strcat label proc ;--- strcat --- + + clc ; carry clear = append + jmp short _docat + + align @wordsize ; want to come in on a nice boundary... +strcpy label proc ;--- strcpy --- + + stc ; carry set = don't append to end of string + ;fall thru + + +; --- Common code --- + +_docat proc private \ + uses esi edi, \ + dst:ptr byte, \ + src:ptr byte + + mov edi, dst ; di = dest pointer + jc short @F ; jump if not appending + + ; now skip to end of destination string + + xor eax, eax ; search for the null terminator + or ecx,-1 ; ecx = -1 +repne scasb + dec edi ; edi points to null terminator + + ; copy source string + +@@: mov esi, src + xchg esi, edi ; now ds:esi->dst and es:edi->src + xor eax, eax ; search for null + or ecx,-1 ; ecx = -1 + +repne scasb ; find the length of the src string + not ecx + sub edi, ecx + xchg esi, edi ; now es:edi->dst and ds:esi->src + + mov eax, ecx + shr ecx, ISHIFT ; get the double-word count +rep movsd + and eax, (ISIZE-1) ; get the byte cound + xchg ecx, eax +rep movsb ; move remaining bytes, if any + mov eax, dst ; returned address + +ifdef _STDCALL_ + ret 2*DPSIZE ; _stdcall return +else + ret ; _cdecl return +endif + +_docat endp + end diff --git a/private/crt32/string/i386/strchr.asm b/private/crt32/string/i386/strchr.asm new file mode 100644 index 000000000..b2b6a5b56 --- /dev/null +++ b/private/crt32/string/i386/strchr.asm @@ -0,0 +1,94 @@ + page ,132 + title strchr - search string for given character +;*** +;strchr.asm - search a string for a given character +; +; Copyright (c) 1985-1991, Microsoft Corporation. All rights reserved. +; +;Purpose: +; defines strchr() - search a string for a character +; +;Revision History: +; 10-27-83 RN initial version +; 05-17-88 SJM Add model-independent (large model) ifdef +; 08-04-88 SJM convert to cruntime/ add 32-bit support +; 08-23-88 JCR 386 cleanup +; 10-25-88 JCR General cleanup for 386-only code +; 03-23-90 GJF Changed to _stdcall. Also, fixed the copyright. +; 05-10-91 GJF Back to _cdecl, sigh... +; +;******************************************************************************* + + .xlist + include cruntime.inc + .list + +page +;*** +;char *strchr(string, c) - search a string for a character +; +;Purpose: +; Searches a string for a given character, which may be the +; null character '\0'. +; +; Algorithm: +; char * +; strchr (string, ch) +; char *string, ch; +; { +; while (*string && *string != ch) +; string++; +; if (*string == ch) +; return(string); +; return((char *)0); +; } +; +;Entry: +; char *string - string to search in +; char c - character to search for +; +;Exit: +; returns pointer to the first occurence of c in string +; returns NULL if c does not occur in string +; +;Uses: +; +;Exceptions: +; +;******************************************************************************* + + CODESEG + + public strchr +strchr proc \ + uses edi, \ + string:ptr char, \ + chr:byte + + mov edi,[string] ; edi = string + + push edi ; save string pointer + xor eax,eax ; null byte to search for + mov ecx, -1 +repne scasb ; find string length by scanning for null + not ecx ; cx = length of string + mov al,[chr] ; al=byte to search for + pop edi ; restore saved string pointer +repne scasb ; find that byte (if it exists)! + ; edi points one past byte which stopped scan + dec edi ; edi points to byte which stopped scan + + cmp [edi],al ; take one last look to be sure + je short retdi ; return edi if it matches + xor edi,edi ; no match, so return NULL +retdi: + mov eax,edi ; ret value: pointer to matching byte + +ifdef _STDCALL_ + ret DPSIZE + ISIZE ; _stdcall return +else + ret ; _cdecl return +endif + +strchr endp + end diff --git a/private/crt32/string/i386/strcmp.asm b/private/crt32/string/i386/strcmp.asm new file mode 100644 index 000000000..6024848b5 --- /dev/null +++ b/private/crt32/string/i386/strcmp.asm @@ -0,0 +1,104 @@ + page ,132 + title strcmp.asm - compare two strings +;*** +;strcmp.asm - routine to compare two strings (for equal, less, or greater) +; +; Copyright (c) 1985-1991, Microsoft Corporation. All rights reserved. +; +;Purpose: +; STRCMP compares two strings and returns an integer +; to indicate whether the first is less than the second, the two are +; equal, or whether the first is greater than the second, respectively. +; Comparison is done byte by byte on an UNSIGNED basis, which is to +; say that Null (0) is less than any other character (1-255). +; +;Revision History: +; 04-21-87 SKS Module rewritten to be fast and small +; 05-17-88 SJM Add model-independent (large model) ifdef +; 08-04-88 SJM convert to cruntime/ add 32-bit support +; 08-23-88 JCR Minor 386 cleanup +; 10-25-88 JCR General cleanup for 386-only code +; 03-23-90 GJF Changed to _stdcall. Also, fixed the copyright. +; 05-10-91 GJF Back to _cdecl, sigh... +; +;******************************************************************************* + + .xlist + include cruntime.inc + .list + +page +;*** +;strcmp - compare two strings, returning less than, equal to, or greater than +; +;Purpose: +; Compares two string, determining their lexical order. Unsigned +; comparison is used. +; +; Algorithm: +; int strcmp ( src , dst ) +; unsigned char *src; +; unsigned char *dst; +; { +; int ret = 0 ; +; +; while( ! (ret = *src - *dst) && *dst) +; ++src, ++dst; +; +; if ( ret < 0 ) +; ret = -1 ; +; else if ( ret > 0 ) +; ret = 1 ; +; +; return( ret ); +; } +; +;Entry: +; const char * src - string for left-hand side of comparison +; const char * dst - string for right-hand side of comparison +; +;Exit: +; AX < 0, 0, or >0, indicating whether the first string is +; Less than, Equal to, or Greater than the second string. +; +;Uses: +; CX, DX +; +;Exceptions: +; +;******************************************************************************* + + CODESEG + + .lall + + public strcmp +strcmp proc \ + uses edi esi, \ + src:ptr byte, \ + dst:ptr byte + + + mov esi,[src] ; si = source + xor eax,eax ; mingle register instr with mem instr. + mov edi,[dst] ; di = dest + + or ecx,-1 ; cx = -1 + repne scasb ; compute length of "dst" + not ecx ; CX = strlen(dst)+1 + sub edi,ecx ; restore DI = dst + repe cmpsb ; compare while equal, at most length of "dst" + je short toend ; dst == src? (AX = 0) + ; dst < src dst > src + sbb eax,eax ; AX=-1, CY=1 AX=0, CY=0 + sbb eax,-1 ; AX=-1 AX=1 +toend: + +ifdef _STDCALL_ + ret 2*DPSIZE ; _stdcall return +else + ret ; _cdecl return +endif + +strcmp endp + end diff --git a/private/crt32/string/i386/strcspn.asm b/private/crt32/string/i386/strcspn.asm new file mode 100644 index 000000000..39554147f --- /dev/null +++ b/private/crt32/string/i386/strcspn.asm @@ -0,0 +1,19 @@ +;*** +;strcspn.asm - +; +; Copyright (c) 1991-1992, Microsoft Corporation. All rights reserved. +; +;Purpose: +; defines strcspn()- finds the length of the initial substring of +; a string consisting entirely of characters not in a control string. +; +; NOTE: This stub module scheme is compatible with NT build +; procedure. +; +;Revision History: +; 09-25-91 JCR Stub module created. +; +;******************************************************************************* + +SSTRCSPN EQU 1 +INCLUDE I386\STRSPN.ASM diff --git a/private/crt32/string/i386/strdup.asm b/private/crt32/string/i386/strdup.asm new file mode 100644 index 000000000..04f388e4a --- /dev/null +++ b/private/crt32/string/i386/strdup.asm @@ -0,0 +1,126 @@ + page ,132 + title strdup - duplicate string in malloc'd memory +;*** +;strdup.asm - duplicate a string in malloc'd memory +; +; Copyright (c) 1985-1991, Microsoft Corporation. All rights reserved. +; +;Purpose: +; defines _strdup() - grab new memory, and duplicate the string into it. +; +;Revision History: +; 10-27-83 RN initial version +; 05-18-88 SJM Add model-independent (large model) ifdef +; 08-04-88 SJM convert to cruntime/ add 32-bit support +; 08-23-88 JCR Minor 386 cleanup +; 10-25-88 JCR General cleanup for 386-only code +; 03-23-90 GJF Changed to _stdcall. Also, fixed the copyright. +; 01-18-91 GJF ANSI naming. +; 05-10-91 GJF Back to _cdecl, sigh... +; +;******************************************************************************* + + .xlist + include cruntime.inc + .list + + extrn strlen:proc + extrn strcpy:proc + extrn malloc:proc + + +page +;*** +;char *_strdup(string) - duplicate string into malloc'd memory +; +;Purpose: +; Allocates enough storage via malloc() for a copy of the +; string, copies the string into the new memory, and returns +; a pointer to it. +; +; Algorithm: +; char * +; _strdup (string) +; char *string; +; { +; char *memory; +; +; if (!string) +; return(NULL); +; if (memory = malloc(strlen(string) + 1)) +; return(strcpy(memory,string)); +; return(NULL); +; } +; +;Entry: +; char *string - string to copy into new memory +; +;Exit: +; returns a pointer to the newly allocated storage with the +; string in it. +; returns NULL if enough memory could not be allocated, or +; string was NULL. +; +;Uses: +; eax, edx +; +;Exceptions: +; +;******************************************************************************* + + CODESEG + +% public _strdup +_strdup proc \ + uses edi, \ + string:ptr byte + + + mov edi,[string] ; edi=pointer to string + push edi ; stack parameter: string pointer + call strlen ; eax = string length + +ifndef _STDCALL_ + pop edx ; caller cleans stack (_cdecl) +;else + ; callee cleaned stack (_stdcall) +endif + + inc eax ; need space for null byte too + push eax ; stack parameter: string length (with null) + call malloc ; eax = pointer to space + +ifndef _STDCALL_ + pop edx ; caller cleans stack (_cdecl) +;else + ; callee cleaned stack (_stdcall) +endif + + or eax,eax ; offset == NULL ?? + jz short toend ; error -- couldn't malloc space + +okay: + push edi ; push address of original string + push eax ; push address of dest string + ; source string addr is still on stack + call strcpy ; duplicate the string + +ifndef _STDCALL_ + pop edx ; caller cleans stack (_cdecl) + pop edx +;else + ; callee cleaned stack (_stdcall) +endif + + ; pointer to duplicate is in eax + +toend: ; eax = return value + +ifdef _STDCALL_ + ret DPSIZE ; _stdcall return +else + ret ; _cdecl return +endif + +_strdup endp + end diff --git a/private/crt32/string/i386/stricmp.asm b/private/crt32/string/i386/stricmp.asm new file mode 100644 index 000000000..80f384701 --- /dev/null +++ b/private/crt32/string/i386/stricmp.asm @@ -0,0 +1,127 @@ + page ,132 + title stricmp +;*** +;strcmp.asm - contains case-insensitive string comparision routine +; _stricmp/_strcmpi +; +; Copyright (c) 1985-1991, Microsoft Corporation. All rights reserved. +; +;Purpose: +; contains _stricmpi(), also known as _strcmpi() +; +;Revision History: +; 05-18-88 SJM Add model-independent (large model) ifdef +; 08-04-88 SJM convert to cruntime/ add 32-bit support +; 08-23-88 JCR Minor 386 cleanup +; 10-10-88 JCR Added strcmpi() entry for compatiblity with early revs +; 10-25-88 JCR General cleanup for 386-only code +; 10-27-88 JCR Shuffled regs so no need to save/restore ebx +; 03-23-90 GJF Changed to _stdcall. Also, fixed the copyright. +; 01-18-91 GJF ANSI naming. +; 05-10-91 GJF Back to _cdecl, sigh... +; +;******************************************************************************* + + .xlist + include cruntime.inc + .list + +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 label proc + + public _stricmp +_stricmp proc \ + uses esi, \ + dst:ptr, \ + src:ptr + + + mov esi,[src] ; SI = src + mov edx,[dst] ; DX = dst + mov al,-1 ; fall into loop + +chk_null: + or al,al + jz short done +again: + lodsb ; al = next source byte + mov ah,[edx] ; ah = next dest byte + inc edx + + 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 + +ifdef _STDCALL_ + ret 2*DPSIZE ; _stdcall return +else + ret ; _cdecl return +endif + +_stricmp endp + end diff --git a/private/crt32/string/i386/strlen.asm b/private/crt32/string/i386/strlen.asm new file mode 100644 index 000000000..4ea531018 --- /dev/null +++ b/private/crt32/string/i386/strlen.asm @@ -0,0 +1,84 @@ + page ,132 + title strlen - return the length of a null-terminated string +;*** +;strlen.asm - contains strlen() routine +; +; Copyright (c) 1985-1991, Microsoft Corporation. All rights reserved. +; +;Purpose: +; strlen returns the length of a null-terminated string, +; not including the null byte itself. +; +;Revision History: +; 04-21-87 SKS Rewritten to be fast and small, added file header +; 05-18-88 SJM Add model-independent (large model) ifdef +; 08-02-88 SJM Add 32 bit code, use cruntime vs cmacros +; 08-23-88 JCR 386 cleanup +; 10-05-88 GJF Fixed off-by-2 error. +; 10-10-88 JCR Minor improvement +; 10-25-88 JCR General cleanup for 386-only code +; 10-26-88 JCR Re-arrange regs to avoid push/pop ebx +; 03-23-90 GJF Changed to _stdcall. Also, fixed the copyright. +; 05-10-91 GJF Back to _cdecl, sigh... +; +;******************************************************************************* + + .xlist + include cruntime.inc + .list + +page +;*** +;strlen - return the length of a null-terminated string +; +;Purpose: +; Finds the length in bytes of the given string, not including +; the final null character. +; +; Algorithm: +; int strlen (const char * str) +; { +; int length = 0; +; +; while( *str++ ) +; ++length; +; +; return( length ); +; } +; +;Entry: +; const char * str - string whose length is to be computed +; +;Exit: +; AX = length of the string "str", exclusive of the final null byte +; +;Uses: +; CX, DX +; +;Exceptions: +; +;******************************************************************************* + + CODESEG + + public strlen +strlen proc \ + uses edi, \ + string:ptr byte + + mov edi,string ; edi -> string + xor eax,eax ; null byte + or ecx,-1 ; set ecx to -1 +repne scasb ; scan for null, ecx = -(1+strlen(str)) + not ecx + dec ecx ; ecx = strlen(str) + mov eax,ecx ; eax = strlen(str) + +ifdef _STDCALL_ + ret DPSIZE ; _stdcall return +else + ret ; _cdecl return +endif + +strlen endp + end diff --git a/private/crt32/string/i386/strlwr.asm b/private/crt32/string/i386/strlwr.asm new file mode 100644 index 000000000..edec61eb3 --- /dev/null +++ b/private/crt32/string/i386/strlwr.asm @@ -0,0 +1,104 @@ + page ,132 + title strlwr - map string to lower-case +;*** +;strlwr.asm - routine to map lower-case characters in a string to upper-case +; +; Copyright (c) 1985-1991, Microsoft Corporation. All rights reserved. +; +;Purpose: +; STRLWR converts upper-case characters in a null-terminated string +; to their lower-case equivalents. Conversion is done in place and +; characters other than upper-case letters are not modified. +; +; This function modifies only 7-bit ASCII characters +; in the range 0x41 through 0x5A ('A' through 'Z'). +; +;Revision History: +; 04-21-87 SKS Rewritten to be fast and small, added file header +; 05-18-88 SJM Add model-independent (large model) ifdef +; 08-04-88 SJM convert to cruntime/ add 32-bit support +; 08-19-88 JCR Minor optimization +; 10-10-88 JCR Changed an 'xchg' to 'mov' +; 10-25-88 JCR General cleanup for 386-only code +; 10-26-88 JCR Re-arrange regs to avoid push/pop ebx +; 03-23-90 GJF Changed to _stdcall. Also, fixed the copyright. +; 01-18-91 GJF ANSI naming. +; 05-10-91 GJF Back to _cdecl, sigh... +; +;******************************************************************************* + + .xlist + include cruntime.inc + .list + +page +;*** +;char *_strlwr(string) - map upper-case characters in a string to lower-case +; +;Purpose: +; Converts all the upper case characters in a string to lower case, +; in place. +; +; Algorithm: +; char * _strlwr (char * string) +; { +; char * cp = string; +; +; while( *cp ) +; { +; if ('A' <= *cp && *cp <= 'Z') +; *cp += 'a' - 'A'; +; ++cp; +; } +; return(string); +; } +; +;Entry: +; char *string - string to change to lower case +; +;Exit: +; The input string address is returned in AX or DX:AX +; +;Uses: +; BX, CX, DX +; +;Exceptions: +; +;******************************************************************************* + + CODESEG + + public _strlwr +_strlwr proc \ + string:ptr byte + + + mov ecx,[string] ; ecx = *string + mov edx,ecx ; save return value + jmp short first_char; jump into the loop + + align @WordSize +check_char: + sub al,'A' ; 'A' <= al <= 'Z' ? + cmp al,'Z'-'A'+1 + jnb short next_char + add al,'a' ; map to lower case + mov [ecx],al ; and store new value +next_char: + inc ecx ; bump pointer +first_char: + mov al,[ecx] ; get next character + or al,al + jnz short check_char + +done: + mov eax,edx ; AX = return value ("string") + +ifdef _STDCALL_ + ret DPSIZE ; _stdcall return +else + ret ; _cdecl return +endif + +_strlwr endp + end diff --git a/private/crt32/string/i386/strncat.asm b/private/crt32/string/i386/strncat.asm new file mode 100644 index 000000000..b6060bb12 --- /dev/null +++ b/private/crt32/string/i386/strncat.asm @@ -0,0 +1,117 @@ + page ,132 + title strncat - append n chars of string1 to string2 +;*** +;strncat.asm - append n chars of string to new string +; +; Copyright (c) 1985-1991, Microsoft Corporation. All rights reserved. +; +;Purpose: +; defines strncat() - appends n characters of string onto +; end of other string +; +;Revision History: +; 10-25-83 RN initial version +; 08-05-87 SKS Fixed bug: extra null was stored if n > strlen(back) +; 05-18-88 SJM Add model-independent (large model) ifdef +; 08-04-88 SJM convert to cruntime/ add 32-bit support +; 08-23-88 JCR Minor 386 cleanup +; 10-26-88 JCR General cleanup for 386-only code +; 03-23-90 GJF Changed to _stdcall. Also, fixed the copyright. +; 05-10-91 GJF Back to _cdecl, sigh... +; +;******************************************************************************* + + .xlist + include cruntime.inc + .list + +page +;*** +;char *strncat(front, back, count) - append count chars of back onto front +; +;Purpose: +; Appends at most count characters of the string back onto the +; end of front, and ALWAYS terminates with a null character. +; If count is greater than the length of back, the length of back +; is used instead. (Unlike strncpy, this routine does not pad out +; to count characters). +; +; Algorithm: +; char * +; strncat (front, back, count) +; char *front, *back; +; unsigned count; +; { +; char *start = front; +; +; while (*front++) +; ; +; front--; +; while (count--) +; if (!(*front++ = *back++)) +; return(start); +; *front = '\0'; +; return(start); +; } +; +;Entry: +; char *front - string to append onto +; char *back - string to append +; unsigned count - count of max characters to append +; +;Exit: +; returns a pointer to string appended onto (front). +; +;Uses: +; +;Exceptions: +; +;******************************************************************************* + + CODESEG + + public strncat +strncat proc \ + uses edi esi, \ + front:ptr byte, \ + back:ptr byte, \ + count:IWORD + + + mov edi,[front] ; di=pointer to dest + + mov edx,edi ; save return value in dx + xor eax,eax ; search value: null byte (assumed zero below!) + or ecx,-1 ; cx = -1, so won't stop scan +repne scasb ; find null byte + dec edi ; di points to dest null terminator + mov esi,edi ; si " " " " " + + mov edi,[back] ; di points to source + + push edi ; save back pointer + mov ecx,[count] ; cx = count bytes negatively +repne scasb ; find null byte & get source length + jne short nonull + inc ecx ; do NOT count null byte in length +nonull: + ; cx=count of difference in bytes in source + ; with reference (without null) + sub ecx,[count] ; take the difference of bytes counted to expected + neg ecx ; away from expected + mov edi,esi ; di=pointer to dest null terminator + pop esi ; restore pointer to source +rep movsb ; concatenate the strings + ; WARNING: AL must be zero at this point! + stosb ; attach null byte + + mov eax,edx ; return value: dest addr + +ifdef _STDCALL_ + ret 2*DPSIZE + ISIZE ; _stdcall return +else + ret ; _cdecl return +endif + +strncat endp + end diff --git a/private/crt32/string/i386/strncmp.asm b/private/crt32/string/i386/strncmp.asm new file mode 100644 index 000000000..15b187651 --- /dev/null +++ b/private/crt32/string/i386/strncmp.asm @@ -0,0 +1,120 @@ + page ,132 + title strncmp - compare first n chars of two strings +;*** +;strncmp.asm - compare first n characters of two strings +; +; Copyright (c) 1985-1991, Microsoft Corporation. All rights reserved. +; +;Purpose: +; defines strncmp() - compare first n characters of two strings +; for lexical order. +; +;Revision History: +; 10-26-83 RN initial version +; 05-18-88 SJM Add model-independent (large model) ifdef +; 08-04-88 SJM convert to cruntime/ add 32-bit support +; 08-23-88 JCR 386 cleanup +; 10-26-88 JCR General cleanup for 386-only code +; 03-23-90 GJF Changed to _stdcall. Also, fixed the copyright. +; 05-10-91 GJF Back to _cdecl, sigh... +; +;******************************************************************************* + + .xlist + include cruntime.inc + .list + +page +;*** +;int strncmp(first, last, count) - compare first count chars of strings +; +;Purpose: +; Compares two strings for lexical order. The comparison stops +; after: (1) a difference between the strings is found, (2) the end +; of the strings is reached, or (3) count characters have been +; compared. +; +; Algorithm: +; int +; strncmp (first, last, count) +; char *first, *last; +; unsigned count; +; { +; if (!count) +; return(0); +; while (--count && *first && *first == *last) +; { +; first++; +; last++; +; } +; return(*first - *last); +; } +; +;Entry: +; char *first, *last - strings to compare +; unsigned count - maximum number of characters to compare +; +;Exit: +; returns <0 if first < last +; returns 0 if first == last +; returns >0 if first > last +; +;Uses: +; +;Exceptions: +; +;******************************************************************************* + + CODESEG + + public strncmp +strncmp proc \ + uses edi esi ebx, \ + first:ptr byte, \ + last:ptr byte, \ + count:IWORD + + + mov ecx,[count] ; cx=max number of bytes to compare + jecxz short toend ; it's as if strings are equal + + mov ebx,ecx ; bx saves count + + mov edi,[first] ; di=first pointer (es=segment part) + + mov esi,edi ; si saves first pointer + xor eax,eax ; ax=0 +repne scasb ; count bytes + neg ecx ; cx=count - strlen + add ecx,ebx ; strlen + count - strlen + +okay: + mov edi,esi ; restore first pointer + mov esi,[last] ; si = last pointer +repe cmpsb ; compare strings + mov al,[esi-1] + xor ecx,ecx ; set return value = 0 + + cmp al,[edi-1] ; last-first + ja short lastbig ; <last is bigger> + je short toend ; <equal> + ;jb short firstbig ; <first is bigger> + +firstbig: + dec ecx ; first string is bigger + dec ecx ; make FFFE so 'not' will give 0001 + +lastbig: ; last string is bigger + not ecx ; return -1 + +toend: + mov eax,ecx ; return value + +ifdef _STDCALL_ + ret 2*DPSIZE + ISIZE ; _stdcall return +else + ret ; _cdecl return +endif + +strncmp endp + end diff --git a/private/crt32/string/i386/strncpy.asm b/private/crt32/string/i386/strncpy.asm new file mode 100644 index 000000000..fcf882553 --- /dev/null +++ b/private/crt32/string/i386/strncpy.asm @@ -0,0 +1,108 @@ + page ,132 + title strncpy - copy at most n characters of string +;*** +;strncpy.asm - copy at most n characters of string +; +; Copyright (c) 1985-1991, Microsoft Corporation. All rights reserved. +; +;Purpose: +; defines strncpy() - copy at most n characters of string +; +;Revision History: +; 10-25-83 RN initial version +; 05-18-88 SJM Add model-independent (large model) ifdef +; 08-04-88 SJM convert to cruntime/ add 32-bit support +; 08-23-88 JCR 386 cleanup +; 10-26-88 JCR General cleanup for 386-only code +; 10-26-88 JCR Re-arrange regs to avoid push/pop ebx +; 03-23-90 GJF Changed to _stdcall. Also, fixed the copyright. +; 05-10-91 GJF Back to _cdecl, sigh... +; +;******************************************************************************* + + .xlist + include cruntime.inc + .list + +page +;*** +;char *strncpy(dest, source, count) - copy at most n characters +; +;Purpose: +; Copies count characters from the source string to the +; destination. If count is less than the length of source, +; NO NULL CHARACTER is put onto the end of the copied string. +; If count is greater than the length of sources, dest is padded +; with null characters to length count. +; +; Algorithm: +; char * +; strncpy (dest, source, count) +; char *dest, *source; +; unsigned count; +; { +; char *start = dest; +; +; while (count && (*dest++ = *source++)) +; count--; +; if (count) +; while (--count) +; *dest++ = '\0'; +; return(start); +; } +; +;Entry: +; char *dest - pointer to spot to copy source, enough space +; is assumed. +; char *source - source string for copy +; unsigned count - characters to copy +; +;Exit: +; returns dest, with the character copied there. +; +;Uses: +; +;Exceptions: +; +;******************************************************************************* + + CODESEG + + public strncpy +strncpy proc \ + uses edi esi, \ + dest:ptr byte, \ + sorc:ptr byte, \ + count:IWORD + + + mov edi,[dest] ; di=pointer to dest + mov esi,[sorc] ; si=pointer to source + + mov edx,edi ; dx saves dest pointer + mov ecx,[count] ; get the max char count + jecxz short toend ; don't do loop if nothing to move + +lupe: + lodsb ; get byte into al and kick si + or al,al ; see if we just moved a null + jz short outlupe ; end of string + + stosb ; store byte from al and kick di + loop lupe ; dec cx & jmp to lupe if nonzero + ; else drop out +outlupe: + xor al,al ; null byte to store +rep stosb ; store null for all cx>0 + +toend: + mov eax,edx ; return value: dest addr + +ifdef _STDCALL_ + ret 2*DPSIZE + ISIZE ; _stdcall return +else + ret ; _cdecl return +endif + +strncpy endp + end diff --git a/private/crt32/string/i386/strnicmp.asm b/private/crt32/string/i386/strnicmp.asm new file mode 100644 index 000000000..cec5ec5a6 --- /dev/null +++ b/private/crt32/string/i386/strnicmp.asm @@ -0,0 +1,153 @@ + page ,132 + title strnicmp - compare n chars of strings, ignore case +;*** +;strnicmp.asm - compare n chars of strings, ignoring case +; +; Copyright (c) 1985-1991, Microsoft Corporation. All rights reserved. +; +;Purpose: +; defines _strnicmp() - Compares at most n characters of two strings, +; without regard to case. +; +;Revision History: +; 04-04-85 RN initial version +; 07-11-85 TC zeroed cx, to allow correct return value if not equal +; 05-18-88 SJM Add model-independent (large model) ifdef +; 08-04-88 SJM convert to cruntime/ add 32-bit support +; 08-23-88 JCR 386 cleanup and improved return value sequence +; 10-26-88 JCR General cleanup for 386-only code +; 03-23-90 GJF Changed to _stdcall. Also, fixed the copyright. +; 01-18-91 GJF ANSI naming. +; 05-10-91 GJF Back to _cdecl, sigh... +; +;******************************************************************************* + + .xlist + include cruntime.inc + .list + + +page +;*** +;int _strnicmp(first, last, count) - compares count char of strings, ignore case +; +;Purpose: +; Compare the two strings for lexical order. Stops the comparison +; when the following occurs: (1) strings differ, (2) the end of the +; strings is reached, or (3) count characters have been compared. +; For the purposes of the comparison, upper case characters are +; converted to lower case. +; +; Algorithm: +; int +; _strncmpi (first, last, count) +; char *first, *last; +; unsigned int count; +; { +; int f,l; +; int result = 0; +; +; if (count) { +; do { +; f = tolower(*first); +; l = tolower(*last); +; first++; +; last++; +; } while (--count && f && l && f == l); +; result = f - l; +; } +; return(result); +; } +; +;Entry: +; char *first, *last - strings to compare +; unsigned count - maximum number of characters to compare +; +;Exit: +; returns <0 if first < last +; returns 0 if first == last +; returns >0 if first > last +; +;Uses: +; +;Exceptions: +; +;******************************************************************************* + + CODESEG + + public _strnicmp +_strnicmp proc \ + uses edi esi ebx, \ + first:ptr byte, \ + last:ptr byte, \ + count:IWORD + + + mov esi,[first] ; si = first string + mov edi,[last] ; di = last string + + mov ecx,[count] ; cx = byte count + jecxz short toend ; if count=0 + + mov bh,'A' + mov bl,'Z' + mov dh,'a'-'A' ; add to cap to make lower + +lupe: + mov ah,[esi] ; *first + mov al,[edi] ; *last + + or ah,ah ; see if *first is null + jz short eject ; jump if so + + or al,al ; see if *last is null + jz short eject ; jump if so + + inc esi ; first++ + inc edi ; last++ + + cmp ah,bh ; 'A' + jb short skip1 + + cmp ah,bl ; 'Z' + ja short skip1 + + add ah,dh ; make lower case + +skip1: + cmp al,bh ; 'A' + jb short skip2 + + cmp al,bl ; 'Z' + ja short skip2 + + add al,dh ; make lower case + +skip2: + cmp ah,al ; *first == *last ?? + jne short differ + + loop lupe + +eject: + xor ecx,ecx + cmp ah,al ; compare the (possibly) differing bytes + je short toend ; both zero; return 0 + +differ: + mov ecx,-1 ; assume last is bigger (* can't use 'or' *) + jb short toend ; last is, in fact, bigger (return -1) + neg ecx ; first is bigger (return 1) + +toend: + mov eax,ecx + +ifdef _STDCALL_ + ret 2*DPSIZE + ISIZE ; _stdcall return +else + ret ; _cdecl return +endif + +_strnicmp endp + end diff --git a/private/crt32/string/i386/strnset.asm b/private/crt32/string/i386/strnset.asm new file mode 100644 index 000000000..ae8a1248d --- /dev/null +++ b/private/crt32/string/i386/strnset.asm @@ -0,0 +1,104 @@ + page ,132 + title strnset - set first n characters to one char. +;*** +;strnset.asm - set first n characters to single character +; +; Copyright (c) 1985-1991, Microsoft Corporation. All rights reserved. +; +;Purpose: +; defines _strnset() - sets at most the first n characters of a string +; to a given character. +; +;Revision History: +; 11-18-83 RN initial version +; 05-18-88 SJM Add model-independent (large model) ifdef +; 05-23-88 WAJ If count = strlen(string)+1 then strlen+1 bytes were set. +; 08-04-88 SJM convert to cruntime/ add 32-bit support +; 08-23-88 JCR 386 cleanup +; 10-26-88 JCR General cleanup for 386-only code +; 03-23-90 GJF Changed to _stdcall. Also, fixed the copyright. +; 01-18-91 GJF ANSI naming. +; 05-10-91 GJF Back to _cdecl, sigh... +; +;******************************************************************************* + + .xlist + include cruntime.inc + .list + +page +;*** +;char *_strnset(string, val, count) - set at most count characters to val +; +;Purpose: +; Sets the first count characters of string the character value. +; If the length of string is less than count, the length of +; string is used in place of n. +; +; Algorithm: +; char * +; _strnset (string, val, count) +; char *string,val; +; unsigned int count; +; { +; char *start = string; +; +; while (count-- && *string) +; *string++ = val; +; return(start); +; } +; +;Entry: +; char *string - string to set characters in +; char val - character to fill with +; unsigned count - count of characters to fill +; +;Exit: +; returns string, now filled with count copies of val. +; +;Uses: +; +;Exceptions: +; +;******************************************************************************* + + CODESEG + + public _strnset +_strnset proc \ + uses edi ebx, \ + string:ptr byte, \ + val:byte, \ + count:IWORD + + + mov edi,[string] ; di = string + mov edx,edi ; dx=string addr; save return value + mov ebx,[count] ; cx = max chars to set + xor eax,eax ; null byte + mov ecx,ebx + jecxz short done ; zero length specified + +repne scasb ; find null byte & count bytes in cx + jne short nonull ; null not found + inc ecx ; don't want the null + +nonull: + sub ebx,ecx ; bx=strlen (not null) + mov ecx,ebx ; cx=strlen (not null) + + mov edi,edx ; restore string pointer + mov al,val ; byte value +rep stosb ; fill 'er up + +done: + mov eax,edx ; return value: string addr + +ifdef _STDCALL_ + ret DPSIZE + 2*ISIZE ; _stdcall return +else + ret ; _cdecl return +endif + +_strnset endp + end diff --git a/private/crt32/string/i386/strpbrk.asm b/private/crt32/string/i386/strpbrk.asm new file mode 100644 index 000000000..1ccde4d0b --- /dev/null +++ b/private/crt32/string/i386/strpbrk.asm @@ -0,0 +1,19 @@ +;*** +;strpbrk.asm - +; +; Copyright (c) 1991-1992, Microsoft Corporation. All rights reserved. +; +;Purpose: +; defines strpbrk()- finds the index of the first character in a string +; that is not in a control string +; +; NOTE: This stub module scheme is compatible with NT build +; procedure. +; +;Revision History: +; 09-25-91 JCR Stub module created. +; +;******************************************************************************* + +SSTRPBRK EQU 1 +INCLUDE I386\STRSPN.ASM diff --git a/private/crt32/string/i386/strrchr.asm b/private/crt32/string/i386/strrchr.asm new file mode 100644 index 000000000..3808b7b8b --- /dev/null +++ b/private/crt32/string/i386/strrchr.asm @@ -0,0 +1,105 @@ + page ,132 + title strrchr - find last occurence of character in string +;*** +;strrchr.asm - find last occurrence of character in string +; +; Copyright (c) 1985-1991, Microsoft Corporation. All rights reserved. +; +;Purpose: +; defines strrchr() - find the last occurrence of a given character +; in a string. +; +;Revision History: +; 10-27-83 RN initial version +; 05-18-88 SJM Add model-independent (large model) ifdef +; 08-04-88 SJM convert to cruntime/ add 32-bit support +; 08-23-88 JCR 386 cleanup +; 10-26-88 JCR General cleanup for 386-only code +; 03-26-90 GJF Changed to _stdcall. Also, fixed the copyright. +; 05-10-91 GJF Back to _cdecl, sigh... +; +;******************************************************************************* + + .xlist + include cruntime.inc + .list + +page +;*** +;char *strrchr(string, ch) - find last occurrence of ch in string +; +;Purpose: +; Finds the last occurrence of ch in string. The terminating +; null character is used as part of the search. +; +; Algorithm: +; char * +; strrchr (string, ch) +; char *string, ch; +; { +; char *start = string; +; +; while (*string++) +; ; +; while (--string != start && *string != ch) +; ; +; if (*string == ch) +; return(string); +; return(NULL); +; } +; +;Entry: +; char *string - string to search in +; char ch - character to search for +; +;Exit: +; returns a pointer to the last occurrence of ch in the given +; string +; returns NULL if ch does not occurr in the string +; +;Uses: +; +;Exceptions: +; +;******************************************************************************* + + CODESEG + + public strrchr +strrchr proc \ + uses edi, \ + string:ptr byte, \ + chr:byte + + mov edi,[string] ; di = string + xor eax,eax ; al=null byte + or ecx,-1 ; cx = -1 +repne scasb ; find the null & count bytes + inc ecx ; cx=-byte count (with null) + neg ecx ; cx=+byte count (with null) + dec edi ; di points to terminal null + mov al,chr ; al=search byte + std ; count 'down' on string this time +repne scasb ; find that byte + inc edi ; di points to byte which stopped scan + + cmp [edi],al ; see if we have a hit + je short returndi ; yes, point to byte + + xor eax,eax ; no, return NULL + jmp short toend ; do return sequence + +returndi: + mov eax,edi ; ax=pointer to byte + +toend: + cld + +ifdef _STDCALL_ + ret DPSIZE + ISIZE ; _stdcall return +else + ret ; _cdecl return +endif + +strrchr endp + end diff --git a/private/crt32/string/i386/strrev.asm b/private/crt32/string/i386/strrev.asm new file mode 100644 index 000000000..09071834e --- /dev/null +++ b/private/crt32/string/i386/strrev.asm @@ -0,0 +1,121 @@ + page ,132 + title strrev - reverse a string in place +;*** +;strrev.asm - reverse a string in place +; +; Copyright (c) 1985-1991, Microsoft Corporation. All rights reserved. +; +;Purpose: +; defines _strrev() - reverse a string in place (not including +; '\0' character) +; +;Revision History: +; 10-26-83 RN initial version +; 07-16-87 JCR Added check for empty string (fixes large model bug) +; 05-18-88 SJM Add model-independent (large model) ifdef +; 08-04-88 SJM convert to cruntime/ add 32-bit support +; 08-23-88 JCR 386 cleanup, minor alterations +; 10-26-88 JCR General cleanup for 386-only code +; 10-26-88 JCR Re-arrange regs to avoid push/pop ebx +; 03-26-90 GJF Changed to _stdcall. Also, fixed the copyright. +; 01-18-91 GJF ANSI naming. +; 05-10-91 GJF Back to _cdecl, sigh... +; +;******************************************************************************* + + .xlist + include cruntime.inc + .list + +page +;*** +;char *_strrev(string) - reverse a string in place +; +;Purpose: +; Reverses the order of characters in the string. The terminating +; null character remains in place. +; +; Algorithm: +; char * +; _strrev (string) +; char *string; +; { +; char *start = string; +; char *left = string; +; char ch; +; +; while (*string++) +; ; +; string -= 2; +; while (left < string) +; { +; ch = *left; +; *left++ = *string; +; *string-- = ch; +; } +; return(start); +; } +; +; NOTE: There is a check for an empty string in the following code. +; Normally, this would fall out of the "cmp si,di" instruction in the +; loop portion of the routine. However, if the offset of the empty +; string is 0 (as it could be in large model), then the cmp does not +; catch the empty string and the routine essentially hangs (i.e., loops +; moving bytes one at a time FFFFh times). An explicit empty string +; check corrects this. +; +;Entry: +; char *string - string to reverse +; +;Exit: +; returns string - now with reversed characters +; +;Uses: +; +;Exceptions: +; +;******************************************************************************* + + CODESEG + + public _strrev +_strrev proc \ + uses edi esi, \ + string:ptr byte + + mov edi,[string] ; di = string + mov edx,edi ; dx=pointer to string; save return value + + mov esi,edi ; si=pointer to string + xor eax,eax ; search value (null) + or ecx,-1 ; cx = -1 +repne scasb ; find null + cmp ecx,-2 ; is string empty? (if offset value is 0, the + je short done ; cmp below will not catch it and we'll hang). + + dec edi ; string is not empty, move di pointer back + dec edi ; di points to last non-null byte + +lupe: + cmp esi,edi ; see if pointers have crossed yet + jae short done ; exit when pointers meet (or cross) + + mov ah,[esi] ; get front byte... + mov al,[edi] ; and end byte + mov [esi],al ; put end byte in front... + mov [edi],ah ; and front byte at end + inc esi ; front moves up... + dec edi ; and end moves down + jmp short lupe ; keep switching bytes + +done: + mov eax,edx ; return value: string addr + +ifdef _STDCALL_ + ret DPSIZE ; _stdcall return +else + ret ; _cdecl return +endif + +_strrev endp + end diff --git a/private/crt32/string/i386/strset.asm b/private/crt32/string/i386/strset.asm new file mode 100644 index 000000000..8446a0812 --- /dev/null +++ b/private/crt32/string/i386/strset.asm @@ -0,0 +1,93 @@ + page ,132 + title strset - set all characters of string to character +;*** +;strset.asm - sets all charcaters of string to given character +; +; Copyright (c) 1985-1991, Microsoft Corporation. All rights reserved. +; +;Purpose: +; defines _strset() - sets all of the characters in a string (except +; the '\0') equal to a given character. +; +;Revision History: +; 11-18-83 RN initial version +; 05-18-88 SJM Add model-independent (large model) ifdef +; 08-04-88 SJM convert to cruntime/ add 32-bit support +; 08-23-88 JCR 386 cleanup +; 10-26-88 JCR General cleanup for 386-only code +; 03-26-90 GJF Changed to _stdcall. Also, fixed the copyright. +; 01-18-91 GJF ANSI naming. +; 05-10-91 GJF Back to _cdecl, sigh... +; +;******************************************************************************* + + .xlist + include cruntime.inc + .list + +page +;*** +;char *_strset(string, val) - sets all of string to val +; +;Purpose: +; Sets all of characters in string (except the terminating '/0' +; character) equal to val. +; +; Algorithm: +; char * +; _strset (string, val) +; char *string; +; char val; +; { +; char *start = string; +; +; while (*string) +; *string++ = val; +; return(start); +; } +; +;Entry: +; char *string - string to modify +; char val - value to fill string with +; +;Exit: +; returns string -- now filled with val's +; +;Uses: +; +;Exceptions: +; +;******************************************************************************* + + CODESEG + + public _strset +_strset proc \ + uses edi, \ + string:ptr byte, \ + val:byte + + + mov edi,[string] ; di = string + mov edx,edi ; dx=string addr; save return value + + xor eax,eax ; ax = 0 + or ecx,-1 ; cx = -1 +repne scasb ; scan string & count bytes + inc ecx + inc ecx ; cx=-strlen + neg ecx ; cx=strlen + mov al,[val] ; al = byte value to store + mov edi,edx ; di=string addr +rep stosb + + mov eax,edx ; return value: string addr + +ifdef _STDCALL_ + ret DPSIZE + ISIZE ; _stdcall return +else + ret ; _cdecl return +endif + +_strset endp + end diff --git a/private/crt32/string/i386/strspn.asm b/private/crt32/string/i386/strspn.asm new file mode 100644 index 000000000..803e4a223 --- /dev/null +++ b/private/crt32/string/i386/strspn.asm @@ -0,0 +1,277 @@ + page ,132 + title strspn - search for init substring of chars from control str +;*** +;strspn.asm - find length of initial substring of chars from a control string +; +; Copyright (c) 1985-1992, Microsoft Corporation. All rights reserved. +; +;Purpose: +; defines strspn() - finds the length of the initial substring of +; a string consisting entirely of characters from a control string. +; +; defines strcspn()- finds the length of the initial substring of +; a string consisting entirely of characters not in a control string. +; +; defines strpbrk()- finds the index of the first character in a string +; that is not in a control string +; +;Revision History: +; 10-28-83 RN initial version +; 06-30-87 SKS Faster version -- also reentrant +; 05-18-88 SJM Add model-independent (large model) ifdef +; 08-02-88 SJM Created 386-specific version. +; 08-23-88 JCR 386 cleanup +; 10-10-88 JCR Misc bug fixes +; 10-26-88 JCR General cleanup for 386-only code +; 03-26-90 GJF Changed to _stdcall. Also, fixed the copyright. +; 05-10-91 GJF Back to _cdecl, sigh... +; 09-25-91 JCR Build "strspn" if no other directives are given +; 01-17-92 GJF Fixed build of "strspn". +; +;******************************************************************************* + + .xlist + include cruntime.inc + .list + +page +;*** +;int strspn(string, control) - find init substring of control chars +; +;Purpose: +; Finds the index of the first character in string that does belong +; to the set of characters specified by control. This is +; equivalent to the length of the initial substring of string that +; consists entirely of characters from control. The '\0' character +; that terminates control is not considered in the matching process. +; +; Algorithm: +; int +; strspn (string, control) +; unsigned char *string, *control; +; { +; unsigned char map[32]; +; int count; +; +; for (count = 0; count < 32; count++) +; map[count] = 0; +; while (*control) +; { +; map[*control >> 3] |= (1 << (*control & 7)); +; control++; +; } +; if (*string) +; { +; while (map[*string >> 3] & (1 << (*string & 7))) +; { +; count++; +; string++; +; } +; return(count); +; } +; return(0); +; } +; +;Entry: +; char *string - string to search +; char *control - string containing characters not to search for +; +;Exit: +; returns index of first char in string not in control +; +;Uses: +; +;Exceptions: +; +;******************************************************************************* + +;*** +;int strcspn(string, control) - search for init substring w/o control chars +; +;Purpose: +; returns the index of the first character in string that belongs +; to the set of characters specified by control. This is equivalent +; to the length of the length of the initial substring of string +; composed entirely of characters not in control. Null chars not +; considered. +; +; Algorithm: +; int +; strcspn (string, control) +; unsigned char *string, *control; +; { +; unsigned char map[32]; +; int count; +; +; for (count = 0; count < 32; count++) +; map[count] = 0; +; while (*control) +; { +; map[*control >> 3] |= (1 << (*control & 7)); +; control++; +; } +; map[0] |= 1; +; while (!(map[*string >> 3] & (1 << (*string & 7)))) +; { +; count++; +; string++; +; } +; return(count); +; } +; +;Entry: +; char *string - string to search +; char *control - set of characters not allowed in init substring +; +;Exit: +; returns the index of the first char in string +; that is in the set of characters specified by control. +; +;Uses: +; +;Exceptions: +; +;******************************************************************************* + +;*** +;char *strpbrk(string, control) - scans string for a character from control +; +;Purpose: +; Finds the first occurence in string of any character from +; the control string. +; +; Algorithm: +; char * +; strpbrk (string, control) +; unsigned char *string, *control; +; { +; unsigned char map[32]; +; int count; +; +; for (count = 0; count < 32; count++) +; map[count] = 0; +; while (*control) +; { +; map[*control >> 3] |= (1 << (*control & 7)); +; control++; +; } +; while (*string) +; { +; if (map[*string >> 3] & (1 << (*string & 7))) +; return(string); +; string++; +; } +; return(NULL); +; } +; +;Entry: +; char *string - string to search in +; char *control - string containing characters to search for +; +;Exit: +; returns a pointer to the first character from control found +; in string. +; returns NULL if string and control have no characters in common. +; +;Uses: +; +;Exceptions: +; +;******************************************************************************* + + +ifdef SSTRCSPN + + _STRSPN_ equ <strcspn> + +elseifdef SSTRPBRK + + _STRSPN_ equ <strpbrk> + +else + +; Default is to build strspn() + + SSTRSPN equ 1 + _STRSPN_ equ <strspn> + +endif + +% public _STRSPN_ + + CODESEG + +_STRSPN_ proc \ + uses edi esi, \ + string:ptr byte, \ + control:ptr byte + + local map[8]:dword ; 8*4*8 = 256 bits + +; Zero out char bit map + + mov ecx, 8 ; clear the 256 bits + xor eax, eax + lea edi, [map] +rep stosd + +; Set control char bits in map + + mov esi,control ; si = control string + + align @WordSize +lab listnext ; init char bit map + lodsb + or al,al + jz short listdone + bts map, eax + jmp short listnext + +lab listdone + +; Loop through comparing source string with control bits + + mov esi, string ; si = string + +_ifnd SSTRPBRK <dec ecx> ; set ecx to -1 + + align @WordSize +lab dstnext + +_ifnd SSTRPBRK <inc ecx> + + lodsb + or al,al + jz short dstdone + bt map, eax + +ifdef SSTRSPN + jc short dstnext ; strspn: found char, continue +elseifdef SSTRCSPN + jnc short dstnext ; strcspn: did not find char, continue +elseifdef SSTRPBRK + jnc short dstnext ; strpbrk: did not find char, continue + lea eax,[esi-1] ; found char, return address of it + jmp short done +endif + +; Return code + +lab dstdone + +ifndef SSTRPBRK + mov eax,ecx ; strspn/strcspn: return index +else + xor eax,eax ; strpbrk: no chars in common, return NULL +done: + +endif + +ifdef _STDCALL_ + ret 2*DPSIZE ; _stdcall return +else + ret ; _cdecl return +endif + +_STRSPN_ endp + end diff --git a/private/crt32/string/i386/strstr.asm b/private/crt32/string/i386/strstr.asm new file mode 100644 index 000000000..81a9b76bd --- /dev/null +++ b/private/crt32/string/i386/strstr.asm @@ -0,0 +1,135 @@ + page ,132 + title strstr - search for one string inside another +;*** +;strstr.asm - search for one string inside another +; +; Copyright (c) 1985-1991, Microsoft Corporation. All rights reserved. +; +;Purpose: +; defines strstr() - search for one string inside another +; +;Revision History: +; 02-02-88 SKS Rewritten from scratch. Now works correctly with +; strings > 32 KB in length. Also smaller and faster. +; 03-01-88 SKS Ensure that ES = DS right away (Small/Medium models) +; 05-18-88 SJM Add model-independent (large model) ifdef +; 08-04-88 SJM convert to cruntime/ add 32-bit support +; 08-18-88 PHG Corrected return value when src is empty string +; to conform with ANSI. +; 08-23-88 JCR Minor 386 cleanup +; 10-26-88 JCR General cleanup for 386-only code +; 03-26-90 GJF Changed to _stdcall. Also, fixed the copyright. +; 05-10-91 GJF Back to _cdecl, sigh... +; +;******************************************************************************* + + .xlist + include cruntime.inc + .list + +page +;*** +;char *strstr(string1, string2) - search for string2 in string1 +; +;Purpose: +; finds the first occurrence of string2 in string1 +; +;Entry: +; char *string1 - string to search in +; char *string2 - string to search for +; +;Exit: +; returns a pointer to the first occurrence of string2 in +; string1, or NULL if string2 does not occur in string1 +; +;Uses: +; +;Exceptions: +; +;******************************************************************************* + + CODESEG + + public strstr +strstr proc \ + uses esi edi ebx, \ + dst:ptr byte, \ + src:ptr byte + + local srclen:IWORD + + + mov edi, (src) ; di = src + xor eax,eax ; Scan for null at end of (src) + or ecx,-1 ; cx = -1 +repnz scasb + not ecx + dec ecx + jecxz short empty_src ; src == "" ? + dec ecx ; CX = strlen(src)-1 + mov (srclen),ecx + + mov edi,(dst) + mov ebx,edi ; BX will keep the current offset into (dst) + + xor eax,eax ; Scan for null at end of (dst) + or ecx,-1 ; cx = -1 +repnz scasb + not ecx + dec ecx ; CX = strlen(dst) + + mov edx,ecx ; Save strlen(dst) in DX + + sub edx,(srclen) ; DX = strlen(dst) - (strlen(src)-1) + jbe short not_found ; strlen(dst) <= (strlen(src)-1) + ; target is longer than source? + mov edi,ebx ; restore ES:DI = (dst) + +findnext: + mov esi,IWORD ptr (src) + lodsb ; Get the first byte of the source + mov edi,ebx ; restore position in source + mov ecx,edx ; count of possible starting bytes in src +; +; CX, DX = number of bytes left in source where target can still fit +; DI, BX = current position in (dst) +; DS:SI = (src) + 1 +; AL = *(src) +; + +repne scasb ; find next occurrence of *(target) in dst + jne short not_found ; out of string -- return NULL + + mov edx,ecx ; update count of acceptable bytes left in dst + mov ebx,edi ; save current offset in dst + + mov ecx,(srclen) + jecxz short match ; single character src string? + +repe cmpsb + jne short findnext + +; +; Match! Return (BX-1) +; +match: + lea eax,[ebx-1] + jmp short retval + +empty_src: ; empty src string, return dst (ANSI mandated) + mov eax,(dst) ; eax = dst + jmp short retval ; return + +not_found: + xor eax,eax + +retval: + +ifdef _STDCALL_ + ret 2*DPSIZE ; _stdcall return +else + ret ; _cdecl return +endif + +strstr endp + end diff --git a/private/crt32/string/i386/strupr.asm b/private/crt32/string/i386/strupr.asm new file mode 100644 index 000000000..c8b66243f --- /dev/null +++ b/private/crt32/string/i386/strupr.asm @@ -0,0 +1,104 @@ + page ,132 + title strupr - map string to upper-case +;*** +;strupr.asm - routine to map lower-case characters in a string to upper-case +; +; Copyright (c) 1985-1991, Microsoft Corporation. All rights reserved. +; +;Purpose: +; _strupr() converts lower-case characters in a null-terminated string +; to their upper-case equivalents. Conversion is done in place and +; characters other than lower-case letters are not modified. +; +; This function modifies only 7-bit ASCII characters +; in the range 0x61 through 0x7A ('a' through 'z'). +; +;Revision History: +; 04-21-87 SKS Rewritten to be fast and small, added file header +; 05-18-88 SJM Add model-independent (large model) ifdef +; 08-04-88 SJM convert to cruntime/ add 32-bit support +; 08-19-88 JCR Minor optimization +; 10-10-88 JCR Changed an 'xchg' to 'mov' +; 10-26-88 JCR General cleanup for 386-only code +; 10-26-88 JCR Re-arrange regs to avoid push/pop ebx +; 03-26-90 GJF Changed to _stdcall. Also, fixed the copyright. +; 01-18-91 GJF ANSI naming. +; 05-10-91 GJF Back to _cdecl, sigh... +; +;******************************************************************************* + + .xlist + include cruntime.inc + .list + +page +;*** +;char *_strupr(string) - map lower-case characters in a string to upper-case +; +;Purpose: +; Converts all the lower case characters in string to upper case +; in place. +; +; Algorithm: +; char * _strupr (char * string) +; { +; char * cp = string; +; +; while( *cp ) +; { +; if ('a' <= *cp && *cp <= 'z') +; *cp += 'A' - 'a'; +; ++cp; +; } +; return(string); +; } +; +;Entry: +; char *string - string to change to upper case +; +;Exit: +; The input string address is returned in AX or DX:AX +; +;Uses: +; BX, CX, DX +; +;Exceptions: +; +;******************************************************************************* + + CODESEG + + public _strupr +_strupr proc \ + string:ptr byte + + + mov ecx,[string] ; cx = *string + mov edx,ecx ; save return value + jmp short first_char; jump into the loop + + align @WordSize +check_char: + sub al,'a' ; 'a' <= al <= 'z' ? + cmp al,'z'-'a'+1 + jnb short next_char + add al,'A' ; map to upper case + mov [ecx],al ; and store new value +next_char: + inc ecx ; bump pointer +first_char: + mov al,[ecx] ; get next character + or al,al + jnz short check_char + +done: + mov eax,edx ; ax = return value ("string") + +ifdef _STDCALL_ + ret DPSIZE ; _stdcall return +else + ret ; _cdecl return +endif + +_strupr endp + end |