1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
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
|