FORUM DE DISCUSSION SUR LE LANGAGE PANORAMIC

Développement d'applications avec le langage Panoramic
 
AccueilAccueil  FAQFAQ  RechercherRechercher  S'enregistrerS'enregistrer  MembresMembres  GroupesGroupes  Connexion  
Derniers sujets
» Palette (une de plus): 16, 48 ou 216 couleurs
par mindstorm Hier à 21:55

» La roue de la fortune
par Jean Claude Hier à 21:23

» Modifier le son d'une vidéo
par Jean Claude Hier à 21:10

» SimpleEditor
par Klaus Hier à 20:02

» KGF_dll - nouvelles versions
par Klaus Hier à 18:21

» Synedit_Editor - nouvelles versions
par Klaus Hier à 12:25

» Gestionnaire de Projets Panoramic
par Laurent (Minibug) Lun 24 Avr 2017 - 23:23

» Un nouveau
par jjn4 Lun 24 Avr 2017 - 20:32

» PANO-LIKE : Une copie de Panoramic Editeur
par Laurent (Minibug) Dim 23 Avr 2017 - 18:42

» Un compteur de lignes de code source
par Klaus Sam 22 Avr 2017 - 21:55

» Rechercher une chaîne de caractère dans un fichier.
par papydall Sam 22 Avr 2017 - 13:45

» Problème avec la fonction IsolateWordsFromString.
par Klaus Sam 22 Avr 2017 - 10:42

» Recherche Hardware MIDI
par Yannick Ven 21 Avr 2017 - 21:08

» Panoramic Editor
par Yannick Jeu 20 Avr 2017 - 23:18

» Problème avec la fonction ReplaceStringInString.
par Pedro Alvarez Jeu 20 Avr 2017 - 17:29

Navigation
 Portail
 Index
 Membres
 Profil
 FAQ
 Rechercher
Rechercher
 
 

Résultats par :
 
Rechercher Recherche avancée
Avril 2017
LunMarMerJeuVenSamDim
     12
3456789
10111213141516
17181920212223
24252627282930
CalendrierCalendrier

Partagez | 
 

 Pic et Poc, les joyeux drilles

Voir le sujet précédent Voir le sujet suivant Aller en bas 
Aller à la page : Précédent  1, 2, 3, 4  Suivant
AuteurMessage
Nardo26

avatar

Nombre de messages : 2294
Age : 48
Localisation : Valence
Date d'inscription : 02/07/2010

MessageSujet: Re: Pic et Poc, les joyeux drilles   Mar 16 Oct 2012 - 6: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 !
Very Happy
Revenir en haut Aller en bas
Voir le profil de l'utilisateur http://nardo26.lescigales.org
jean_debord

avatar

Nombre de messages : 704
Age : 62
Localisation : Limoges
Date d'inscription : 21/09/2008

MessageSujet: Re: Pic et Poc, les joyeux drilles   Mar 16 Oct 2012 - 10: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 !
Revenir en haut Aller en bas
Voir le profil de l'utilisateur http://www.unilim.fr/pages_perso/jean.debord/index.htm
Klaus

avatar

Nombre de messages : 9821
Age : 67
Localisation : Ile de France
Date d'inscription : 29/12/2009

MessageSujet: Re: Pic et Poc, les joyeux drilles   Mar 16 Oct 2012 - 12: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.
Revenir en haut Aller en bas
Voir le profil de l'utilisateur http://klauspanoramic.comxa.com/index.html En ligne
Nardo26

avatar

Nombre de messages : 2294
Age : 48
Localisation : Valence
Date d'inscription : 02/07/2010

MessageSujet: Re: Pic et Poc, les joyeux drilles   Mar 16 Oct 2012 - 17:16

Bonjour à tous ! Smile

@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
Revenir en haut Aller en bas
Voir le profil de l'utilisateur http://nardo26.lescigales.org
Klaus

avatar

Nombre de messages : 9821
Age : 67
Localisation : Ile de France
Date d'inscription : 29/12/2009

MessageSujet: Re: Pic et Poc, les joyeux drilles   Mar 16 Oct 2012 - 17: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.
Revenir en haut Aller en bas
Voir le profil de l'utilisateur http://klauspanoramic.comxa.com/index.html En ligne
Klaus

avatar

Nombre de messages : 9821
Age : 67
Localisation : Ile de France
Date d'inscription : 29/12/2009

