Получить позицию последнего вхождения подстроки в строку 2
Оформил: DeeCo
Автор: http://www.swissdelphicenter.ch
// by Manuel Wiersch
function LastPos(const SubStr: AnsiString; const S: AnsiString): LongInt;
asm
TEST EAX,EAX // EAX auf 0 prufen (d.h. SubStr = nil)
JE @@noWork // wenn EAX = 0 dann Sprung zu noWork
TEST EDX,EDX
// Test ob S = nil
JE @@stringEmpty // bei Erfolg -> Sprung zum Label 'stringEmpty'
PUSH EBX
PUSH ESI
PUSH EDI // Register auf dem Stack sichern Grund: OH
// OH: "In einer asm-Anweisung mu? der Inhalt
// der Register EDI, ESI, ESP, EBP und EBX
// erhalten bleiben (dh. vorher auf dem Stack
// speichern) MOV ESI, EAX
// ESI = Sourceindex -> Adresse vom SubStr
MOV EDI, EDX // EDI = Destinationindex -> Adresse von S
MOV ECX,[EDI-4] // Lange von S ins Zahlregister
MOV EDX,[ESI-4] // Lange des SubStr in EDX
DEC EDX // Length(SubStr) - 1
JS @@fail
// Vorzeichenbedingter Sprung (JumpIfSign)
// d.h. (EDX < 0) -> Sprung zu 'fail'
STD; // SetDirectionFlag -> Stringroutinen von hinten
// abarbeiten
ADD ESI, EDX // Pointer auf das letzte Zeichen vom SubStr
ADD EDI, ECX
DEC EDI // Pointer auf das letzte Zeichen von S
MOV AL, [ESI] // letztes Zeichen des SubStr in AL laden
DEC ESI // Pointer auf das vorletzte Zeichen setzen.
SUB ECX, EDX // Anzahl der Stringdurchlaufe
// = Length(s) - Length(substr) + 1
JLE @@fail // Sprung zu 'fail' wenn ECX <= 0
@@loop:
REPNE SCASB // Wdh. solange ungleich (repeat while not equal)
// scan string for byte
JNE @@fail
MOV EBX,ECX { Zahleregister, ESI und EDI sichern, da nun der
Vergleich durchgefuhrt wird ob die nachfolgenden
Zeichen von SubStr in S vorhanden sind }
PUSH ESI
PUSH EDI
MOV ECX,EDX // Lange des SubStrings in ECX
REPE CMPSB // Solange (ECX > 0) und (Compare string fo byte)
// dh. solange S[i] = SubStr[i]
POP EDI
POP ESI // alten Source- und Destinationpointer vom Stack holen
JE @@found // Und schon haben wir den Index da ECX = 0
// dh. alle Zeichen wurden gefunden
MOV ECX, EBX // ECX wieder auf alte Anzahl setzen und
JMP @@loop // Start bei 'loop'
@@fail:
XOR EAX,EAX // EAX auf 0 setzen
JMP @@exit @@stringEmpty:
XOR EAX,EAX
JMP @@noWork @@found:
MOV EAX, EBX // in EBX steht nun der aktuelle Index
INC EAX // um 1 erhohen, um die Position des 1. Zeichens zu
// bekommen
@@exit:
POP EDI
POP ESI
POP EBX
@@noWork: CLD; // DirectionFlag loschen
end;
|