Novembre 2024 | Lun | Mar | Mer | Jeu | Ven | Sam | Dim |
---|
| | | | 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 | | Calendrier |
|
|
| Pic et Poc, les joyeux drilles | |
|
+5papydall Jicehel Klaus Nardo26 JL35 9 participants | |
Auteur | Message |
---|
Nardo26
Nombre de messages : 2294 Age : 56 Localisation : Valence Date d'inscription : 02/07/2010
| Sujet: Re: Pic et Poc, les joyeux drilles Mar 16 Oct 2012 - 5:36 | |
| Bravo Klaus ! Pas eu le temps de chercher plus... (j'apprend à programmer sous android) Mais l'essentiel c'est d'y être parvenu : ...Depuis le temps que l'on cherchait ces fameuses adresses de tableaux ! | |
| | | jean_debord
Nombre de messages : 1266 Age : 70 Localisation : Limoges Date d'inscription : 21/09/2008
| Sujet: Re: Pic et Poc, les joyeux drilles Mar 16 Oct 2012 - 9:35 | |
| Merci pour cette nouvelle fonction Klaus. A titre d'exercice, j'essaie d'en faire une version en FreeBASIC.
J'espère aussi que le nouveau Panoramic permettra un accès plus simple ! | |
| | | Klaus
Nombre de messages : 12331 Age : 75 Localisation : Ile de France Date d'inscription : 29/12/2009
| Sujet: Re: Pic et Poc, les joyeux drilles Mar 16 Oct 2012 - 11:11 | |
| Je suis en train de tester ces fonctions avec des programmes Panoramic plus complexes. Et là, surprise ! Si l'on ajoute une procédure, même simple, avec AU MOINS UN PARAMETRE, cela ne marche plus ! Les données des tableaux ne sont plus encodées au même endroit, c'est-a-dire juste après la table de symboles. Autre chose s'y intercale jusqu'à la fin de la section de mémoire accessible, et je ne trouve plus les données des tableaux.
Je vais donc faire des recherches pour éclaircir cela. En attendant, cela marche tout de même avec des procédures sans paramètres. Mais ce n'est pas satisfaisant. | |
| | | Nardo26
Nombre de messages : 2294 Age : 56 Localisation : Valence Date d'inscription : 02/07/2010
| Sujet: Re: Pic et Poc, les joyeux drilles Mar 16 Oct 2012 - 16:16 | |
| Bonjour à tous ! @Klaus: Est-ce que l'on peut convenir d'une adresse de base concernant la structure de définition des variables? C'est plus simple par la suite de définir des offsets, quelque soit le type de variable... D'après ce que j'ai vu, il n'y a rien avant le pointeur sur la chaine de caractères qui contient le nom de la variable. En partant de ce principe, j'ai écrit une procédure qui permet de retrouver une variable à partir son nom. La différence par rapport à la fonction VARIABLE() c'est qu'elle renvoie l'adresse de base de la structure. - Code:
-
DIM MonTableau%(12)
VarExists("MonTableau%") IF VarExists_return%<>0 PRINT "Variable trouvée !" : PRINT "Adresse de base : ";HEX$(VarExists_return%) AfficheStruct(VarExists_return%) END_IF
END
' ----------------------------------------------------------------- ' Permet de tester l'existence d'une variable par son nom ' retour: adresse de la structure de définition sinon renvoie 0 ' ----------------------------------------------------------------- SUB VarExists(t$) IF VARIABLE("VarExists_return%")=0 THEN DIM VarExists_return% VarExists_return%=ADR(NUMBER_3D_OBJECTS)-24 t$=UPPER$(t$) REPEAT VarExists_return%=VarExists_return%+80 GetName(VarExists_return%) UNTIL GetName_return$=t$ OR GetName_return$="" IF GetName_return$="" THEN VarExists_return%=0:EXIT_SUB END_SUB
' ------------------------------------------------------------------------------ ' Renvoie la valeur de l'entier (32 bits) situé à l'adresse ad% ' ------------------------------------------------------------------------------ SUB LPEEK(ad%) IF VARIABLE("LPEEK_return%")=0 THEN DIM LPEEK_return% DIM_LOCAL Value%,i%,Value$,c% Value% = 0 FOR i%=0 TO 3 c%=PEEK(ad%+i%) IF c%<16 : Value$="0"+HEX$(c%)+Value$ ELSE:Value$=HEX$(c%)+Value$:END_IF NEXT i% LPEEK_return% = HEX(Value$) END_SUB
' ----------------------------------------------------------------- ' Récupère le contenu d'une chaine Delphi ' ----------------------------------------------------------------- SUB GetName(Ad%) DIM_LOCAL pStart%,pName%,lStr% DIM_LOCAL ch$,i% IF VARIABLE("GetName_return$")=0 THEN DIM GetName_return$ GetName_return$="" LPEEK(Ad%):pName%=LPEEK_return% IF pName%<>0 LPEEK(pName%-4):lStr%=LPEEK_return% FOR i%=0 TO lStr%-1 GetName_return$=GetName_return$+CHR$(PEEK(pName%+i%)) NEXT i% END_IF END_SUB
' ============================================================================== ' ============================================================================== ' Procédures pour la démo ' ============================================================================== SUB AfficheStruct(Ad%) DUMP(Ad%) DUMP(Ad%+16) DUMP(Ad%+32) DUMP(Ad%+48) DUMP(Ad%+64) END_SUB
' ------------------------------------------------------------------------------ ' Affiche le dump des 16 octets qui se trouvent à l'adresse ad% ' ------------------------------------------------------------------------------ SUB DUMP(Ad%) DIM_LOCAL i%,v%,a$,b$ a$="":b$="" FOR i%=0 TO 15 v%=PEEK(Ad%+i%) IF v%<16 : a$=a$+"0"+HEX$(v%)+" " ELSE:a$=a$+HEX$(v%)+" ":END_IF if MOD(i%+1,4)=0 THEN a$=a$+" " if v%>31:b$=b$+chr$(v%) ELSE:b$=b$+".":END_IF NEXT i% PRINT HEX$(Ad%)+" :"+a$+" "+b$ END_SUB | |
| | | Klaus
Nombre de messages : 12331 Age : 75 Localisation : Ile de France Date d'inscription : 29/12/2009
| Sujet: Re: Pic et Poc, les joyeux drilles Mar 16 Oct 2012 - 16:39 | |
| @Nardo26: Effectivement, tu retrouves ainsi le descripteur de la variable dont tu as passé le nom. Il faut encode tester le type de variable. C'est - -8 par rapport à adr("variable"). pour un tableau d'entiers, ce mot de 32 bits doit contenir 4. Et cela ne donne pas du tout accès aux données du tableau qui ne sont pas stockées dans le descripteur.
| |
| | | Klaus
Nombre de messages : 12331 Age : 75 Localisation : Ile de France Date d'inscription : 29/12/2009
| Sujet: Re: Pic et Poc, les joyeux drilles Mar 16 Oct 2012 - 16:51 | |
| J'ai corrigé un petit bug dans FindArrayAddress, et KGF.dll passe donc à 1.75 16/10/2012 correction d'un bug dans FindArrayAddress
La routine publiée ci-dessus sur cette page a été remplacée.
J'ai affiné mes recherches sur les procédures en lien avec cette fonction. En réalité, c'est un problème lié au volume du source. J'arrive dans certains cas à ajouter plusieurs procédures, même avec paramètres, sans qu'il y ait un problème. Puis, on arrive à une limite, et l'organisation interne de la mémoire change sans que je voie comment, pour l'instant. Il en est de même avec les variables: j'arrive à créer 38 variables sans problème, et la 39ème provoque un changement radical dans l'organisation de la mémoire APRES la table des variables qui, elle, garde sa structure connue.
La table des variables se compose comme suit: 1. une entête de 4 mots de 32 bits. Le premier mot est 0, de deuxième mot contient la longueur de la table en octets, additionnée de 14, le 3ème contient 1, et le 4ème contient le nombre de variables dans la table. 2. Ensuite, il y a une case de 20 mots de 32 bits où tout est à zéro 3. Puis les cases pour toutes les variables système 4. Enfin, les cases pour toutes les variables application
Le deuxième mot contient dont (1+nombre de variables système+nombre de variables application)*80+14. Cela, additionné à l'adresse du début de l'entête, pointe au-delà de la table des variables, endroit où je commence à chercher les données des tableaux.
Or, lorsque le code source devient trop grand, ou lorsqu'il y a trop de variables application, les informations qui suivent la table des variables changent et un n'y trouve plus les valeurs tableaux.
Dernière édition par Klaus le Mar 16 Oct 2012 - 17:22, édité 1 fois | |
| | | Nardo26
Nombre de messages : 2294 Age : 56 Localisation : Valence Date d'inscription : 02/07/2010
| Sujet: Re: Pic et Poc, les joyeux drilles Mar 16 Oct 2012 - 17:04 | |
| - Klaus a écrit:
- @Nardo26:
Effectivement, tu retrouves ainsi le descripteur de la variable dont tu as passé le nom. Il faut encode tester le type de variable. C'est - -8 par rapport à adr("variable"). pour un tableau d'entiers, ce mot de 32 bits doit contenir 4. Et cela ne donne pas du tout accès aux données du tableau qui ne sont pas stockées dans le descripteur.
Tout à fait Klaus : Dans l'exemple ci-dessus, je ne cherche pas trouver les valeurs d'un tableau, mais à retourner l'adresse de "base" du descripteur... J'aurais très bien pu faire dans la demo un VarExists(chaine$) La procédure VarExists est d'ordre plus général (elle fonctionne quelque soit le type de la donnée)... sinon je l'aurai appelé AdrTab() L'idée c'est d'éviter d'écrire ceci : - Code:
-
DIM variableBidon%,MonTableau%(124) DLL_CALLx("Fonction",ADR(VariableBidon%)+80,....
Pour écrire plutôt ceci : - Code:
-
VarExists("MonTableau%") DLL_CALLx("Fonction",VarExist_return%,....
... en attendant les fonctions.... | |
| | | Klaus
Nombre de messages : 12331 Age : 75 Localisation : Ile de France Date d'inscription : 29/12/2009
| Sujet: Re: Pic et Poc, les joyeux drilles Mer 17 Oct 2012 - 19:40 | |
| J'ai trouvé la solution pour retrouver mes infos dans tous les cas de figure ! Il n'y a plus qu'à assembler les morceaux du puzzle. Ce sera pour bientôt ! | |
| | | Jack Admin
Nombre de messages : 2394 Date d'inscription : 28/05/2007
| Sujet: Re: Pic et Poc, les joyeux drilles Mer 17 Oct 2012 - 20:16 | |
| Discussion intéressante. Il faudra qu'un jour j'étende ADR aux éléments de tableau. | |
| | | Klaus
Nombre de messages : 12331 Age : 75 Localisation : Ile de France Date d'inscription : 29/12/2009
| Sujet: Re: Pic et Poc, les joyeux drilles Mer 17 Oct 2012 - 20:55 | |
| Ah, ce serait une super-nouvelle ! Un truc genre - Code:
-
dim test%(200), a% a% = ADR_ARRAY(test%) serait formidable. En attendant, j'ai trouvé comment identifier la section mémoire contenant les données des tableaux d'entiers et de flottants, même dans les cas qui me posaient problème jusqu'à aujourd'hui. Ce sera mis en ligne rapidement, probablement cette nuit ou demain. Ouverture vers les fonctions statistiques et financières de Delphi, vers la gestion plus puissante des API de Windows - les applications sont multiples. | |
| | | Yannick
Nombre de messages : 8635 Age : 53 Localisation : Bretagne Date d'inscription : 15/02/2010
| Sujet: re Mer 17 Oct 2012 - 21:42 | |
| @ Klaus, Ce domaine dépasse de loin mes compétences et je suis admiratif devant vos connaissances mais je suis d'un oeil l'évolution de ce post, peut être que dans quelques années... Je me demande ce que tu entends par l'utilisation de l' API ( juste par curiosité personnelle, pour ne pas finir idiot... ) @ Jack, Je ne sais pas si on dévie de l'utilisation prévue initialement pour Panoramic mais vois tu ce que devient ton beau bébé ? Pas mal, non ? Entre les nouvelles commandes et les apports des dll's des plus costauds en la matière, on arrive quasiment à faire tout ( mais pas n'importe quoi... ) avec lui. Je dirai que Panoramic devient adolescent . | |
| | | Klaus
Nombre de messages : 12331 Age : 75 Localisation : Ile de France Date d'inscription : 29/12/2009
| Sujet: Re: Pic et Poc, les joyeux drilles Mer 17 Oct 2012 - 22:06 | |
| @Ygeronimi: Les API, ce sont simplement des routines placées dans des DLLs. Généralement, on perle d'API quand il s'agit des routines du système Windows, fournies par MicroSoft, comme dans User32.dll etc. Cela permet d'agir sur le système, d'obtenir des informations intéressantes etc. Maintenant, API signifie Application Programming Interface voici le lien vers la page de Wikipedia. Et il y en a d'autres que ceux de MicroSoft. Il y a ceux de Google, Ceux de PayPal, les miens (eh oui, KGF.dll contient des API...). API, ce n'est rien qu'un mot "savant" pour dire "routines de service". | |
| | | Jicehel
Nombre de messages : 5947 Age : 52 Localisation : 77500 Date d'inscription : 18/04/2011
| Sujet: Re: Pic et Poc, les joyeux drilles Mer 17 Oct 2012 - 22:09 | |
| Klaus, je pense que Jack pensait plutôt étendre la fonction existante que d'en créer une nouvelle Du genre: dim test%(200), a% a% = ADR(test%(0)) Enfin, il me semble, mais bon on verra bien, ne demandons rien pendant quelques temps que Jack ait le temps de rajouter ce dont il a envie pour faire évoluer un peu Panoramic comme il l'imagine. En tout cas, c'est du beau boulot et j'ai hâte de voir ce que tu vas encore imaginer comme application | |
| | | Klaus
Nombre de messages : 12331 Age : 75 Localisation : Ile de France Date d'inscription : 29/12/2009
| Sujet: Re: Pic et Poc, les joyeux drilles Mer 17 Oct 2012 - 22:31 | |
| @Tous: J'ai réussi. On peut maintenant trouver les données des tableaux d'entiers ET de flottants, quelque soit la taille du programme. En effet, je me suis heurté à un changement de configuration de mémoire dès que le nombre de variables dépassait une certaine limite (38 pour être précis) ou dès que le source devenait trop grand (grosso modo plus de 2000 lignes). Alors qu'en-dessous de ces limites, les données SUIVENT la table des variables dans le champs d'adressage de la mémoire virtuelle, il n'en est plus de même dès qu'une de ces limites est dépassée. La table des variables est alors déplacée bien au-delà de l'endroit où sont placées les données ! Et ma recherche à partir de la table des variables échouait fatalement. J'ai dû recourir à collecter l'ensemble des sections de mémoire virtuelle (uniquement celles SANS l'attribut READ_ONLY), et chercher alors mes données à partir de l'adresse virtuelle 0 si je ne les trouve pas au-delà de la table des variables. Et encore: ceci n'est valable que pour les tableaux flottants. Car l'identifiant que je cherche pour les tableaux d'entiers existe bien dans tous les cas au-delà de la table des variables, mais malheureusement, il est utilisée à plusieurs reprises pour des fins différents, et seule la première occurrence est la bonne. Pour les tableaux d'entiers, donc, il faut toujours chercher à partir de l'adresse 0. Bon, assez de technique. Tout cela est traité dans la DLL, de façon transparente pour le programme Panoramic. On peut appeler la fonction FindArrayAddress de la DLL directement, ou utiliser la procédure FindArrayAddress de KGF_SUB qui a été étendu pour gérer cette fonction. Et il y a un ajout au programme de démo de KGF_SUB pour montrer l'exemple. Dans ce programme de démo, je crée les tableaux au début, et je leur charge des valeurs. Puis, dès le début, je vais chercher leur adresses et le les mémorise dans des variables. Il y a un petit délai, dû à la recherche dans tout l'espace d'adressage (voir ci-dessus). Mais après, les adresses ne changeront plus, et c'est pour cela que je les détermine au démarrage du programme, et plus tard, je n'utilise plus que les variables dans lesquelles je les ai mémorisées. La DLL est passée à la version 1.76 17/10/2012 ajout fonction FindValueInVirtualMemoryCette fonction, bien qu'accessible par Panoramic, n'est pas documentée et n'a pas beaucoup d'intérêt en soi. Elle est appelée directement par la fonction FindArrayAddress, à l'intérieur même de la DLL. KGF_SUB a été modifié, et il y a un nouveau programme de démo: demo_KGF_SUB avec FindArrayAddress.bas Donc, télé-chargez ces 3 modules: demo_KGF_SUB avec FindArrayAddress.bas KGF_SUB.bas KGF.dll ainsi que la doc KGF.chm Et, pour les amateurs de Delphi, voici comment j'ai fait: - Code:
-
Type TMBIArray = array of TMemoryBasicInformation;
// retourner toutes les régions de mémoire virtuelle du processus actuel function GetRegionList(a: integer) : TMBIArray; var p1, p2 : pointer; mbi : TMemoryBasicInformation; i1 : integer; begin SetLength(result, 200); // préallocation pour gain de temps i1 := 0; // p1 := nil; // commencer au début de la mémoire virtuelle p1 := pointer(a); p2 := nil; while VirtualQuery(p1, mbi, sizeOf(mbi)) = sizeOf(mbi) do begin // retourner les sections de mémoire if (mbi.State = MEM_COMMIT) and // si la section est allouée (mbi.AllocationBase <> p2) and // et si l'adresse de base est différente de la précédente (mbi.AllocationBase = mbi.BaseAddress) then begin // et si l'adresse est la bonne if i1 = Length(result) then SetLength(result, i1+100); // augmenter l'allocation si nécessaire result[i1] := mbi; // mémoriser tout le bloc d'information dans une case du tableau inc(i1); // et compter cet élément end; p2 := mbi.AllocationBase; // mémoriser l'adresse de base dword(p1) := dword(p1) + mbi.RegionSize; // et pointer un mot au-delà de la région traitée end; SetLength(result, i1); // allocation définitive si préallocation trop grande end;
// Cette fonction parcourt la mémoire virtuelle à partir d'une adresse de base et cherche une valeur spécifique. function FindValueInVirtualMemory(a, v1,v2: integer):integer; stdcall; export; var MBI: TMBIArray; i,j: integer; s: string; pi,pf: integer; begin MBI := GetRegionList(a); // retourner la liste de toutes les régions de mémoire virtuelle du process for i:=0 to high(MBI) do begin if MBI[i].Protect<>PAGE_READONLY then begin pi := integer(MBI[i].BaseAddress); pf := pi + integer(MBI[i].RegionSize-4); while pi<pf do begin if (pinteger(pi)^=v1) or (pinteger(pi)^=v2) then begin result := pi; exit; end; pi := pi + 4; end; end; end; result := 0; end;
// ******************************************************************************************
// Cette fonction retourne l'adresse de l'élément 0 d'un tableau à 1 dimension dont la déclaration // suit celle de la variable dont l'adresse est passée en paramètre. { Une case le la table de symboles des variables Panoramic a la structure suivante: Longueur: 20 integer soit 80 octets La première colonne donne l'offset par rapport au début du descripteur La seconde colonne donne l'offset par rapport à adr(x) 0 -12 adresse du string contenant le nom (terminé par NUL) 4 -8 type de variable 1=int 2=str 3=flo +3=tableau 1 dim +4=tableu 2 dim 8 -4 adr(x) 12 0 donnée si type 1 (integer) 16 4 adresse du string terminé par NUL si type 2 (string) 20 8 24 12 1er mot de données sur 2 mots de 32 bits si type 3 (flottant) 28 16 2ème mot de données sur 2 mots de 32 bits si type 3 (flottant) 32 20 offset premier élément dans partie 818 tableau entier 1 dimension (multiple de 4) 36 24 40 28 offset premier élément dans partie 1622 tableau flottant 1 dimension (multiple de 8) 44 32 48 36 52 40 56 44 nombre d'éléments de première dimension si type=4 ou 7 (integer) 60 48 nombre d'éléments de première dimension si type=5 ou 8 (string) 64 52 nombre d'éléments de première dimension si type=6 ou 9 (flottant) 68 56 nombre d'éléments de seconde dimension si type=7 (integer) 72 60 nombre d'éléments de seconde dimension si type=8 (string) 76 64 nombre d'éléments de seconde dimension si type=9 (flottant) La table de symboles a la structure suivante: entête 4 mots de 32 bits 0 0 (poids fort de la longueur de la table ?) 4 longueur de la table = nombre de variables * 80 + 14 8 1 12 nombre de variables (y copris la case vide) vide 1 case vide de 20 mots de 32 bits système liste de cases des variables système, chacune de 20 mots de 32 bits application liste de cases des variables application, chacune de 20 mots de 32 bits } function FindArrayAddress(adr:pinteger; nom:pstring):integer; stdcall; export; var name, temp: string; ptr: pinteger; off, typ, p: integer; begin result := 0; // supposer "erreur" name := UpperCase(nom^); typ := 6; // supposer "flottant" (ni % ni $) if RightStr(name,1)='%' then typ := 4; if RightStr(name,1)='$' then typ := 5; ptr := adr; inc(ptr,-3); // pointer sur l'adresse du nom temp := pstring(ptr)^; // prendre le nom de la variable while temp<>name do begin // chercher la variable demandée inc(ptr,20); // passer à la variable suivante if ptr^=0 then exit; // fin de table ? non trouvé ! temp := pstring(ptr)^; // prendre le nom de la variable suivante end; inc(ptr); // pointer sur le type de variable if ptr^<>typ then exit; // pas du type array du nom de la variable ? non trouvé ! case typ of 4: begin inc(ptr,7); // pointer sur le offset off := ptr^; // et le mémoriser inc(ptr,12); // dépasser ce descripteur end; 5: begin end; 6: begin inc(ptr,9); // pointer sur le offset off := ptr^; // et le mémoriser inc(ptr,10); // dépasser ce descripteur end; end; case typ of 4: begin while (ptr^<>0) do inc(ptr,20); // 80 octets: pointer au début du descripteur suivant p := FindValueInVirtualMemory(150000000, 818,819); if p=0 then p := FindValueInVirtualMemory(0, 818,819); ptr := pinteger(p); inc(ptr,3+off); // 12+off*4: adresse de l'élément (0) end; 6: begin while (ptr^<>0) do inc(ptr,20); // 80 octets: pointer au début du descripteur suivant p := FindValueInVirtualMemory(integer(ptr), 1622, 1622); if p=0 then p := FindValueInVirtualMemory(150000000, 1622, 1622); if p=0 then p := FindValueInVirtualMemory(0, 1622, 1622); ptr := pinteger(p); inc(ptr,3+off*2); // 12+off*4*2: adresse de l'élément (0) end end; result := integer(ptr); end;
@JeanDebord: Voilà, la voie est libre pour les fonctions de statistiques ! | |
| | | Klaus
Nombre de messages : 12331 Age : 75 Localisation : Ile de France Date d'inscription : 29/12/2009
| Sujet: Re: Pic et Poc, les joyeux drilles Mer 17 Oct 2012 - 22:34 | |
| @Jicehel Tu donnes comme exemple: - Code:
-
dim test%(200), a% a% = ADR(test%(0)) Malheureusement, tu obtiens avec cela l'adresse du résultat de l'expression arithmétique test%(0) qui se trouvera à un endroit tout à fait différent des données du tableau ! Il faudrait faire comme ceci: - Code:
-
dim test%(200), a% a% = ADR(test%()) mais le compilateur ne permet pas cette syntaxe pour le moment. C'est pourquoi je proposais un nouveau mot-clé, dans la logique des HANDLE, HANDLE_CANVAS et HANDLE_FORM. Cela me semble correspondre à l'esprit de Panoramic. | |
| | | Jicehel
Nombre de messages : 5947 Age : 52 Localisation : 77500 Date d'inscription : 18/04/2011
| Sujet: Re: Pic et Poc, les joyeux drilles Mer 17 Oct 2012 - 22:55 | |
| Ah ok, ça me dépasse un peu je pense ... On verra bien à ce moment là | |
| | | Nardo26
Nombre de messages : 2294 Age : 56 Localisation : Valence Date d'inscription : 02/07/2010
| Sujet: Re: Pic et Poc, les joyeux drilles Jeu 18 Oct 2012 - 1:20 | |
| Super Klaus ! Que penses tu de ma proposition ? cela éviterai de déclarer une variable bidon% pour trouver l'adresse d'un tableau... On pourrait s'appuyer sur une variable connue (comme une variable système par ex.) pour faire la recherche du tableau... PS : Merci pour le source Delphi, je me pencherai dessus dès que je trouverai le temps de le faire... | |
| | | jean_debord
Nombre de messages : 1266 Age : 70 Localisation : Limoges Date d'inscription : 21/09/2008
| Sujet: Re: Pic et Poc, les joyeux drilles Jeu 18 Oct 2012 - 11:21 | |
| - Klaus a écrit:
@JeanDebord: Voilà, la voie est libre pour les fonctions de statistiques !
Merci Klaus. J'ai récupéré le code de la dernière fonction. Il est un peu trop complexe pour pouvoir être transposé en FreeBASIC mais ce n'est pas un problème car j'ai déjà toute une bibliothèque mathématique en Delphi ( http://sourceforge.net/projects/dmath/). | |
| | | Klaus
Nombre de messages : 12331 Age : 75 Localisation : Ile de France Date d'inscription : 29/12/2009
| Sujet: Re: Pic et Poc, les joyeux drilles Jeu 18 Oct 2012 - 11:24 | |
| Ton idée avec une variable système est bonne, et je l'ai retenue. Conséquence: KGF.dll passe à la version 1.77 18/10/2012 FindArrayAddress utilise l'adresse d'un flottant en premier paramètreIl y a une nouvelle fonction: - Code:
-
SymbolTableStartAddress% = DLL_call1("FindSymbolTableStartAddress",adr(NUMBER_CLICK))
Cette fonction donne l'adresse du début de la table des variables de Panoramic. On lui passe l'adresse d'une variable flottante, de préférence une variable système de type flottant comme NUMBER_CLICK. Et c'est cette valeur qui sera désormais passé comme premier paramètre à la fonction FindArrayAddress pour retrouver les données des tableaux de type entier ou flottant. Si l'on utilise KGF_SUB, cela est transparent. Tout est géré de façon automatique dans les procédures. La procédure enveloppant FindArrayAddress n'a plus qu'un seul paramètre: le nom du tableau dont il faut trouver les données. Et si l'on n'a pas appelé FindSymbolTableStartAddress au prélable, la procédure FindArrayAddress le fait de façon automatique et récupère l'adresse de base de la table des variables, de façon tranparente pour le programmeur. "KGF_SUB.bas" et "demo_KGF_SUB avec FindArrayAddress.bas" ainsi que la doc ont été mis à jour. Et voici la dernière version des fonctions Delphi qui sont à la base de cela: - Code:
-
Type TMBIArray = array of TMemoryBasicInformation;
// retourner toutes les régions de mémoire virtuelle du processus actuel function GetRegionList(a: integer) : TMBIArray; var p1, p2 : pointer; mbi : TMemoryBasicInformation; i1 : integer; begin SetLength(result, 200); // préallocation pour gain de temps i1 := 0; // p1 := nil; // commencer au début de la mémoire virtuelle p1 := pointer(a); p2 := nil; while VirtualQuery(p1, mbi, sizeOf(mbi)) = sizeOf(mbi) do begin // retourner les sections de mémoire if (mbi.State = MEM_COMMIT) and // si la section est allouée (mbi.AllocationBase <> p2) and // et si l'adresse de base est différente de la précédente (mbi.AllocationBase = mbi.BaseAddress) then begin // et si l'adresse est la bonne if i1 = Length(result) then SetLength(result, i1+100); // augmenter l'allocation si nécessaire result[i1] := mbi; // mémoriser tout le bloc d'information dans une case du tableau inc(i1); // et compter cet élément end; p2 := mbi.AllocationBase; // mémoriser l'adresse de base dword(p1) := dword(p1) + mbi.RegionSize; // et pointer un mot au-delà de la région traitée end; SetLength(result, i1); // allocation définitive si préallocation trop grande end; { mbi.STATE: (MEM_COMMIT, MEM_RESERVE, MEM_FREE, MEM_PRIVATE, MEM_MAPPED, MEM_IMAGE) mbi.PROTECT: (PAGE_READONLY, PAGE_READWRITE, PAGE_NOACCESS, PAGE_WRITECOPY, PAGE_EXECUTE, PAGE_EXECUTE_READ, PAGE_EXECUTE_READWRITE, PAGE_EXECUTE_WRITECOPY, PAGE_GUARD, PAGE_NOCACHE) }
function TestGetRegionList(v: integer):integer; stdcall; export; var MBI: TMBIArray; i,j: integer; s,f: string; pi,pf: integer; begin MBI := GetRegionList(0); // retourner la liste de toutes les régions de mémoire virtuelle du process for i:=0 to high(MBI) do begin if MBI[i].Protect<>PAGE_READONLY then begin case MBI[i].Protect of PAGE_READONLY: s := 'PAGE_READONLY'; PAGE_READWRITE: s := 'PAGE_READWRITE'; PAGE_NOACCESS: s := 'PAGE_NOACCESS'; PAGE_WRITECOPY: s := 'PAGE_WRITECOPY'; PAGE_EXECUTE: s := 'PAGE_EXECUTE'; PAGE_EXECUTE_READ: s := 'PAGE_EXECUTE_READ'; PAGE_EXECUTE_READWRITE: s := 'PAGE_EXECUTE_READWRITE'; PAGE_EXECUTE_WRITECOPY: s := 'PAGE_EXECUTE_WRITECOPY'; PAGE_GUARD: s := 'PAGE_GUARD'; PAGE_NOCACHE: s := 'PAGE_NOCACHE'; end; pi := integer(MBI[i].BaseAddress); pf := pi + integer(MBI[i].RegionSize-4);
f := 'rien'; while pi<pf do begin if pinteger(pi)^=v then begin f := 'trouvé'; pi := pf; end; pi := pi + 4; end; showmessage(inttostr(integer(MBI[i].BaseAddress))+': '+inttostr(MBI[i].RegionSize)+' '+f); end; end; result := 0; end;
// Cette fonction parcourt la mémoire virtuelle à partir d'une adresse de base // et cherche une valeur spécifique. // le paramètre prot indique le type de protection des pages dans lesquelles chercher, // ou zéro pour chercher dans toutes les pages. // le paramètre a donne l'adresse virtuelle de départ de la recherche. // les paramètres V1 et V2 donnent deux valeurs dont la premire trouvée termine la recherche. // La fonction retourne l'adresse virtuelle trouvée, ou zéro si rien n'est trouvé. function FindValueInVirtualMemory(prot, a, v1,v2: integer):integer; stdcall; export; var MBI: TMBIArray; i,j: integer; s: string; pi,pf: integer; begin MBI := GetRegionList(a); // retourner la liste de toutes les régions de mémoire virtuelle du process for i:=0 to high(MBI) do begin if (prot=0) or (MBI[i].Protect=prot) then begin pi := integer(MBI[i].BaseAddress); pf := pi + integer(MBI[i].RegionSize-4); while pi<pf do begin if (pinteger(pi)^=v1) or (pinteger(pi)^=v2) then begin result := pi; exit; end; pi := pi + 4; end; end; end; result := 0; end;
// Cette fonction retourne l'adresse du début de la table des variables de Panoramic. // Elle doit être appelée avec l'adresse d'une variable système en format flottant, // comme NUMBER_CLICK par exemple. function FindSymbolTableStartAddress(a_number_click: pinteger):integer; stdcall; export; var name, temp: string; ptr: pinteger; off, typ, p: integer; begin result := 0; // supposer "erreur" ptr := a_number_click; inc(ptr,-6); // pointer sur l'adresse du nom de NUMBER_CLICK if pstring(ptr)^='NUMBER_CLICK' then begin while ptr^<>0 do inc(ptr,-20); inc(ptr,20); result := integer(ptr); end; end;
// Cette fonction retourne l'adresse de l'élément 0 d'un tableau à 1 dimension dont la déclaration // suit celle de la variable dont l'adresse est passée en paramètre. Cette variable DOIT être une // variable flottante, de préférence une variable système comme NUMBER_CLICK. { Une case le la table de symboles des variables Panoramic a la structure suivante: Longueur: 20 integer soit 80 octets La première colonne donne l'offset par rapport au début du descripteur La seconde colonne donne l'offset par rapport à adr(x%) 0 -12 adresse du string contenant le nom (terminé par NUL) 4 -8 type de variable 1=int 2=str 3=flo +3=tableau 1 dim +4=tableu 2 dim 8 -4 adr(x%) 12 0 donnée si type 1 (integer) 16 4 adresse du string terminé par NUL si type 2 (string) 20 8 adr(x) 24 12 1er mot de données sur 2 mots de 32 bits si type 3 (flottant) 28 16 2ème mot de données sur 2 mots de 32 bits si type 3 (flottant) 32 20 offset premier élément dans partie 818 tableau entier 1 dimension (multiple de 4) 36 24 40 28 offset premier élément dans partie 1622 tableau flottant 1 dimension (multiple de 8) 44 32 48 36 52 40 56 44 nombre d'éléments de première dimension si type=4 ou 7 (integer) 60 48 nombre d'éléments de première dimension si type=5 ou 8 (string) 64 52 nombre d'éléments de première dimension si type=6 ou 9 (flottant) 68 56 nombre d'éléments de seconde dimension si type=7 (integer) 72 60 nombre d'éléments de seconde dimension si type=8 (string) 76 64 nombre d'éléments de seconde dimension si type=9 (flottant) La table de symboles a la structure suivante: entête 4 mots de 32 bits 0 0 (poids fort de la longueur de la table ?) 4 longueur de la table = nombre de variables * 80 + 14 8 1 12 nombre de variables (y copris la case vide) vide 1 case vide de 20 mots de 32 bits système liste de cases des variables système, chacune de 20 mots de 32 bits application liste de cases des variables application, chacune de 20 mots de 32 bits } function FindArrayAddress(adr_base:pinteger; nom:pstring):integer; stdcall; export; var name, temp: string; ptr: pinteger; off, typ, p: integer; begin result := 0; // supposer "erreur" name := UpperCase(nom^); typ := 6; // supposer "flottant" (ni % ni $) if RightStr(name,1)='%' then typ := 4; if RightStr(name,1)='$' then typ := 5; ptr := adr_base; // prendre l'adresse de la table de symboles temp := pstring(ptr)^; // prendre le nom de la variable while temp<>name do begin // chercher la variable demandée inc(ptr,20); // passer à la variable suivante if ptr^=0 then exit; // fin de table ? non trouvé ! temp := pstring(ptr)^; // prendre le nom de la variable suivante end; inc(ptr); // pointer sur le type de variable if ptr^<>typ then exit; // pas du type array du nom de la variable ? non trouvé ! case typ of 4: begin inc(ptr,7); // pointer sur le offset off := ptr^; // et le mémoriser inc(ptr,12); // dépasser ce descripteur end; 5: begin end; 6: begin inc(ptr,9); // pointer sur le offset off := ptr^; // et le mémoriser inc(ptr,10); // dépasser ce descripteur end; end; case typ of 4: begin while (ptr^<>0) do inc(ptr,20); // 80 octets: pointer au début du descripteur suivant // while (ptr^<>818) and (ptr^<>819) do inc(ptr); // chercher en mémoire p := FindValueInVirtualMemory(PAGE_READWRITE, 150000000, 818,819); if p=0 then p := FindValueInVirtualMemory(PAGE_READWRITE, 0, 818,819); ptr := pinteger(p); inc(ptr,3+off); // 12+off*4: adresse de l'élément (0) end; 6: begin while (ptr^<>0) do inc(ptr,20); // 80 octets: pointer au début du descripteur suivant p := FindValueInVirtualMemory(PAGE_READWRITE, integer(ptr), 1622, 1622); if p=0 then p := FindValueInVirtualMemory(PAGE_READWRITE, 150000000, 1622, 1622); if p=0 then p := FindValueInVirtualMemory(PAGE_READWRITE, 0, 1622, 1622); ptr := pinteger(p); inc(ptr,3+off*2); // 12+off*4*2: adresse de l'élément (0) end end; result := integer(ptr); end;
// Cette fonction retourne l'adresse de l'élément 0 d'un tableau à 1 dimension dont la déclaration // suit immédiatement celle de la variable dont l'adresse est passée en paramètre. function ArrayAddress(adr: pinteger):integer; stdcall; export; var ptr: pinteger; off: integer; begin ptr := adr; inc(ptr,20+5); // 80+20 octets: pointe sur la case "offset" du descripteur suivant off := ptr^; // offset des données dans la zone réservée aux tableaux ptr := adr; inc(ptr,-3+20); // -12+80 octets: pointe sur le début du descripteur suivant: while (ptr^<>818) and (ptr^<>819) do inc(ptr,20); // 80 octets: pointer au début du descripteur suivant inc(ptr,3+off); // 12+off*4: adresse de l'élément (0) result := integer(ptr); end;
J'aime bien ce ping-pong des idées - cela permet vraiment d'avancer vers quelque chose d'abouti. | |
| | | Klaus
Nombre de messages : 12331 Age : 75 Localisation : Ile de France Date d'inscription : 29/12/2009
| Sujet: Re: Pic et Poc, les joyeux drilles Jeu 18 Oct 2012 - 11:25 | |
| @jean_debord: Re-télé-charge à nouveau - je viens de tout mettre à jour en fonction de mon dernier post ! | |
| | | Klaus
Nombre de messages : 12331 Age : 75 Localisation : Ile de France Date d'inscription : 29/12/2009
| Sujet: Re: Pic et Poc, les joyeux drilles Jeu 18 Oct 2012 - 15:47 | |
| J'ai malheureusement une mauvaise nouvelle.
En cours d'exécution du programme, l'allocation de mémoire change dynamiquement, et même des parties de la table des variables, de même que les emplacements des données des tableaux sont régulièrement déplacés. Donc, mes adresses qui étaient valables en début de programme ne le sont plus du tout en coure de programme, et elles évoluent même au cours de l'exécution.
Je suis donc à la recherche d'un moyen plus fiable de localiser les données. Ah, si l'on avait ADR_ARRAY... | |
| | | JL35
Nombre de messages : 7112 Localisation : 77 Date d'inscription : 29/11/2007
| Sujet: Re: Pic et Poc, les joyeux drilles Jeu 18 Oct 2012 - 16:10 | |
| C'est bien ce qu'il me semblait avoir constaté, que la mémoire évolue constamment et que les éléments changent de place pendant le déroulement du programme... ce qui m'a fait lever le pied sur l'exploration mémoire, je ne m'y retrouvais plus. | |
| | | Nardo26
Nombre de messages : 2294 Age : 56 Localisation : Valence Date d'inscription : 02/07/2010
| Sujet: Re: Pic et Poc, les joyeux drilles Jeu 18 Oct 2012 - 18:42 | |
| On tourne en rond... (tassage des données ) Depuis que Jack fait un free en sortie de sub...les données sont fatalement déplacées lors du malloc suivant Mais on va pas lui reprocher hein?... Par contre les variables globales déclarées en début ne doivent pas bouger... | |
| | | Jack Admin
Nombre de messages : 2394 Date d'inscription : 28/05/2007
| Sujet: Re: Pic et Poc, les joyeux drilles Jeu 18 Oct 2012 - 18:57 | |
| - Citation :
- En cours d'exécution du programme, l'allocation de mémoire change dynamiquement, et même des parties de la table des variables, de même que les emplacements des données des tableaux sont régulièrement déplacés. Donc, mes adresses qui étaient valables en début de programme ne le sont plus du tout en cours de programme, et elles évoluent même au cours de l'exécution.
- Citation :
- Depuis que Jack fait un free en sortie de sub...les données sont fatalement déplacées lors du malloc suivant
Tout à fait. Il y a des déplacements de données en cours d'exécution... Concernant l'adresse d'un élément de tableau, c'est compliqué pour la déterminer, mais depuis qu'il y a la fonction PEEK(), ce n'est pas infaisable. C'est pourquoi, dans un premier temps, je ne l'ai pas codé dans la fonction ADR(). Je le coderai un jour, quand je ne saurai plus quoi faire pendant les week-end pluvieux. Bref, vous l'aurez compris, ce n'est pas dans mes priorités. Je considère que le programmeur du dimanche n'en a pas besoin dans son quotidien. Je pense que l'accès direct à l'imprimante, par exemple, est plus prioritaire. | |
| | | Klaus
Nombre de messages : 12331 Age : 75 Localisation : Ile de France Date d'inscription : 29/12/2009
| Sujet: Re: Pic et Poc, les joyeux drilles Jeu 18 Oct 2012 - 19:12 | |
| Parfaitement compris, Jack.
Je continue de mon côté, et j'ai réussi, dans tous les cas de figure, avec les tableaux d'entiers. Même si la mémoire évolue entre-temps. mais j'ai encore un problème avec le tableaux des flottants. Je travaille dessus.
Ceci dit, puis-je faire une suggestion ? Si l'on utilise un élément d'un tableau dans une expression, Panoramic retrouve bien l'adresse, puis la valeur à partir de là ! Si tu considères de faire, non pas une extension de la fonction ADR(), mais une fonction ADR_ARRAY() à laquelle on passerait le nom du tableau et qui retournerait systématiquement l'adresse de l'élément 0 du tableau, tout comme l'evaluation de l'expression tableau(0) a dû le faire. Pas d'interaction avec l'existant de cette façon, et cohérant dans la philosophie avec J=HANDLE(), HANDLE_CANVAS() et HANDLE_FORM(). | |
| | | Contenu sponsorisé
| Sujet: Re: Pic et Poc, les joyeux drilles | |
| |
| | | | Pic et Poc, les joyeux drilles | |
|
Sujets similaires | |
|
| Permission de ce forum: | Vous ne pouvez pas répondre aux sujets dans ce forum
| |
| |
| |