Zitat von
3_of_8:
Meine Idee wäre jetzt sowas gewesen:
Ich rufe AnsiLowerCase auf, denn substr steht in eax.
Dann pushe ich eax auf den Stack und lade edx (wo s steht) nach eax, rufe wieder AnsiLowerCase auf und lade eax nach edx.
Dann poppe ich eax wieder runter.
Gibt nur ne
AV. Warum? Was mache ich falsch?
@Manuel,
Wenn Du AnsiLowerCase aufrufst, dann werden dort EDX und auch ECX verändert, d.h. sowohl @s und p sind nicht mehr verfügbar.
Du könntest das lösen, indem Du vor Aufruf von AnsiLowerCase die Register rettest, z.B.
push ecx
push edx
call AnsiLowerCase
xchg [esp],eax // @LowerCase(substr) auf Stack, EAX=@s
call AnsiLowerCase
mov edx, eax // @LowerCase(s)
pop eax // @LowerCase(substr)
pop ecx // p
Aber das wäre eher kontraproduktiv weil damit die Performance im Eimer ist.
Ich hab das mal ungeschrieben in 3 Funktionen
1) StrAtPos = binärer Vergleich
2) TextAtPos = arbeitet case insensitiv für A..Z / a..z
3) AnsiTextPos = arbeitet komplett case insensitiv
Um die Längenprüfung nicht in allen Funktionen vornehmen zu müssen, habe diese in eine separate Prozedur _CheckLengths ausgelagert.
Das Retten der Register EDI und ESI wird in _CheckLengths vorgenommen, d.h. EDI und ESI müssen in ..AtPos nicht auf den Stack gelegt, jedoch am Ende vom Stack genommen werden.
Wenn bereits die Längenprüfung ein False ergibt, dann wird nicht in die ..AtPos Funtionen zurückgekehrt sondern dorthin von wo ..AtPos aufgerufen wurde (und es wird natürlich False zurückgegeben).
Damit entfällt auch in den ..AtPos Funktionen die Prüfung des Resultates von _CheckLengths.
Ist ein bischen trickie, funktioniert aber.
Wenn mir nicht grobe Fehler unterlaufen sind, sollten die Funktionen das tun was sie tun sollen.
Delphi-Quellcode:
// Subroutine für die Funktionen StrAtPos, TextAtPos, AnsiTextAtPos
// --> EAX=@substr, EDX=@s, ECX=p
// Prüft ob die strings s und subst nicht leer sind und ob s lang genug ist,
// um ab s[p] substr enthalten zu können. Wenn p=0 ist, wird p=1 angenommen.
// Mögliche Resultate:
// 1) Einer der Stings ist leer oder s nicht lang genug:
// Rücksprung zu der Adresse, von der die aufrufende Funktion aufgerufen
// wurde mit dem Resultat False
// 2) Längenprüfung OK
// <-- EDI=@s[p], ESI=@Substr, ECX=Length(substr)
// EDI und ESI wurden auf den Stack gelegt und müssen von der aufrufenden
// Routine vom Stack genommen werden
PROCEDURE _CheckLengths;
asm
xchg [esp],edi
// EDI auf Stack, EDI=Returnadresse
push esi
// ESI auf Stack
push edi
// Returnadresse auf Stack
test eax,eax
je @Fail
// substring leer
test edx,edx
je @Fail
// s leer
test ecx,ecx
jne @1
mov ecx,1
@1: mov esi,eax
// @substr
lea edi,[edx+ecx-1]
// @s[p]
mov eax,ecx
// p
mov ecx,[esi-4]
// Lenght(substr)
test ecx,ecx
je @Fail
// Lenght(substr)=0
lea eax,[eax+ecx-1]
// p+Length(substr)-1
cmp eax,[edx-4]
jbe @
End
@Fail:
xor eax,eax
pop ecx
// Resturnadresse der aufrufenden Funktion
pop esi
pop edi
@
End:
end;
FUNCTION StrAtPos(
const substr,s:
string; p:integer):boolean;
asm
call _CheckLengths
mov edx,ecx
shr ecx,2
repe cmpsd
// (Lenght(substr) div 4) mal 4 Bytes vergleichen
jne @SetRes
@Bytes: mov ecx,edx
and ecx,3
repe cmpsb
// (Lenght(substr) and 3) Bytes vergleichen
@SetRes: sete al
@
End: pop esi
pop edi
end;
FUNCTION TextAtPos(
const substr,s:
string; p:integer):boolean;
asm
call _CheckLengths
@Loop: sub ecx,1
jc @SetRes
mov al,[esi+ecx]
// Char aus substr
mov
dl,[edi+ecx]
// Char aus s
xor al,
dl
je @Loop
// identisch
cmp al,$20
jne @Fail
// nicht nur Bit 5 unterschiedlich
and dl,$
DF // Bit 5 in DL löschen (=UpperCase)
cmp
dl,'
A'
jb @Fail
cmp
dl,'
Z'
jbe @Loop
@Fail: clc
@SetRes: setc al
@
End: pop esi
pop edi
end;
FUNCTION AnsiTextAtPos(
const substr,s:
string; p:integer):boolean;
asm
call _CheckLengths
@Loop: sub ecx,1
jc @SetRes
mov al,[esi+ecx]
// Char aus substr
mov
dl,[edi+ecx]
// Char aus s
xor al,
dl
je @Loop
// identisch
cmp al,$20
jne @Fail
// nicht nur Bit 5 unterschiedlich
and dl,$
DF // Bit 5 in DL löschen (=UpperCase)
cmp
dl,'
A'
jb @Fail
cmp
dl,'
Z'
jbe @Loop
cmp
dl,$C0
jb @Fail
cmp
dl,$D7
je @Fail
cmp
dl,$
df
jne @Loop
@Fail: clc
@SetRes: setc al
@
End: pop esi
pop edi
end;