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
| // Case avec des strings (Pascal Peyremorte)
FUNCTION ChercheTexte(Const Chaine,Texte:ShortString):Integer; Assembler;
Var
Table : Array[Byte] of Byte;
Asm
push edi {Il faut conserver EDI, ESI, EBX, ESP et EBP}
push esi
push ebx
cld
{Récupère longueur(eax) et adresse(esi) de Chaine}
mov esi,Chaine
xor eax,eax {Pour conversion byte -> 32b}
lodsb {Récup longueur Chaine et pointe premier car}
or al,al {Si longueur=0 : Exit}
jz @Inconnue
{Récupère longueur(ecx) et adresse(edi) de Texte}
mov edi,Texte
xor ecx,ecx {Pour conversion byte -> 32b}
mov cl,[edi] {Récup longueur Texte}
jcxz @Inconnue {Si longueur=0 : Exit}
inc edi {Saute l'octet longueur et pointe premier car}
{Si Long(Chaine)=1, c'est 1 caractère -> recherche simplifiée}
cmp eax,1
jne @Boyer_Moore
{--- Recherche simplifiée ---}
lodsb {Récupère l'unique caractère de Chaine}
repne scasb {et le cherche dans Texte}
jnz @Inconnue {pas trouvé, exit}
mov esi,edi
sub esi,2
jmp @Corresp
{--- Recherche Boyer-Moore ---}
@Boyer_Moore:
push edi {on aura besoin de @ du premier car de Texte}
mov edx,ecx {et de longueur de Texte plus loin}
{Remplis le tableau avec la longueur de Chaine}
lea edi,Table {ebx Pointe la table des sauts}
mov ah,al {AH = AL = Longueur de Chaine}
mov ecx,128 {taille de table des sauts / 2 (écrit des words)}
rep stosw {remplis avec longueur de Chaine, ecx=0 en fin de bcle}
{Place dans la table(Car) la distance entre Car et fin de Chaine -1}
xor ah,ah
mov ecx,eax {ecx = Longueur Chaine-1}
dec ecx
push ecx {on a besoin de longueur(Chaine)-1 plus loin}
lea ebx,Table {ebx = @Table des sauts, esi pointe encore début de Chaine}
@Remplis:
lodsb {Récupère un car de Chaine}
mov [ebx+eax],cl {Met la distance à sauter}
loop @Remplis
lodsb {ecx=0 : idem pour dernier caractère}
mov [ebx+eax],cl
{Initialise pointeurs pour recherche}
std {comparaisons à partir de la fin}
dec edx {edx = Length(Texte)-1}
pop eax {Récupère longueur(Chaine)-1 = longueur du premier saut}
pop esi {esi pointe Texte, ebx pointe encore Table de sauts}
@SautSuivant:
sub edx,eax {Texte épuisé ?}
jc @Inconnue {oui, pas de correspondance}
add esi,eax {Avance pointeur du nbre de car à sauter}
mov al,[esi] {Récup car pointé}
mov al,[ebx+eax] {et récup nbre de car à sauter dans table sauts}
or al,al {Si 0, peut-être correspondance : compare chaines}
jne @SautSuivant
{Occurence possible, compare les chaines}
mov eax,esi {Sauve Pointeur dans Texte}
dec esi {saute le caractère comparé (indirectement via table)}
mov edi,Chaine {Pointe chaine à rechercher}
mov cl,[edi] {et ecx = longueur à comparer}
dec ecx {dernier car déjà testé}
add edi,ecx {edi pointe avant dernier car de Chaine}
repe cmpsb {compare à rebrousse-poil}
je @Corresp {Egales : correspondance trouvée !}
mov esi,eax {Sinon récupère pointeur dans Texte}
mov eax,1 {Sautera 1 seul caractère}
jmp @SautSuivant
@Corresp:
mov eax,esi {Récup position dans Texte}
sub eax,Texte {Ôte adresse de début de Texte+2}
inc eax
cld
jmp @Fin
@Inconnue:
xor eax,eax {Pas d'occurence, retourne 0}
@Fin:
pop ebx
pop esi
pop edi
End; |