MessageSujet: Re: Pic et Poc, les joyeux drilles   Mar 16 Oct 2012 - 17: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 - 18:22, édité 1 fois
Revenir en haut Aller en bas
Voir le profil de l'utilisateur http://klauspanoramic.comxa.com/index.html En ligne
Nardo26

avatar

Nombre de messages : 2294
Age : 48
Localisation : Valence
Date d'inscription : 02/07/2010

MessageSujet: Re: Pic et Poc, les joyeux drilles   Mar 16 Oct 2012 - 18: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() Wink

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.... Wink
Revenir en haut Aller en bas
Voir le profil de l'utilisateur http://nardo26.lescigales.org
Klaus

avatar

Nombre de messages : 9821
Age : 67
Localisation : Ile de France
Date d'inscription : 29/12/2009

MessageSujet: Re: Pic et Poc, les joyeux drilles   Mer 17 Oct 2012 - 20: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 !
Revenir en haut Aller en bas
Voir le profil de l'utilisateur http://klauspanoramic.comxa.com/index.html En ligne
Jack
Admin
avatar

Nombre de messages : 1632
Date d'inscription : 28/05/2007

MessageSujet: Re: Pic et Poc, les joyeux drilles   Mer 17 Oct 2012 - 21:16

Discussion intéressante.
Il faudra qu'un jour j'étende ADR aux éléments de tableau.
Revenir en haut Aller en bas
Voir le profil de l'utilisateur http://panoramic.free-boards.net
Klaus

avatar

Nombre de messages : 9821
Age : 67
Localisation : Ile de France
Date d'inscription : 29/12/2009

MessageSujet: Re: Pic et Poc, les joyeux drilles   Mer 17 Oct 2012 - 21: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.
Revenir en haut Aller en bas
Voir le profil de l'utilisateur http://klauspanoramic.comxa.com/index.html En ligne
Yannick

avatar

Nombre de messages : 7532
Age : 45
Localisation : Bretagne
Date d'inscription : 15/02/2010

MessageSujet: re   Mer 17 Oct 2012 - 22: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... Laughing

Je me demande ce que tu entends par l'utilisation de l' API scratch
( juste par curiosité personnelle, pour ne pas finir idiot... Laughing )

@ 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... Laughing ) avec lui.

Je dirai que Panoramic devient adolescent Laughing .

Revenir en haut Aller en bas
Voir le profil de l'utilisateur
Klaus

avatar

Nombre de messages : 9821
Age : 67
Localisation : Ile de France
Date d'inscription : 29/12/2009

MessageSujet: Re: Pic et Poc, les joyeux drilles   Mer 17 Oct 2012 - 23: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".
Revenir en haut Aller en bas
Voir le profil de l'utilisateur http://klauspanoramic.comxa.com/index.html En ligne
Jicehel

avatar

Nombre de messages : 5816
Age : 44
Localisation : 77500
Date d'inscription : 19/04/2011

MessageSujet: Re: Pic et Poc, les joyeux drilles   Mer 17 Oct 2012 - 23: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 Wink
Revenir en haut Aller en bas
Voir le profil de l'utilisateur
Klaus

avatar

Nombre de messages : 9821
Age : 67
Localisation : Ile de France
Date d'inscription : 29/12/2009

MessageSujet: Re: Pic et Poc, les joyeux drilles   Mer 17 Oct 2012 - 23: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 FindValueInVirtualMemory

Cette 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 !
Revenir en haut Aller en bas
Voir le profil de l'utilisateur http://klauspanoramic.comxa.com/index.html En ligne
Klaus

avatar

Nombre de messages : 9821
Age : 67
Localisation : Ile de France
Date d'inscription : 29/12/2009

MessageSujet: Re: Pic et Poc, les joyeux drilles   Mer 17 Oct 2012 - 23: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.
Revenir en haut Aller en bas
Voir le profil de l'utilisateur http://klauspanoramic.comxa.com/index.html En ligne
Jicehel

avatar

Nombre de messages : 5816
Age : 44
Localisation : 77500
Date d'inscription : 19/04/2011

MessageSujet: Re: Pic et Poc, les joyeux drilles   Mer 17 Oct 2012 - 23:55

Ah ok, ça me dépasse un peu je pense ... On verra bien à ce moment là Wink
Revenir en haut Aller en bas
Voir le profil de l'utilisateur
Nardo26

avatar

Nombre de messages : 2294
Age : 48
Localisation : Valence
Date d'inscription : 02/07/2010

MessageSujet: Re: Pic et Poc, les joyeux drilles   Jeu 18 Oct 2012 - 2:20

