IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

x86 32-bits / 64-bits Assembleur Discussion :

[VC++/ASM] Allocation dynamique de mémoire ?


Sujet :

x86 32-bits / 64-bits Assembleur

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Profil pro
    Ingénieur R&D
    Inscrit en
    Juillet 2002
    Messages
    81
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur R&D
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2002
    Messages : 81
    Par défaut [VC++/ASM] Allocation dynamique de mémoire ?
    Bonjour,

    Dans le cadre d'un jeu réalisé par des amis, j'ai réalisé une petite DLL de cryptage/decryptage de fichiers en C++ sous VC++. Pour en optimiser les performances, j'ai convertit la partie la plus critique de l'agorithme en assembleur, avec un gain de temps impressionnant. Cependant j'aimerais maintenant convertir le reste du code en assembleur sous MASM32 (en fait c'est surtout que mes amis me demandent une DLL aussi petite que possible).

    Et là où je bloque, c'est sur la façon de réaliser les allocations dynamiques de mémoire. J'y ai passé plusieurs jours sans y parvenir.

    J'ai tenté d'utiliser HeapAlloc et VirutalAlloc sans grand succès. Au premier appel de la fonction, tout fonctionne parfaitement, mais dès le second appel, le programme plante avec une erreur de violation d'accès. A des fins de tests, j'ai alors fait une fonction inutile qui se contente d'appeler HeapAlloc, d'écrire dans le premier octet du buffer ainsi alloué, puis de libérer le buffer avec HeapFree. Je me suis retrouvé avec le même problème, à savoir que le premier appel fonctionnait, mais pas les suivants. Pourtant, HeapAlloc ne me retourne pas d'erreur.

    Je précise que je ne suis pas encore passé sous MASM32.

    Ma question est donc dans un premier temps: quelle est la façon correcte de faire une allocation dynamique de mémoire en assembleur ?

    Si par la suite je n'y arrive toujours pas, je posterai le code de la fonction.

    En vous remerciant par avance pour vos réponses.

  2. #2
    Rédacteur
    Avatar de Neitsa
    Homme Profil pro
    Chercheur sécurité informatique
    Inscrit en
    Octobre 2003
    Messages
    1 041
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Chercheur sécurité informatique

    Informations forums :
    Inscription : Octobre 2003
    Messages : 1 041
    Par défaut
    Hello,

    Si vous passez par VirtualAlloc, vérifiez bien que votre mapping et en Read_write si jamais vous essayez d'y écrire :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    	invoke VirtualAlloc,NULL,SizeBuffer,MEM_COMMIT,PAGE_READWRITE
    Sinon pour le fond du problème je ve vois pas trop...surement un problème dans votre code. Un petit copier/coller serait peut être utile.

    Cordialement, Neitsa.

  3. #3
    Membre confirmé
    Profil pro
    Ingénieur R&D
    Inscrit en
    Juillet 2002
    Messages
    81
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur R&D
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2002
    Messages : 81
    Par défaut
    Merci beaucoup pour votre réponse.

    En fait, comme je suis encore sous VC++ et pas encore passé à MASM32, j'appelle les fonctions de cette façon:

    Pour allouer la mémoire:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    		push PAGE_READWRITE
    		push MEM_RESERVE | MEM_COMMIT
    		push FSize
    		push NULL
    		call dword ptr VirtualAlloc
    		mov Buffer, eax
    Pour libérer la mémoire:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    		push MEM_RELEASE
    		push FSize
    		push Buffer
    		call dword ptr VirtualFree
    Mes variables sont déclarées façon C:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    	char *Buffer;
    	int FSize;
    Voilà, une fonction ne contenant que ces éléments plante si j'essaie de mettre quelques chose dans le Buffer lors d'un deuxième appel, mais fonctionne lors du premier appel.

    D'ailleurs, voici comment je procède pour accéder au Buffer ainsi obtenu:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    		mov edi, Buffer
    		mov [edi], al
    Ensuite j'incrémente edi pour accéder au reste du buffer. Mais même sans l'incrémenter, au deuxième appel, ça plante.

  4. #4
    Rédacteur
    Avatar de Neitsa
    Homme Profil pro
    Chercheur sécurité informatique
    Inscrit en
    Octobre 2003
    Messages
    1 041
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Chercheur sécurité informatique

    Informations forums :
    Inscription : Octobre 2003
    Messages : 1 041
    Par défaut
    Hello,

    je suis étonné que même le premier appel puisse fonctionner:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
          push PAGE_READWRITE
          push MEM_RESERVE | MEM_COMMIT ; impossible !
          push FSize
          push NULL
          call dword ptr VirtualAlloc
          mov Buffer, eax
    les paramètres RESERVE et COMMIT sont incompatibles entre eux.

    RESERVE, comme son nom l'indique ne fait que réserver un bloc mémoire sans l'allouer, de ce fait le bloc ne pourra être pris par une autre fonction ou une réallocation de mémoire.

    COMMIT alloue un bloc (de ce fait il est réservé) en mémoire, ainsi on peut alors s'en servir, le bloc reserver ne servant à rien en tant que tel.

    c'est bien préciser dans la MSDN

    flAllocationType
    [in] Type of memory allocation. This parameter must contain one of the following values.
    A part ce détail je ne vois pas ce qui cloche, le bout de code me semble correct...

    Si vous avez d'autres problèmes n'hésitez pas. Sinon il reste toujours l'option du débugging de l'application.(au cas où je peux toujours vous aider).

    Cordialement, Neitsa.

  5. #5
    Membre confirmé
    Profil pro
    Ingénieur R&D
    Inscrit en
    Juillet 2002
    Messages
    81
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur R&D
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2002
    Messages : 81
    Par défaut
    Et bien, je pensais qu'il fallait réserver la mémoire avant de l'allouer. Alors si on utilise MEM_COMMIT, la mémoire est réservée et allouée ? Ou faut-il faire deux appels ?

    EDIT: J'ai été plus sage, j'ai vérifié que MEM_COMMIT seul marchait.

    Voici donc mon code actuel:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    		push PAGE_READWRITE
    		push MEM_COMMIT
    		push FSize
    		push NULL
    		call dword ptr VirtualAlloc
    		mov Buffer, eax
     
    		mov edi, Buffer
    		mov al, [edi]
     
    		push MEM_RELEASE
    		push NULL
    		push Buffer
    		call dword ptr VirtualFree
    Je précise que c'est juste ma fonction de test. Comme à son habitude, elle fonctionne au premier appel, mais au second appel, j'ai un message de violation d'accès sur "mov al, [edi]".

  6. #6
    Membre expérimenté
    Profil pro
    Inscrit en
    Août 2003
    Messages
    247
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2003
    Messages : 247
    Par défaut
    Pourquoi ne pas utiliser la fonction standard malloc ?

  7. #7
    Rédacteur
    Avatar de Neitsa
    Homme Profil pro
    Chercheur sécurité informatique
    Inscrit en
    Octobre 2003
    Messages
    1 041
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Chercheur sécurité informatique

    Informations forums :
    Inscription : Octobre 2003
    Messages : 1 041
    Par défaut
    Hello,

    Pour le MEM_COMMIT c'est bien ca.

    un petit problème encore

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
          mov edi, Buffer
          mov al, [edi] ; c'est plutôt l'inverse
    on devrais plutôt faire ceci:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
          mov edi, Buffer
          mov byte ptr [edi] ,al
    (avec en plus une indication de format).

  8. #8
    Membre émérite
    Profil pro
    Inscrit en
    Juillet 2002
    Messages
    842
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2002
    Messages : 842
    Par défaut
    Citation Envoyé par Selenite
    Pourquoi ne pas utiliser la fonction standard malloc ?
    Eh bien parce que cette fonction appartient au standard C, et que le but du jeu est de convertir tout en asm.

    Cela dit, il est effectivement dommage de vouloir écrire tout en asm si ce n'est que pour une contrainte de taille. J'en ai pas à vous conseiller, mais vous pourriez plutôt rechercher les compilateurs qui sont capable de produire un obj petit. Ca existe, et ce serait une méthode certainement plus rapide, à moins que vous n'ayez qu'une petite vingtaine de lignes à convertir.


    En ce qui concerne le mov [edi], je ne pense pas qu'il y ait d'erreur. Le programme testait la lecture et non l'écriture, aucun contenu explicite qui justifie l'écriture dans al, bref, ca ne risque pas de changer grand chose.


    Si vous avez une violation d'accès, vous devriez avoir l'adresse qu'on a tenté de lire/écrire. Et si vous êtes sur VC, vous devriez pouvoir vérifier la valeur retournée par VirtualAlloc, que par ailleurs, il faudrait toujours vérifier dans le code. A priori, je ne vois pas ce qui puisse justifier qu'un deuxième appel ne fonctionne pas, si bien entendu, les paramètres d'appel n'ont pas changé. Mais il faut savoir que sous windows, et en particulier quand on commence à faire de l'asm, une erreur à l'opposée du code qui plante dans le programme peut créer ce genre d'erreur.


    Enfin, notez, qu'il nétait pas indispensable d'utiliser VirtualAlloc. Vous pouviez très bien utiliser la fonction plus générale GlobalAlloc, qui permet de se préoccuper de moins de détails, mais enfin, ca ne résoud pas le problème.


    Donc, puisqu'on est pas très doués apparement, donnez nous un peu plus d'informations sur la violation d'accès.



    Amicalement, Blustuff.

Discussions similaires

  1. Allocation dynamique et mémoire virutelle
    Par mambo dans le forum Visual C++
    Réponses: 1
    Dernier message: 31/05/2007, 09h46
  2. probleme d'allocation dynamique de mémoire
    Par Blo0d4x3 dans le forum C
    Réponses: 2
    Dernier message: 13/03/2007, 07h53
  3. Allocation dynamique de mémoire : Limitations ?
    Par rulianf dans le forum C++
    Réponses: 5
    Dernier message: 22/03/2006, 17h03
  4. Allocation dynamique de mémoire
    Par cd090580 dans le forum Autres éditeurs
    Réponses: 7
    Dernier message: 12/11/2005, 11h17
  5. Allocation dynamique de mémoire en asm
    Par narmataru dans le forum Assembleur
    Réponses: 7
    Dernier message: 17/12/2002, 22h31

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo