DELPHI7的通配符比较的汇编函数
DELPHI7中的POS()函数是不能用通配符的,但是有汇编代码公开的,于是我想能否把此汇编函数改编成可能用通配符,有此想法已有多年了,最近我重新研究这个问题,发现是可行了,并做了出来,由于时间仓促,错误在所难免,希望能发现此汇编函数有BUG者能反馈给我知,我就多谢大家了。下面是我修改DELPHI7中的POS()而成的POSLI()的汇编源码,我试过可以通配符的,未知有无什么BUG,希望有人通知我BUG在何处。
此汇编函数支持?号只匹配一个中文。只支持?号和*号,不支持[]号。例如:子串为"Edit*1*2*3?4*5",源串为"Edit111www222123国45qEdit222www333qq"时将返回最后一个*号之后第一个字符的匹配处INDEX。
如果子串没有*号,返回子串第一个字符的匹配INDEX,如果子串有*号,返回最后一个最接近*号的字符的匹配INDEX值。总之,返回值大于0就表示匹配成功了。
此函数支持中文查找,如子串为"谢",源串为"中华",返回0,虽然中之后半字节和华之前半字节合成谢字,但我这汇编函数已做了处理了。
此汇编函数参数为PCHAR,可以传多于255个字符的字串作参数也!
function Posli( substr :pchar ; s : pchar ) : Integer;
var
dlen,sublen,esi0,edi0,starnum,starnum2,ifbacknum:integer;
asm
{ ->EAX Pointer to substr }
{ EDX Pointer to string }
{ <-EAX Position of substr in s or 0 }
PUSH EBX
PUSH ESI
PUSH EDI
MOV ESI,EAX { Point ESI to substr }
MOV EDI,EAX
MOV starnum,0
MOV starnum2,0
MOV dlen,0
MOV sublen,0
XOR ECX,ECX
MOV CL,[EDI]
INC EDI
////////////////////////
XOR ECX,ECX
MOV ECX,0FFFFFFFFH
XOR AL,AL
REPNE SCASB
NOT ECX
MOV sublen,ECX
//SUB sublen,2
/////////////////////////
MOV EDI,ESI
MOV AL,'*'
@@start0:
REPNE SCASB
JNE @@start
ADD starnum,1
JMP @@start0
//////////////////////////////
@@start:
///////////////////////////////
MOV EDI,EDX
INC EDI
XOR ECX,ECX
MOV ECX,0FFFFFFFFH
XOR AL,AL
REPNE SCASB
NOT ECX
MOV dlen,ECX
//SUB dlen,1
/////////////////////////////////////////
MOV EDI,EDX { Point EDI to s }
MOV esi0,ESI
MOV edi0,EDI
XOR ECX,ECX { ECX = Length(s) }
MOV CL,[EDI]
MOV ECX, dlen
PUSH EDI { remember s position to calculate index }
//INC EDI { Point EDI to first char of s }
XOR EDX,EDX { EDX = Length(substr) }
MOV DL,[ESI]
//INC ESI { Point ESI to first char of substr }
MOV EDX, sublen
CMP EDX,0 { EDX = Length(substr) - 1 }
JS @@fail { < 0 ? return 0 }
MOV AL,[ESI] { AL = first char of substr }
//INC ESI { Point ESI to 2'nd char of substr }
DEC EDX
SUB ECX,EDX { #positions in s to look at }
{ = Length(s) - Length(substr) + 1 }
ADD ECX,starnum
JLE @@fail
PUSH ESI { save outer loop substr pointer }
PUSH EDI { save outer loop s pointer }
MOV ECX,sublen
ADD EDI,1
JMP @@star
@@loop:
REPNE SCASB
JNE @@fail
MOV EBX,ECX { save outer loop counter }
PUSH ESI { save outer loop substr pointer }
PUSH EDI { save outer loop s pointer }
MOV ECX,EDX
@@loopwww:
// MOV AL,[ESI]
// MOV AL,[ESI-1]
//MOV AL,[ESI-2]
REPE CMPSB
//PUSH ESI
JE @@found
//INC EDI
///////////////
//MOV AL,[ESI]
//MOV AL,[ESI-1]
//MOV AL,[EDI-1]
//CMP AL,[ESI-1]
//JE @@found
CMP ECX,0
JE @@iffound1
{MOV AL,[ESI]
CMP AL,$12
JE @@found
CMP AL,$0
JE @@found
CMP AL,$FF
JE @@found}
/////////////////
@@iffound2:
//PUSH EAX
MOV AL,[ESI]
SUB ESI,1
MOV AL,[ESI]
INC ESI
//INC ESI
CMP AL,'?'
//POP ESI
JE @@what
CMP AL,'*'
JE @@star
//MOV AL,[ESI]
//CMP AL,$12
//JE @@fail2
//CMP AL,$0
//JE @@fail2
//POP EAX
MOV AL,[EDI]
CMP AL,$12
JE @@fail2
CMP AL,$0
JE @@fail2
////////////////有可能源串短于子串也,因?号匹配中文也
POP EDI { restore outer loop s pointer }
POP ESI { restore outer loop substr pointer }
MOV ECX,EBX { restore outer loop counter }
JMP @@loopOK
@@what:
MOV EAX,0
MOV EAX,EDI
SUB EAX,dlen
CMP EAX,edi0
JGE @@fail2
///////如果源串已结束则必NO //BUG
MOV AL,[ESI]
CMP AL,$12 //此当结束
//POP EAX
JE @@found
CMP AL,$0
JE @@found
//push eax
//MOV AL,[ESI]
//CMP AL,$0 //此也当结束,为经验,不知何解
//POP EAX
CMP ECX,0
JE @@found
/////////////////////
MOV AL,[EDI]
CMP AL,$80
JNB @@chinese
@@whatchinese:
MOV AL,[ESI]
////////////////////////
JMP @@loopwww
@@chinese:
ADD EDI,1
JMP @@whatchinese
@@star:
ADD starnum2,1
SUB EDI,1
MOV AL,[ESI]
CMP AL,$12
//POP EAX
JE @@found
CMP AL,$0
JE @@found
// POP EAX
// POP EAX
/////////
//XOR ECX,ECX
// MOV CL,[EDI]
// INC EDI { Point EDI to first char of s }
// PUSH EDI { remember s position to calculate index }
// XOR EDX,EDX { EDX = Length(substr) }
// MOV DL,[ESI]
// INC ESI { Point ESI to first char of substr }
// DEC EDX { EDX = Length(substr) - 1 }
// JS @@fail { < 0 ? return 0 }
// XOR EAX,EAX
//////////////////////////
////////////////////
//PUSH EAX
@@www:
CMP ECX,0
JE @@found
MOV EAX,0
MOV EAX,EDI
SUB EAX,dlen
CMP EAX,edi0
JG @@fail2
////////////////////
MOV AL,[ESI]
ADD ESI,1