FindMemoryByte(), FindMemoryUnicode(), et caetera...

Partagez votre expérience de PureBasic avec les autres utilisateurs.
Ollivier
Messages : 4190
Inscription : ven. 29/juin/2007 17:50
Localisation : Encore ?
Contact :

FindMemoryByte(), FindMemoryUnicode(), et caetera...

Message par Ollivier »

Bonjour,

voici 8 fonctions de recherche, respectivement :

Result = FindMemoryByte(*AddresseMemoire, CodeAChercher [ , TailleMaximumDuBufferDeRecherche] )
Result = FindMemoryUnicode( ~ )
Result = FindMemoryLong( ~ )
Result = FindMemoryQuad( ~ ) (x64 uniquement)

cherchent la valeur d'un byte, d'un unicode, d'un long ou d'un quad (x64 uniquement) spécifié (Argument "CodeAChercher"), à partir de l'adresse spécifiée (avec "*AdresseMemoire").

et

Result = FindMemoryNonByte(*AddresseMemoire, CodeAChercher [ , TailleMaximumDuBufferDeRecherche] )
Result = FindMemoryNonUnicode( ~ )
Result = FindMemoryNonLong( ~ )
Result = FindMemoryNonQuad( ~ ) (x64 uniquement)

cherchent une valeur différente du byte, de l'unicode, du long ou du quad (x64 uniquement) spécifié (Argument "CodeAChercher"), à partir de l'adresse spécifiée (avec "*AdresseMemoire").

L'argument "TailleMaximumDuBufferDeRecherche" est facultatif, ce qui rend cette fonction plutôt sportive*, si on ne la précise pas.
L'unité de la taille de recherche dépend directement de la fonction utilisée.

En octets pour Find...Byte()
En mots pour Find...Unicode()
En double-mots pour Find...Long()
En quadruple-mots pour Find...Quad()

Chaque fonction retourne :

Zéro (0) si la recherche n'a pas abouti

ou bien

L'adresse mémoire du premier code trouvé par la fonction.

Code : Tout sélectionner

;******************************************************************************************************************************************
;{ FindMemory Lib }

Macro _FindUnit_(UnitFunction, UnitSymbol, UnitSize, UnitSize_, StopConditionSymbol, NonStopConditionSymbol, RegisterPrefix)
        Procedure FindMemory#UnitFunction(*ResearchStart, WantedValue, MaximumQuantityToBeScanned = -1)
                                
                ! mov                           RegisterPrefix#ax,      [p.v_WantedValue]
                ! mov                           RegisterPrefix#cx,      [p.v_MaximumQuantityToBeScanned]
                ! mov                           RegisterPrefix#di,      [p.p_ResearchStart]
                ! xor                           RegisterPrefix#bx,      RegisterPrefix#bx
                ! shr                           RegisterPrefix#cx,      UnitSize_
                
                ! rep#StopConditionSymbol                               scas#UnitSymbol
                ! lea                           RegisterPrefix#di,      [RegisterPrefix#di - UnitSize]
                ! lea                           RegisterPrefix#ax,      [RegisterPrefix#bx]
                ! cmov#NonStopConditionSymbol   RegisterPrefix#ax,      RegisterPrefix#di
                ProcedureReturn
                
        EndProcedure
EndMacro

Macro _FindMemory_(UnitName, UnitSymbol, UnitSize, UnitSize_)
        CompilerIf #PB_Compiler_Processor = #PB_Processor_x86
                CompilerIf UnitSize < 8
                        _FindUnit_(UnitName, UnitSymbol, UnitSize, UnitSize_, ne, e, e)
                        _FindUnit_(Non#UnitName, UnitSymbol, UnitSize, UnitSize_, e, ne, e)
                CompilerEndIf
        CompilerElseIf #PB_Compiler_Processor = #PB_Processor_x64
                _FindUnit_(UnitName, UnitSymbol, UnitSize, UnitSize_, ne, e, r)
                _FindUnit_(Non#UnitName, UnitSymbol, UnitSize, UnitSize_, e, ne, r)
        CompilerEndIf
EndMacro

_FindMemory_(Byte, b, 1, 0)
_FindMemory_(Unicode, w, 2, 1)
_FindMemory_(Long, d, 4, 2)
_FindMemory_(Quad, q, 8, 3)

;}

(*) Attention aux accès mémoire invalide si la taille maximum de recherche n'est pas précisée.
Ollivier
Messages : 4190
Inscription : ven. 29/juin/2007 17:50
Localisation : Encore ?
Contact :

Re: FindMemoryByte(), FindMemoryUnicode(), et caetera...

Message par Ollivier »

Exemple:

Ici, il y a 3 caractères à scanner avant d'atteindre la cible 0. Mais vous pouvez mettre le paquet (un truc léger, un gigaoctets par exemple), ça reste très rapide.

Code : Tout sélectionner

DataSection
Ici:
Data.A 65,33,48,0
EndDataSection

Debug "Adresse de départ :"
Debug ?Ici
Debug "Adresse du caractère 0:"
Debug FindMemoryByte(?Ici, 0)
Avatar de l’utilisateur
Kwai chang caine
Messages : 6962
Inscription : sam. 23/sept./2006 18:32
Localisation : Isere

Re: FindMemoryByte(), FindMemoryUnicode(), et caetera...

Message par Kwai chang caine »

Ca marche, merci pour le partage 8)
ImageLe bonheur est une route...
Pas une destination

PureBasic Forum Officiel - Site PureBasic
Ollivier
Messages : 4190
Inscription : ven. 29/juin/2007 17:50
Localisation : Encore ?
Contact :

Re: FindMemoryByte(), FindMemoryUnicode(), et caetera...

Message par Ollivier »

Je me permets d'apporter une précision technique.

Au sein de la ligne ASM :

Code : Tout sélectionner

 ! repCC scasU
... Il se produit une quantité non négligeable d'instructions internes au CPU.

Grâce à ce site : http://www.felixcloutier.com/x86/SCAS:S ... SCASD.html, voici un pseudo-code de ce qu'il s'y passe (Il y a quatre sous-parties, c'est selon la taille de l'unité de comparaison, 8bits, 16bits, 32bits ou 64bits, que l'une de ces quatre sous-parties s'exécute x fois. La 1ère sous-partie existe depuis les années 80) :

Code : Tout sélectionner

IF (Byte cmparison)
    THEN
         temp ← AL − SRC;
         SetStatusFlags(temp);
              THEN IF DF = 0
                    THEN (R|E)DI ← (R|E)DI + 1;
                    ELSE (R|E)DI ← (R|E)DI – 1; FI;
    ELSE IF (Word comparison)
         THEN
              temp ← AX − SRC;
              SetStatusFlags(temp);
              IF DF = 0
                    THEN (R|E)DI ← (R|E)DI + 2;
                    ELSE (R|E)DI ← (R|E)DI – 2; FI;
         FI;
    ELSE IF (Doubleword comparison)
         THEN
              temp ← EAX – SRC;
              SetStatusFlags(temp);
              IF DF = 0
                    THEN (R|E)DI ← (R|E)DI + 4;
                    ELSE (R|E)DI ← (R|E)DI – 4; FI;
         FI;
    ELSE IF (Quadword comparison using REX.W )
         THEN
              temp ← RAX − SRC;
              SetStatusFlags(temp);
              IF DF = 0
                    THEN (R|E)DI ← (R|E)DI + 8;
                    ELSE (R|E)DI ← (R|E)DI – 8;
              FI;
    FI;
F
Répondre