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 :

[MASM32] Comment utiliser la fonction printf


Sujet :

x86 32-bits / 64-bits Assembleur

  1. #1
    Membre régulier
    Profil pro
    Inscrit en
    Juin 2007
    Messages
    217
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2007
    Messages : 217
    Points : 105
    Points
    105
    Par défaut [MASM32] Comment utiliser la fonction printf
    Bonjours à tous!
    Il y a certains points que je ne comprend pas au niveau de l'inclusion de librairies et de fonctions :

    Comment permettre l'utilisation d'une fonction C, comme par exemple printf dans un programme assembleur 32 bits?
    Je sais qu'il faut l'appeler : "call _printf", et je connait les conventions d'appel, mais comment indiquer au compilateur qu'il s'agit d'une fonction externe? Faut-il rajouter "extern _printf" dans le segment de code, ou bien inclure un prototype au début du fichier : "_printf proto ???"?

    Ensuite, comment me procurer le fichier .lib qui contient la fonction précompilée? J'ai regardé dans le dossier lib de mon compilateur C, il n'y a pas de fichier "stdio.lib".

    Ensuite, comment montrer au linker dans quel fichier il doit rechercher la fonction précompilée?


    Ensuite, j'ai essayé d'utiliser les fonctions que propose masm, le compilateur que j'utilise.
    Le programme suivant, qui doit afficher une chaîne sur la console, ne fait strictement rien!
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
     
    .486
    .model flat, stdcall
    option casemap:none
     
    include \masm32\include\windows.inc
    include \masm32\include\kernel32.inc
    includelib \masm32\lib\kernel32.lib
    include \masm32\m32lib\masm32.inc
    includelib \masm32\m32lib\masm32.lib
     
    .data 
    Message   db "Message à afficher.",0 
     
    .code
    start:
        invoke StdOut, addr Message
     
        invoke ExitProcess, 0
    end start
    Aidez-moi, s'il vous plais, je suis désespéré!!!

  2. #2
    Membre habitué
    Avatar de Stormy_Ordos
    Profil pro
    Expert sécurité informatique
    Inscrit en
    Mars 2005
    Messages
    91
    Détails du profil
    Informations personnelles :
    Localisation : Canada

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

    Informations forums :
    Inscription : Mars 2005
    Messages : 91
    Points : 166
    Points
    166
    Par défaut
    Bonjour,

    Pourquoi vouloir absolument utiliser Printf pour écrire du texte? tu peux utiliser les fonctions standard du SDK Windows (WriteConsoleW et WriteConsoleA si mes souvenirs sont corrects). Tu peux downloader le SDK gratuitement (incroyable ) et aller faire un tour du côté de MSDN (Microsoft Developer's Network) pour trouver les prototypes. Ces fonctions s'utilisent sans problèmes avec Kernel32.lib et User32.lib.

    Dans la vie, il y a 10 sortes de personnes. Ceux qui comprennent le binaire et les autres...


  3. #3
    Membre régulier
    Profil pro
    Inscrit en
    Juin 2007
    Messages
    217
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2007
    Messages : 217
    Points : 105
    Points
    105
    Par défaut
    Tout à fait d'accord, il est possible d'utiliser les fonctions de l'API Windows, mais c'est aussi utile de savoir comment exploiter les fonctions C à partir d'assembleur et vice-versa.
    En plus, il faut bien dire qu'il n'y a pas et il n'y aura jamais plus pratique que printf en matière de sortie de texte.

    Sinon, au passage, une petite question : pourquoi en assembleur on dispose des fonctions WriteConsoleA, WriteConsoleW, MessageBoxA, MessageBoxW, ... alors qu'en C par exemple on peut utiliser les fonctions WriteConsole, MessageBox, ... sans spécifier quel format de chaine on utilise?

  4. #4
    Membre habitué
    Avatar de Stormy_Ordos
    Profil pro
    Expert sécurité informatique
    Inscrit en
    Mars 2005
    Messages
    91
    Détails du profil
    Informations personnelles :
    Localisation : Canada

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

    Informations forums :
    Inscription : Mars 2005
    Messages : 91
    Points : 166
    Points
    166
    Par défaut
    Probablement parce que les bibliothèques C utilisent des macros texte qui font pointer un terme plus générique comme WriteConsole soit vers WriteConsoleA (pour Win9x) soit vers WriteConsoleW (systèmes NT). Je pense que c'est une question de simplicité.

    il n'y aura jamais plus pratique que printf en matière de sortie de texte
    Faut voir, Write/Writeln est très sympa aussi .

    Dans la vie, il y a 10 sortes de personnes. Ceux qui comprennent le binaire et les autres...


  5. #5
    Membre habitué
    Avatar de Stormy_Ordos
    Profil pro
    Expert sécurité informatique
    Inscrit en
    Mars 2005
    Messages
    91
    Détails du profil
    Informations personnelles :
    Localisation : Canada

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

    Informations forums :
    Inscription : Mars 2005
    Messages : 91
    Points : 166
    Points
    166
    Par défaut
    J'ai fait une recherche Google, juste pour voir (toujours penser à google avant de poster), et j'ai trouvé juste ce que tu cherchais :
    Utiliser PROTO et INVOKE pour appeler printf à partir de MASM

    Dans la vie, il y a 10 sortes de personnes. Ceux qui comprennent le binaire et les autres...


  6. #6
    Membre régulier
    Profil pro
    Inscrit en
    Juin 2007
    Messages
    217
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2007
    Messages : 217
    Points : 105
    Points
    105
    Par défaut
    Moi aussi, j'avais fait une recherche, mais j'avais rien trouvé.
    Enfin bref, j'ai ajouté le prototype de printf dans mon programme, et j'ai essayer de compiler.
    Mais là, ça va pas du tous, parce que pour utiliser les prototypes avec VARARG, il faut utiliser les conventions d'appel C, or pour utiliser l'API Windows, il faut utiliser les conventions Pascal ("stdcall" après la directive ".model").
    En gros, on ne peut pas utiliser en même temps une fonctions C avec invoke (qui requière un prototype) et une fonction de l'API. Donc, à moins qu'on puisse changer au beau milieu du programme les conventions d'appel, il faut se résoudre à utiliser call avec les fonctions C.

    Sinon, j'ai parcouru un peu les fichiers d'en-tête C des fonctions de l'API Windows (windows.h, winuser.h, ...) et j'ai remarqué qu'à chaque début de prototype, il y a le mot WINAPI. Ce serais pas ce qui permet au compilateur C de savoir qu'il faut utiser les conventions d'appel Pascal lors de l'appel de ces fonctions?

  7. #7
    Membre confirmé Avatar de dapounet
    Profil pro
    Étudiant
    Inscrit en
    Juillet 2007
    Messages
    469
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juillet 2007
    Messages : 469
    Points : 567
    Points
    567
    Par défaut
    Lis la partie de ce tutorial sur les sous-programmes, c'est assez complet.
    :wq

  8. #8
    Membre régulier
    Profil pro
    Inscrit en
    Juin 2007
    Messages
    217
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2007
    Messages : 217
    Points : 105
    Points
    105
    Par défaut
    Il se trouve que j'ai déjà ce tutorial, et il n'est pas vraiment assez complet puisqu'il n'explique pas comment utiliser autre chose que les macros fournis avec.

    J'ai recherché dans les header-files et j'ai trouvé que CALLBACK tout comme WINAPI ne servent qu'à informer le compilateur de la convention d'appel utilisé : stdcall.

  9. #9
    Membre habitué
    Avatar de Stormy_Ordos
    Profil pro
    Expert sécurité informatique
    Inscrit en
    Mars 2005
    Messages
    91
    Détails du profil
    Informations personnelles :
    Localisation : Canada

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

    Informations forums :
    Inscription : Mars 2005
    Messages : 91
    Points : 166
    Points
    166
    Par défaut
    En gros, on ne peut pas utiliser en même temps une fonction C avec invoke (qui requiert un prototype) et une fonction de l'API. Donc, à moins qu'on puisse changer au beau milieu du programme les conventions d'appel, il faut se résoudre à utiliser call avec les fonctions C.
    Essaie de ne pas déclarer de conventions d'appel au départ (à propos, STDCALL est la convention d'appel Win32, pas Pascal) et de déclarer tes prototypes avec EXTERN.
    PROTO utilise automatiquement la convention d'appel déclarée, mais je ne suis pas sûr pour EXTERN.
    Puis, tu empiles tes arguments dans l'ordre inverse et enfin CALL.

    Dans la vie, il y a 10 sortes de personnes. Ceux qui comprennent le binaire et les autres...


  10. #10
    Membre confirmé Avatar de dapounet
    Profil pro
    Étudiant
    Inscrit en
    Juillet 2007
    Messages
    469
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juillet 2007
    Messages : 469
    Points : 567
    Points
    567
    Par défaut
    Citation Envoyé par _Michel
    Il se trouve que j'ai déjà ce tutorial, et il n'est pas vraiment assez complet puisqu'il n'explique pas comment utiliser autre chose que les macros fournis avec.
    Pourtant au 4.7 il explique tout ce qu'il te faut, les registres à préserver, l'ordre d'empilement des paramètres etc. à part qu'il utilise NASM donc la syntaxe doit changer.
    :wq

  11. #11
    Membre habitué
    Avatar de Stormy_Ordos
    Profil pro
    Expert sécurité informatique
    Inscrit en
    Mars 2005
    Messages
    91
    Détails du profil
    Informations personnelles :
    Localisation : Canada

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

    Informations forums :
    Inscription : Mars 2005
    Messages : 91
    Points : 166
    Points
    166

    Dans la vie, il y a 10 sortes de personnes. Ceux qui comprennent le binaire et les autres...


  12. #12
    Membre régulier
    Profil pro
    Inscrit en
    Juin 2007
    Messages
    217
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2007
    Messages : 217
    Points : 105
    Points
    105
    Par défaut
    Merci pour les conventions d'appel, je crois que je comprend mieux.
    Maintenant, j'ai réussi à compiler un fichier obj à partir de ce code source :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
     
    .486
    .model flat, stdcall
    option casemap:none
     
    include \masm32\include\windows.inc
    include \masm32\include\kernel32.inc
    includelib \masm32\lib\kernel32.lib
     
    _printf    PROTO C arg1:Ptr Byte, printlist: VARARG
     
    .data 
    Message   db "Message à afficher.",0 
     
    .code
    start:
        invoke _printf, addr Message
        invoke ExitProcess, 0
    end start
    Mais pour en faire un executable, je ne sais pas avec quoi linker.

    J'ai essayer de l'associer avec un fichier obj contenant le code suivant (en C) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    #include <stdio.h>
     
    void AffichageMessage (char *ptr)
    {
    	printf ("%s", ptr);
    }
    et en remplacant bien entendu la fonction printf par la fonction AffichageMessage dans le fichier assembleur.

    Voila ce que me donne ilink32 (linker de bcc55):
    "Turbo Incremental Link 5.00 Copyright (c) 1997, 2000 Borland
    Error: 'C:\ASM\CPUID\CPUID2.OBJ' contains invalid OMF record, type 0x4c (possibly COFF)"

    Et voila ce que me donne link (linker de masm32) :
    "Microsoft (R) Incremental Linker Version 5.12.8078
    Copyright (C) Microsoft Corp 1992-1998. All rights reserved.

    affichage.obj : warning LNK4033: converting object format from OMF to COFF
    LINK : fatal error LNK1221: a subsystem can't be inferred and must be defined"

    Apparement, ils n'aiment pas top les .obj des autres compilateurs, mais c'est pourtant un format standard, non?

  13. #13
    Membre habitué
    Avatar de Stormy_Ordos
    Profil pro
    Expert sécurité informatique
    Inscrit en
    Mars 2005
    Messages
    91
    Détails du profil
    Informations personnelles :
    Localisation : Canada

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

    Informations forums :
    Inscription : Mars 2005
    Messages : 91
    Points : 166
    Points
    166
    Par défaut
    Je pense que tu devrais exporter ta fonction AfficheMessage en C de manière à pouvoir la récupérer dans ton prog assembleur (avec EXTERN). Tu ne déclares pas Printf du coup, et AfficheMessage fait office de wrapper (je ne sais pas si c'est très orthodoxe, mais bon).
    C'est la seule solution si tu veux utiliser printf comme ça, sachant que tu n'as pas de bibliothèque de fonctions C...

    Dans la vie, il y a 10 sortes de personnes. Ceux qui comprennent le binaire et les autres...


  14. #14
    Membre régulier
    Profil pro
    Inscrit en
    Juin 2007
    Messages
    217
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2007
    Messages : 217
    Points : 105
    Points
    105
    Par défaut
    Exporter printf... c'est ce que j'ai fait, non?

    voila le module assembleur maintenant :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
     
    .486
    .model flat, stdcall
    option casemap:none
     
    include \masm32\include\windows.inc
    include \masm32\include\kernel32.inc
    includelib \masm32\lib\kernel32.lib
     
    _AffichageMessage    PROTO C arg1:Ptr Byte
     
    .data 
    Message   db "Message à afficher.",0 
     
    .code
    start:
        invoke _AffichageMessage, addr Message
        invoke ExitProcess, 0
    end start
    mais pourtant il n'arrive pas à le lier au module C.

  15. #15
    Membre habitué
    Avatar de Stormy_Ordos
    Profil pro
    Expert sécurité informatique
    Inscrit en
    Mars 2005
    Messages
    91
    Détails du profil
    Informations personnelles :
    Localisation : Canada

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

    Informations forums :
    Inscription : Mars 2005
    Messages : 91
    Points : 166
    Points
    166
    Par défaut
    Edit : Probablement la seule solution trouvable sur le net :
    Module afact.asm :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
     
    ; afact.asm: assembly program to be linked with cfact.c
     
    .386p		; 386 protected mode
    .model flat, C	; flat memory model, C calling convention
     
    .stack
    .data
     
    ; formats will be used to call printf
    ; c strings terminate in a 0 byte
    formats	db "the factorial of 6 is %d", 13, 10, 0
     
    .code
     
    ; declare printf and external function
    extrn printf: proc
     
    ; must use masm procedure syntax
    factorial proc
     
      	push ebp
    	mov ebp,esp
    	push ecx
    	push edx	; edx implicitly used in multiplication
     
    	mov ecx,[ebp+8]	; move param into a register
    	mov eax, 1	; accumulator
    lp0:	mul ecx		; eax = eax * ecx (edx ignored)
    	dec ecx
    	cmp ecx,2	; no need to multiply by 1
    	jge lp0	
    	; at this point eax contains n!, the return value
     
    	; prepare for printf:  (save eax, for printf returns a value!)
    	push eax	; second parameter to printf
    	mov ecx, offset formats	; address of format string
    	push ecx	; first parameter to printf
    	call printf
    	pop ecx		; deallocate parameters
    	pop eax
     
    	pop edx
    	pop ecx
    	mov esp,ebp
    	pop ebp
    	ret
     
    factorial endp
    end
    Module Cfact.c :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
     
    /* cfact.c */
     
    #include<stdio.h>
     
    /* to be linked externally: */
    extern int factorial(int n);
    /* in C++, use:
    extern "C" int factorial(int n);
    */
     
    int main()
    { int i;
      int A[10];
      int n = 6;
     
      n = factorial(n);
      printf("the factorial of 6 is %d\n",n); 
      exit(0);
    }
     
    /*  to combine with afact.asm (cygwin/gcc procedure):
     
    	ml /c /coff afact.asm   (produces afact.obj)
    	gcc afact.obj cfact.c   (produces a.exe)
    */
    tu déclares ta fonction printf comme ça (attention à la convention d'appel) et tu lies avec un programme C qui contient une fonction main et un printf.
    Note : évidemment, du coup il n'est pas possible de faire un code assembleur indépendant (END au lieu de END + label)...

    Dans la vie, il y a 10 sortes de personnes. Ceux qui comprennent le binaire et les autres...


  16. #16
    Membre régulier
    Profil pro
    Inscrit en
    Juin 2007
    Messages
    217
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2007
    Messages : 217
    Points : 105
    Points
    105
    Par défaut
    Je viens d'essayer de compiler ce programme, mais j'ai encore le même problème : je compile avec bcc32 au lieu de gcc et il ne supporte pas les fichiers .obj crées par ml (avec ou sans l'option -coff).

    Donc quand j'execute "bcc32 afact.obj cfact.c" il me dit que le fichier afact.obj n'est pas correct.


    ------------
    Dans la vie il y a trois sortes de personnes : celles qui savent compter et celles qui ne savent pas compter...

  17. #17
    Membre habitué
    Avatar de Stormy_Ordos
    Profil pro
    Expert sécurité informatique
    Inscrit en
    Mars 2005
    Messages
    91
    Détails du profil
    Informations personnelles :
    Localisation : Canada

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

    Informations forums :
    Inscription : Mars 2005
    Messages : 91
    Points : 166
    Points
    166
    Par défaut
    Tu as essayé de remplacer l'option -coff(format objet typique UNIX) par l'option -omf (typique MSDOS)?
    tu devrais aussi utiliser l'option -Cx (préserve la casse des déclarations publiques et externes)

    Dans la vie, il y a 10 sortes de personnes. Ceux qui comprennent le binaire et les autres...


  18. #18
    Membre régulier
    Profil pro
    Inscrit en
    Juin 2007
    Messages
    217
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2007
    Messages : 217
    Points : 105
    Points
    105
    Par défaut
    Non, ça ne solutionne pas le problème. en fait, j'ai l'erreur :
    "Borland C++ 5.5.1 for Win32 Copyright (c) 1993, 2000 Borland
    cfact.c:
    Turbo Incremental Link 5.00 Copyright (c) 1997, 2000 Borland
    Fatal: 'afact.asm': Additional segments need to be defined in a .def file"
    lors du linkage avec bcc32.

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

    Informations forums :
    Inscription : Juillet 2002
    Messages : 842
    Points : 696
    Points
    696
    Par défaut
    Borland distribue coff2omf avec son EDI en principe. Ca peut servir.

  20. #20
    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
    Points : 1 956
    Points
    1 956
    Par défaut
    Bonjour à tous,

    Les fonctions C (sous Win) sont disponibles dans la bibliothèque MSVCRT (microsoft Visual C Runtime) :

    http://msdn2.microsoft.com/en-us/lib...yh(VS.80).aspx

    Sous MASM, il suffit de lier sur cette bibliothèque et d'inclure l'entête (msvcrt.inc) qui va bien, tout est dispo dans le pack MASM "de base" :

    N.B : remarquez qu'il faut préfixer les noms de fonctions C avec 'crt_'

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
     
    .686p
    .model flat, stdcall  ;32 bit memory model
    option casemap :none  ;case sensitive
    assume FS:NOTHING
     
    include windows.inc
     
    include kernel32.inc
    includelib kernel32.lib
     
    include msvcrt.inc
    includelib msvcrt.lib
     
    .const 
    CRLF equ 0dh, 0ah; équivalent du '\n' en C [Carriage Ret + Line Feed]
     
    .data
    Format BYTE "Hello %s : %u", CRLF,0
    World BYTE "world",0
     
    .code
    start:
    	xor ecx, ecx
     
    @HelloLoop:
    	inc ecx
    	push ecx
    	cmp ecx, 11d
    	jz @EndLoop
    	invoke crt_printf, addr Format, addr World, ecx ; printf du C ! (fonction variadique appelée sans problème)
    	pop ecx
    	jmp @HelloLoop
    @EndLoop:
    	pop ecx
     
    	ret
    end start

    Output :

    Hello world : 1
    Hello world : 2
    Hello world : 3
    Hello world : 4
    ...
    Il pourrait être intéressant de lier sur msvcr80.dll (la dernière version en date du runtime C) plutôt que msvcrt.dll mais la version 80 ne dispose pas d'en-tête ni de fichier de lib. C'est faisable mais long et rébarbatif...

    Ceci dit, ça fonctionne très bien avec msvcrt.dll

    En espérant que cela réponde à la question d'origine.

+ Répondre à la discussion
Cette discussion est résolue.
Page 1 sur 2 12 DernièreDernière

Discussions similaires

  1. [Excel] Comment utiliser la fonction RECHERCHEV
    Par forsay1 dans le forum Macros et VBA Excel
    Réponses: 17
    Dernier message: 03/02/2006, 11h43
  2. Réponses: 3
    Dernier message: 31/12/2005, 23h09
  3. Comment utiliser la fonction NBR.JOURS.OUVRES?
    Par MEHCOOPER dans le forum Access
    Réponses: 9
    Dernier message: 20/10/2005, 12h50
  4. [MASM32] Comment utiliser md5()
    Par sefo dans le forum x86 32-bits / 64-bits
    Réponses: 14
    Dernier message: 13/12/2004, 00h29
  5. Réponses: 11
    Dernier message: 22/12/2003, 21h06

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