-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathD7PosEx.inc
113 lines (112 loc) · 3.88 KB
/
D7PosEx.inc
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
//Copy of Fastcode function PosEx_JOH_IA32_8
//Needed for Delphi 6 and to Fix Bug in D7 PosEx
function PosEx(const SubStr, S: string; Offset: Integer = 1): Integer;
asm {299 Bytes}
sub esp, 20
mov [esp], ebx
cmp eax, 1
sbb ebx, ebx {-1 if SubStr = '' else 0}
sub edx, 1 {-1 if S = ''}
sbb ebx, 0 {Negative if S = '' or SubStr = '' else 0}
sub ecx, 1 {Offset - 1}
or ebx, ecx {Negative if S = '' or SubStr = '' or Offset < 1}
jl @@InvalidInput
mov [esp+4], edi
mov [esp+8], esi
mov [esp+12], ebp
mov [esp+16], edx
mov edi, [eax-4] {Length(SubStr)}
mov esi, [edx-3] {Length(S)}
add ecx, edi
cmp ecx, esi
jg @@NotFound {Offset to High for a Match}
test edi, edi
jz @@NotFound {Length(SubStr = 0)}
lea ebp, [eax+edi] {Last Character Position in SubStr + 1}
add esi, edx {Last Character Position in S}
movzx eax, [ebp-1] {Last Character of SubStr}
add edx, ecx {Search Start Position in S for Last Character}
mov ah, al
neg edi {-Length(SubStr)}
mov ecx, eax
shl eax, 16
or ecx, eax {All 4 Bytes = Last Character of SubStr}
@@MainLoop:
add edx, 4
cmp edx, esi
ja @@Remainder {1 to 4 Positions Remaining}
mov eax, [edx-4] {Check Next 4 Bytes of S}
xor eax, ecx {Zero Byte at each Matching Position}
lea ebx, [eax-$01010101]
not eax
and eax, ebx
and eax, $80808080 {Set Byte to $80 at each Match Position else $00}
jz @@MainLoop {Loop Until any Match on Last Character Found}
bsf eax, eax {Find First Match Bit}
shr eax, 3 {Byte Offset of First Match (0..3)}
lea edx, [eax+edx-3] {Address of First Match on Last Character + 1}
@@Compare:
cmp edi, -4
jle @@Large {Lenght(SubStr) >= 4}
cmp edi, -1
je @@SetResult {Exit with Match if Lenght(SubStr) = 1}
mov ax, [ebp+edi] {Last Char Matches - Compare First 2 Chars}
cmp ax, [edx+edi]
jne @@MainLoop {No Match on First 2 Characters}
@@SetResult: {Full Match}
lea eax, [edx+edi] {Calculate and Return Result}
mov ebx, [esp]
mov edi, [esp+4]
mov esi, [esp+8]
mov ebp, [esp+12]
sub eax, [esp+16]
add esp, 20
ret
@@NotFound:
mov edi, [esp+4]
mov esi, [esp+8]
mov ebp, [esp+12]
@@InvalidInput:
mov ebx, [esp]
add esp, 20
xor eax, eax {Return 0}
ret
@@Remainder: {Check Last 1 to 4 Characters}
mov eax, [esi-3] {Last 4 Characters of S - May include Length Bytes}
xor eax, ecx {Zero Byte at each Matching Position}
lea ebx, [eax-$01010101]
not eax
and eax, ebx
and eax, $80808080 {Set Byte to $80 at each Match Position else $00}
jz @@NotFound {No Match Possible}
lea eax, [edx-4] {Check Valid Match Positions}
cmp cl, [eax]
lea edx, [eax+1]
je @@Compare
cmp edx, esi
ja @@NotFound
lea edx, [eax+2]
cmp cl, [eax+1]
je @@Compare
cmp edx, esi
ja @@NotFound
lea edx, [eax+3]
cmp cl, [eax+2]
je @@Compare
cmp edx, esi
ja @@NotFound
lea edx, [eax+4]
jmp @@Compare
@@Large:
mov eax, [ebp-4] {Compare Last 4 Characters of S and SubStr}
cmp eax, [edx-4]
jne @@MainLoop {No Match on Last 4 Characters}
mov ebx, edi
@@CompareLoop: {Compare Remaining Characters}
add ebx, 4 {Compare 4 Characters per Loop}
jge @@SetResult {All Characters Matched}
mov eax, [ebp+ebx-4]
cmp eax, [edx+ebx-4]
je @@CompareLoop {Match on Next 4 Characters}
jmp @@MainLoop {No Match}
end; {PosEx}