2025-04-27 07:49:33 -04:00

136 lines
3.2 KiB
NASM

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