Super Klaus !
Que penses tu de ma proposition ?
cela éviterai de déclarer une variable bidon% pour trouver l'adresse d'un tableau... Smile
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... Wink
Revenir en haut Aller en bas
Voir le profil de l'utilisateur http://nardo26.lescigales.org
jean_debord

avatar

Nombre de messages : 704
Age : 62
Localisation : Limoges
Date d'inscription : 21/09/2008

MessageSujet: Re: Pic et Poc, les joyeux drilles   Jeu 18 Oct 2012 - 12: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/).
Revenir en haut Aller en bas
Voir le profil de l'utilisateur http://www.unilim.fr/pages_perso/jean.debord/index.htm
Klaus

avatar

Nombre de messages : 9821
Age : 67
Localisation : Ile de France
Date d'inscription : 29/12/2009

MessageSujet: Re: Pic et Poc, les joyeux drilles   Jeu 18 Oct 2012 - 12: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ètre

Il 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.
Revenir en haut Aller en bas
Voir le profil de l'utilisateur http://klauspanoramic.comxa.com/index.html En ligne
Klaus

avatar

Nombre de messages : 9821
Age : 67
Localisation : Ile de France
Date d'inscription : 29/12/2009

MessageSujet: Re: Pic et Poc, les joyeux drilles   Jeu 18 Oct 2012 - 12:25

@jean_debord:
Re-télé-charge à nouveau - je viens de tout mettre à jour en fonction de mon dernier post !
Revenir en haut Aller en bas
Voir le profil de l'utilisateur http://klauspanoramic.comxa.com/index.html En ligne
Klaus

avatar

Nombre de messages : 9821
Age : 67
Localisation : Ile de France
Date d'inscription : 29/12/2009

MessageSujet: Re: Pic et Poc, les joyeux drilles   Jeu 18 Oct 2012 - 16: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...
Revenir en haut Aller en bas
Voir le profil de l'utilisateur http://klauspanoramic.comxa.com/index.html En ligne
JL35



Nombre de messages : 5859
Localisation : 77
Date d'inscription : 29/11/2007

MessageSujet: Re: Pic et Poc, les joyeux drilles   Jeu 18 Oct 2012 - 17: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.
Revenir en haut Aller en bas
Voir le profil de l'utilisateur
Nardo26

avatar

Nombre de messages : 2294
Age : 48
Localisation : Valence
Date d'inscription : 02/07/2010

MessageSujet: Re: Pic et Poc, les joyeux drilles   Jeu 18 Oct 2012 - 19:42

On tourne en rond... scratch scratch (tassage des données Question )
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?... Smile

Par contre les variables globales déclarées en début ne doivent pas bouger...

Revenir en haut Aller en bas
Voir le profil de l'utilisateur http://nardo26.lescigales.org
Jack
Admin
avatar

Nombre de messages : 1632
Date d'inscription : 28/05/2007

MessageSujet: Re: Pic et Poc, les joyeux drilles   Jeu 18 Oct 2012 - 19: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. Very Happy Very Happy Very Happy

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.
Revenir en haut Aller en bas
Voir le profil de l'utilisateur http://panoramic.free-boards.net
Klaus

avatar

Nombre de messages : 9821
Age : 67
Localisation : Ile de France
Date d'inscription : 29/12/2009

MessageSujet: Re: Pic et Poc, les joyeux drilles   Jeu 18 Oct 2012 - 20: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().
Revenir en haut Aller en bas
Voir le profil de l'utilisateur http://klauspanoramic.comxa.com/index.html En ligne
Contenu sponsorisé




MessageSujet: Re: Pic et Poc, les joyeux drilles   

Revenir en haut Aller en bas
 
Pic et Poc, les joyeux drilles
Voir le sujet précédent Voir le sujet suivant Revenir en haut 
Page 3 sur 4Aller à la page : Précédent  1, 2, 3, 4  Suivant
 Sujets similaires
-
» Pic et Poc, les joyeux drilles
» kit rouge et or joyeux noel pour vous dire bonjour bis beauty
» Joyeux Noel !
» Robin des Bois et ses Joyeux Compagnons
» Joyeux Noël les gens ! <3

Permission de ce forum:Vous ne pouvez pas répondre aux sujets dans ce forum
FORUM DE DISCUSSION SUR LE LANGAGE PANORAMIC :: PANORAMIC 32 bits :: Présentation et bavardage-
Sauter vers: