Flux rss
Collection CommentCaMarche.net
Rechercher : dans
Par : Pertinence Date Nom d'utilisateur
Statut : Non résolu

[C/C++] appel dynamique de fonction

@xi@g@me, le mardi 7 octobre 2008 à 16:51:48
Bonjour,
il y a un problème sur lequel je bloque depuis un certain temps, et je voudrais savoir si l'un d'entre vous peut m'aider (même si la solution nécessite de l'assembleur c'est pas un problème, et la portabilité m'importe peu (développement ciblé Windows exlu sous VS 2005 C++))

En fait je souhaite créer une bibliothèque dynamique (DLL) qui soit capable d'appeler des fonctions qui lui sont passées plus tard. Je m'explique

Le développeur qui utilise ma bibliothèque va créer une fonction, par exemple maFonction(int, int char*);
Ensuite, il me donne le pointeur de la fonction, puis il me dit que cette fonction prend 2 int et un char * (ce que l'on a aucun moyen de savoir à la compilation)
La DLL doit être capable d'appeller cette fonction avec les arguments demandés (la bibliothèque génère ces arguments en fonction d'autres entrées utilisateur)

Comment faire?


merci à tous d'avance
@xi@g@me
Configuration: Linux
Firefox 3.0.1
Répondre à @xi@g@me  Signaler ce message aux modérateurs Aller au dernier message

1


  • 2
    Ce message vous semble utile, votez !
  • Ce message ne vous semble pas utile, votez !
  • Signaler ce message aux modérateurs
kilian, le mardi 7 octobre 2008 à 19:06:59
Salut,

Non ça ne necessite pas d'assembleur :-)
Par contre il faudra que le pointeur de fonction en question fourni par l'utilisateur soit de nombre de paramètres variables, ou plus exactement ne prenne qu'un paramètre: un argument de type va_list (type standard fourni dans stdarg.h représentant une liste d'argument.

Quelques explications ici:
http://www.linux-kheops.com/doc/man/manfr/man-ascii-0.9/man3­/va_start.3.txt.html

Un exemple avec une fonction qui additionne deux entiers:
//Fichier source du developpeur
#include <stdarg.h>

int add(va_list args)
{
    int arg1, arg2;
    arg1 = va_arg(args, int);
    arg2 = va_arg(args, int);
    return arg1 + arg2;
}

int main()
{
    int test = exec_user_func(add, 1, 2);
    printf("%d\n", test); // Affichera 3
    return 0;
}

//Fichier dll
#include <stdarg.h>

typedef (int) (*func_variable) (va_list);

int exec_user_func(func_variable func, ...)
{
    int ret;
    va_list args;
    va_start(args, func);
    ret = func(args);
    va_end(args);
}


Bien sûr il faut quand même être sûr du type de retour, c'est la moindre des choses :-) Alors comme ça je fais le zouave hein?
Répondre à kilian

2


  • Ce message vous semble utile, votez !
  • Signaler ce message aux modérateurs
@xi@g@me, le mercredi 8 octobre 2008 à 00:08:14
salut,
et merci pour ta réponse rapide.

le souci est que je ne souhaite pas que l'utilisateur aie a utiliser va_list car il pourrait lancer ses méthodes de lui même parfois. j'ai pensé a va_list, mais je ne souhaite pas l'utiliser. Je voudrais que l'utilisateur aie a déclarer ses fonctions comme d'habitude (ex : void add(int, int);)

ass-tu une idée?
Répondre à @xi@g@me

3


  • Ce message vous semble utile, votez !
  • Signaler ce message aux modérateurs
Char Snipeur, le mercredi 8 octobre 2008 à 08:58:16
ba là je me demande si c'est faisable.
En C++ ça me semble impossible car la fonction a dans son nom le nombre et type d'argument une fois compilé.
en général, dans ce genre de cas, tu passe par un paramètre générique comme void*. Salutation !  avant je croyais, maintenant je suis fixé.Jésu­s Christ
Char Snipeur
Répondre à Char Snipeur

4


  • Ce message vous semble utile, votez !
  • Signaler ce message aux modérateurs
kilian, le mercredi 8 octobre 2008 à 10:21:28
De toutes façons même en C je doute que ça soit faisable comme tu le souhaites.
L'idéal comme le Char Snipeur, c'est d'avoir une fonction qui prends en paramètre un pointeur vers une structure, puis de l'appeller par la fonction de dll qui prendra le paramètre en tant que void *. Alors comme ça je fais le zouave hein?
Répondre à kilian

5


  • Ce message vous semble utile, votez !
  • Signaler ce message aux modérateurs
@xi@g@me, le mercredi 8 octobre 2008 à 14:20:32
salut,
En faisant des recherches sur internet, c'est effectivement ce que j'ai remarqué...
ne peut t-on pas faire en utilisant du code assembleur?

par exemple on fait un push des paramètres et ensuite un call sur la fonction (et un pop pour enlever les paramètres)
Répondre à @xi@g@me

6


  • Ce message vous semble utile, votez !
  • Signaler ce message aux modérateurs
kilian, le mercredi 8 octobre 2008 à 14:31:03
Ca ne change rien. Comment la fonction de la dll va deviner combien de paramètres il faut envoyer, et quels sont leurs types? Alors comme ça je fais le zouave hein?
Répondre à kilian

7


  • Ce message vous semble utile, votez !
  • Signaler ce message aux modérateurs
@xi@g@me, le mercredi 8 octobre 2008 à 16:59:51
on le lui dit par l'appel d'autres fonctions ^^
Répondre à @xi@g@me

8


  • Ce message vous semble utile, votez !
  • Signaler ce message aux modérateurs
kilian, le mercredi 8 octobre 2008 à 18:03:18
Ah dans ce cas oui. Il faut au préalable (ou durant l'appel) lui signaler le nombre de paramètres que tu lui soumets.
Mais bon c'est pas très propre tout ça :-) Alors comme ça je fais le zouave hein?
Répondre à kilian

9


  • 1
    Ce message vous semble utile, votez !
  • Ce message ne vous semble pas utile, votez !
  • Signaler ce message aux modérateurs
@xi@g@me, le mercredi 8 octobre 2008 à 19:22:26
en fait, un premier appel sert à donner à la DLL le pointeur de la fonction.
Ensuite, c'est assez complexe mais disons que l'utilisateur indique indirectement les paramètres formels de la fonction pour faire simple

une fois toutes les fonctions et leurs paramètres formels envoyés, l'utilisateur appelle une fonction qui lance un algorithme dans la DLL qui est susceptible d'appeler les fonctions transmises par l'utilisateur.
Répondre à @xi@g@me

10


  • 1
    Ce message vous semble utile, votez !
  • Ce message ne vous semble pas utile, votez !
  • Signaler ce message aux modérateurs
Char Snipeur, le jeudi 9 octobre 2008 à 08:36:39
Aîe ! ma tête...
Bonne chance, et dit nous si tu y arrive. Salutation !  avant je croyais, maintenant je suis fixé.Jésu­s Christ
Char Snipeur
Répondre à Char Snipeur

11


  • Ce message vous semble utile, votez !
  • Signaler ce message aux modérateurs
kilian, le jeudi 9 octobre 2008 à 09:59:49
Oui moi aussi bobo les neurones là... Alors comme ça je fais le zouave hein?
Répondre à kilian

12


  • Ce message vous semble utile, votez !
  • Signaler ce message aux modérateurs
@xi@g@me, le jeudi 9 octobre 2008 à 14:08:20
ben en fait, ce qu'il me faudrait c'est savoir comment implémenter du code assembleur dans Visual Studio 2005 et aussi comment faire pour savoir en assembleur ou sont stockées mes variables C.
Après il suffit d'expérimenter ^^'
Répondre à @xi@g@me

13


  • 1
    Ce message vous semble utile, votez !
  • Ce message ne vous semble pas utile, votez !
  • Signaler ce message aux modérateurs
kilian, le jeudi 9 octobre 2008 à 14:23:15
Dans VC:
__asm {
    mov eax, ebx
    etc....
}


Pour trouver tes variables, ah ben là.... :-)
C'est tout un truc à apprendre.
Les variables locales aux fonctions sont soit dans la pile soit dans des registres.
Généralement c'est les deux:
Les variables locales sont dans la pile. Mais dès qu'il faut faire un calcul sur ces variables, on les met dans des registres. Une fois le calcul fait, on les remets eventuellement dans la pile.

Mais pour optimiser, parfois le compilo cantone les variables dans les registres.

Quant aux variables globales sont dans des sections du binaire (dans la mémoire donc...quelque part).

Ici tu trouveras des renseignements dans les derniers chapitres : http://drpaulcarter.com/pcasm/

Le passage de paramètres, c'est dans la pile. Par défaut avec la convention cdecl, mais sous windows les fonctions de l'api sont en stdcall: http://www.commentcamarche.net/faq/sujet 4874 programmation conventions de passage de parametres sous x86

Voilà voilà. Ca va pas être facile au début :-) Alors comme ça je fais le zouave hein?
Répondre à kilian

14


  • Ce message vous semble utile, votez !
  • Signaler ce message aux modérateurs
@xi@g@me, le jeudi 9 octobre 2008 à 21:06:41
ok, merci beaucoup pour toutes ces infos ^^
dès que j'ai le temps j'essaye!!! (avec ce prof de génie logiciel on est pas sorti ^^')
Répondre à @xi@g@me

15


  • Ce message vous semble utile, votez !
  • Signaler ce message aux modérateurs
@xi@g@me, le jeudi 23 octobre 2008 à 15:07:25
salut à tous
j'avance un peu dans la résolution du problème, mais je suis tombé sur quelques trus assez amusants :

La première chose que j'ai faite est de créer ce petit programme :
(ici je fonctionne en stdcall pour le moment)

#include <stdio.h>

void __attribute__((stdcall)) ecrire(int a)
{
  printf("%d\n", a);
}

void __attribute__((stdcall)) afficher(char * s)
{
  printf("%s\n", s);
}

int main(int argc, char * argv[])
{
  int a = 24;
  int b = 35;
  char * tot = "totohffdfdvfgsjhdhjkgsgbdshfejgtrjhdfbvsdjbfjsvjfsyuedbfhndbsjvfjsdbfjhsdgfjgsjgeyugfhjsgfjsvfjgeygesyfv fgsgfeyu/n \n \%d frrty /t fdthdjhskdvnbnjfherkuiugfdhgbn nsejirhtier  et la ca marche encore ???????h";
  // affichage de 35
  ecrire(b);
  // affichage de toto
  afficher(tot);
  // affichage de 24
  ecrire(a);
}



je compile donc ce code en faisant g++ -S, et j'obtiens ceci (simplifié):

main:
.LFB4:
	leal	4(%esp), %ecx
.LCFI6:
	andl	$-16, %esp
	pushl	-4(%ecx)
.LCFI7:
	pushl	%ebp
.LCFI8:
	movl	%esp, %ebp
.LCFI9:
	pushl	%ecx
.LCFI10:
	subl	$20, %esp
.LCFI11:
	movl	$24, -16(%ebp)
	movl	$35, -12(%ebp)
	movl	$.LC1, -8(%ebp)
	movl	-12(%ebp), %eax
	movl	%eax, (%esp)
	call	_Z6ecrirei
	subl	$4, %esp
	movl	-8(%ebp), %eax
	movl	%eax, (%esp)
	call	_Z8afficherPc
	subl	$4, %esp
	movl	-16(%ebp), %eax
	movl	%eax, (%esp)
	call	_Z6ecrirei
	subl	$4, %esp
	movl	$0, %eax
	movl	-4(%ebp), %ecx
	leave
	leal	-4(%ecx), %esp
	ret


dans la partie déclarations des variables (ou je fais int b = 35; etc), je vois ceci : (LC1 c'est la chaine de caractères)
	movl	$24, -16(%ebp)
	movl	$35, -12(%ebp)
	movl	$.LC1, -8(%ebp)

On comprend donc en toute logique que dans la pile d'appel (ebp) on met de -8 à -5 la chaine de caractères (déclarée en dernier), de -12 à -9 l'entier b et de -16 à -13 l'entier a. J'en déduit donc que le compilateur met les variables dans l'ordre "inverse" de leur déclaration.

Ce qui m'a emmené à faire ceci :


#include <stdio.h>

void __attribute__((stdcall)) ecrire(int a)
{
  printf("%d\n", a);
}

void __attribute__((stdcall)) afficher(char * s)
{
  printf("%s\n", s);
}

typedef void (*f_ptr)();

int main(int argc, char * argv[])
{
  void (*ptr)() = (f_ptr)(ecrire);
  void (*ptr2)() = (f_ptr)(afficher);
  int a = 24;
  int b = 35;
  char * tot = "totohffdfdvfgsjhdhjkgsgbdshfejgtrjhdfbvsdjbfjsvjfsyuedbfhndbsjvfjsdbfjhsdgfjgsjgeyugfhjsgfjsvfjgeygesyfv fgsgfeyu/n \n \%d frrty /t fdthdjhskdvnbnjfherkuiugfdhgbn nsejirhtier  et la ca marche encore ???????h";

  // affichage de 35
  asm("pushl %eax");
  asm("movl -12(%ebp), %eax");
  asm("movl %eax, (%esp)");
  ptr();
  asm ("popl %eax");
  asm("subl $4, %esp");

  // affichage de tot
  asm("pushl %eax");
  asm("movl -8(%ebp), %eax");
  asm("movl %eax, (%esp)");
  ptr2();
  asm("popl %eax");
  asm("subl $4, %esp");

  // affichage de 24
  asm("pushl %eax");
  asm("movl -16(%ebp), %eax");
  asm("movl %eax, (%esp)");
  ptr();
  asm("popl %eax");
  asm("subl $4, %esp");
}



Le principe étant simple, (on créée 2 pointeurs de fonction a paramètre vides (void) qu'on affecte avec les fonctions à utiliser (avec un cast de type à l'aide de f_ptr), ensuite on empile en assembleur les paramètres des fonctions puis on appelle celles-ci grâce au pointeur), le code compile et fonctionne.


Pour pouvoir continuer, j'ai donc voulu écrire une fonction qui prend plusieurs paramètres pour voir comment elle est appelée. Pour ceci, je rajoute les paramètres avant a, b et tot afin d'éviter de changer leur adresse dans la pile d'appel.
j'obtiens donc le code suivant :


#include <stdio.h>

void __attribute__((stdcall)) ecrire(int a)
{
  printf("%d\n", a);
}

void __attribute__((stdcall)) ecrire2(short c, char d, long long x, int a)
{
  printf("%d-%d-%d-%d\n", c, d, x, a);
}

void __attribute__((stdcall)) afficher(char * s)
{
  printf("%s\n", s);
}

typedef void (*f_ptr)();

int main(int argc, char * argv[])
{
  void (*ptr)() = (f_ptr)(ecrire);
  void (*ptr2)() = (f_ptr)(afficher);
  short c = 12;
  char d = 'k';
  long long x = 285145145;
  int a = 24;
  int b = 35;
  char * tot = "totohffdfdvfgsjhdhjkgsgbdshfejgtrjhdfbvsdjbfjsvjfsyuedbfhndbsjvfjsdbfjhsdgfjgsjgeyugfhjsgfjsvfjgeygesyfv fgsgfeyu/n \n \%d frrty /t fdthdjhskdvnbnjfherkuiugfdhgbn nsejirhtier  et la ca marche encore ???????h";
  // affichage de 35
  asm("pushl %eax");
  asm("movl -12(%ebp), %eax");
  asm("movl %eax, (%esp)");
  ptr();
  asm ("popl %eax");
  asm("subl $4, %esp");
  // affichage de toto
  asm("pushl %eax");
  asm("movl -8(%ebp), %eax");
  asm("movl %eax, (%esp)");
  ptr2();
  asm("popl %eax");
  asm("subl $4, %esp");
  // appel de ecrire2
  ecrire2(c, d, x, a);
  // affichage de 24
  asm("pushl %eax");
  asm("movl -16(%ebp), %eax");
  asm("movl %eax, (%esp)");
  ptr();
  asm("popl %eax");
  asm("subl $4, %esp");
}



j'ai rajouté la fonction écrire2, ainsi que les variables de types long long, char et short (tant qu'à faire...)
j'obtiens ceci en assembleur (code complet)


	.file	"test.cpp"
	.text
	.align 2
.globl _Z8afficherPc
	.type	_Z8afficherPc, @function
_Z8afficherPc:
.LFB4:
	pushl	%ebp
.LCFI0:
	movl	%esp, %ebp
.LCFI1:
	subl	$8, %esp
.LCFI2:
	movl	8(%ebp), %eax
	movl	%eax, (%esp)
	call	puts
	leave
	ret	$4
.LFE4:
	.size	_Z8afficherPc, .-_Z8afficherPc
.globl __gxx_personality_v0
	.section	.rodata
.LC0:
	.string	"%d-%d-%d-%d\n"
	.text
	.align 2
.globl _Z7ecrire2scxi
	.type	_Z7ecrire2scxi, @function
_Z7ecrire2scxi:
.LFB3:
	pushl	%ebp
.LCFI3:
	movl	%esp, %ebp
.LCFI4:
	pushl	%ebx
.LCFI5:
	subl	$52, %esp
.LCFI6:
	movl	8(%ebp), %eax
	movl	12(%ebp), %edx
	movw	%ax, -12(%ebp)
	movb	%dl, -16(%ebp)
	movl	16(%ebp), %eax
	movl	%eax, -24(%ebp)
	movl	20(%ebp), %eax
	movl	%eax, -20(%ebp)
	movsbl	-16(%ebp),%ecx
	movswl	-12(%ebp),%ebx
	movl	24(%ebp), %eax
	movl	%eax, 20(%esp)
	movl	-24(%ebp), %eax
	movl	-20(%ebp), %edx
	movl	%eax, 12(%esp)
	movl	%edx, 16(%esp)
	movl	%ecx, 8(%esp)
	movl	%ebx, 4(%esp)
	movl	$.LC0, (%esp)
	call	printf
	addl	$52, %esp
	popl	%ebx
	popl	%ebp
	ret	$20
.LFE3:
	.size	_Z7ecrire2scxi, .-_Z7ecrire2scxi
	.section	.rodata
	.align 4
.LC1:
	.string	"totohffdfdvfgsjhdhjkgsgbdshfejgtrjhdfbvsdjbfjsvjfsyuedbfhndbsjvfjsdbfjhsdgfjgsjgeyugfhjsgfjsvfjgeygesyfv fgsgfeyu/n \n %d frrty /t fdthdjhskdvnbnjfherkuiugfdhgbn nsejirhtier  et la ca marche encore ???????h"
	.text
	.align 2
.globl main
	.type	main, @function
main:
.LFB5:
	leal	4(%esp), %ecx
.LCFI7:
	andl	$-16, %esp
	pushl	-4(%ecx)
.LCFI8:
	pushl	%ebp
.LCFI9:
	movl	%esp, %ebp
.LCFI10:
	pushl	%ebx
.LCFI11:
	pushl	%ecx
.LCFI12:
	subl	$80, %esp
.LCFI13:
	movl	$_Z6ecrirei, -44(%ebp)
	movl	$_Z8afficherPc, -40(%ebp)
	movw	$12, -36(%ebp)
	movb	$107, -33(%ebp)
	movl	$285145145, -32(%ebp)
	movl	$0, -28(%ebp)
	movl	$24, -20(%ebp)
	movl	$35, -16(%ebp)
	movl	$.LC1, -12(%ebp)
#APP
	pushl %eax
	movl -12(%ebp), %eax
	movl %eax, (%esp)
#NO_APP
	movl	-44(%ebp), %eax
	call	*%eax
#APP
	popl %eax
	subl $4, %esp
	pushl %eax
	movl -8(%ebp), %eax
	movl %eax, (%esp)
#NO_APP
	movl	-40(%ebp), %eax
	call	*%eax
#APP
	popl %eax
	subl $4, %esp
#NO_APP
	movsbl	-33(%ebp),%ecx
	movswl	-36(%ebp),%ebx
	movl	-20(%ebp), %eax
	movl	%eax, 16(%esp)
	movl	-32(%ebp), %eax
	movl	-28(%ebp), %edx
	movl	%eax, 8(%esp)
	movl	%edx, 12(%esp)
	movl	%ecx, 4(%esp)
	movl	%ebx, (%esp)
	call	_Z7ecrire2scxi
	subl	$20, %esp
#APP
	pushl %eax
	movl -16(%ebp), %eax
	movl %eax, (%esp)
#NO_APP
	movl	-44(%ebp), %eax
	call	*%eax
#APP
	popl %eax
	subl $4, %esp
#NO_APP
	movl	$0, %eax
	leal	-8(%ebp), %esp
	popl	%ecx
	popl	%ebx
	popl	%ebp
	leal	-4(%ecx), %esp
	ret
.LFE5:
	.size	main, .-main
	.section	.rodata
.LC2:
	.string	"%d\n"
	.text
	.align 2
.globl _Z6ecrirei
	.type	_Z6ecrirei, @function
_Z6ecrirei:
.LFB2:
	pushl	%ebp
.LCFI14:
	movl	%esp, %ebp
.LCFI15:
	subl	$8, %esp
.LCFI16:
	movl	8(%ebp), %eax
	movl	%eax, 4(%esp)
	movl	$.LC2, (%esp)
	call	printf
	leave
	ret	$4
.LFE2:
	.size	_Z6ecrirei, .-_Z6ecrirei
	.section	.eh_frame,"a",@progbits
.Lframe1:
	.long	.LECIE1-.LSCIE1
.LSCIE1:
	.long	0x0
	.byte	0x1
	.string	"zP"
	.uleb128 0x1
	.sleb128 -4
	.byte	0x8
	.uleb128 0x5
	.byte	0x0
	.long	__gxx_personality_v0
	.byte	0xc
	.uleb128 0x4
	.uleb128 0x4
	.byte	0x88
	.uleb128 0x1
	.align 4
.LECIE1:
.LSFDE1:
	.long	.LEFDE1-.LASFDE1
.LASFDE1:
	.long	.LASFDE1-.Lframe1
	.long	.LFB4
	.long	.LFE4-.LFB4
	.uleb128 0x0
	.byte	0x4
	.long	.LCFI0-.LFB4
	.byte	0xe
	.uleb128 0x8
	.byte	0x85
	.uleb128 0x2
	.byte	0x4
	.long	.LCFI1-.LCFI0
	.byte	0xd
	.uleb128 0x5
	.align 4
.LEFDE1:
.LSFDE3:
	.long	.LEFDE3-.LASFDE3
.LASFDE3:
	.long	.LASFDE3-.Lframe1
	.long	.LFB3
	.long	.LFE3-.LFB3
	.uleb128 0x0
	.byte	0x4
	.long	.LCFI3-.LFB3
	.byte	0xe
	.uleb128 0x8
	.byte	0x85
	.uleb128 0x2
	.byte	0x4
	.long	.LCFI4-.LCFI3
	.byte	0xd
	.uleb128 0x5
	.byte	0x4
	.long	.LCFI6-.LCFI4
	.byte	0x83
	.uleb128 0x3
	.align 4
.LEFDE3:
.LSFDE5:
	.long	.LEFDE5-.LASFDE5
.LASFDE5:
	.long	.LASFDE5-.Lframe1
	.long	.LFB5
	.long	.LFE5-.LFB5
	.uleb128 0x0
	.byte	0x4
	.long	.LCFI7-.LFB5
	.byte	0xc
	.uleb128 0x1
	.uleb128 0x0
	.byte	0x9
	.uleb128 0x4
	.uleb128 0x1
	.byte	0x4
	.long	.LCFI8-.LCFI7
	.byte	0xc
	.uleb128 0x4
	.uleb128 0x4
	.byte	0x4
	.long	.LCFI9-.LCFI8
	.byte	0xe
	.uleb128 0x8
	.byte	0x85
	.uleb128 0x2
	.byte	0x4
	.long	.LCFI10-.LCFI9
	.byte	0xd
	.uleb128 0x5
	.byte	0x4
	.long	.LCFI12-.LCFI10
	.byte	0x84
	.uleb128 0x4
	.byte	0x83
	.uleb128 0x3
	.align 4
.LEFDE5:
.LSFDE7:
	.long	.LEFDE7-.LASFDE7
.LASFDE7:
	.long	.LASFDE7-.Lframe1
	.long	.LFB2
	.long	.LFE2-.LFB2
	.uleb128 0x0
	.byte	0x4
	.long	.LCFI14-.LFB2
	.byte	0xe
	.uleb128 0x8
	.byte	0x85
	.uleb128 0x2
	.byte	0x4
	.long	.LCFI15-.LCFI14
	.byte	0xd
	.uleb128 0x5
	.align 4
.LEFDE7:
	.ident	"GCC: (GNU) 4.1.2 20071124 (Red Hat 4.1.2-42)"
	.section	.note.GNU-stack,"",@progbits



je m'intéresse à la partie déclaration des variables, et là :

.LCFI13:
	movl	$_Z6ecrirei, -44(%ebp)
	movl	$_Z8afficherPc, -40(%ebp)
	movw	$12, -36(%ebp)
	movb	$107, -33(%ebp)
	movl	$285145145, -32(%ebp)
	movl	$0, -28(%ebp)
	movl	$24, -20(%ebp)
	movl	$35, -16(%ebp)
	movl	$.LC1, -12(%ebp)



l'entier b (35) a été déplacé a -16, le a à -20 et la chaine de caractères à -12 :S
alors ma question est pourquoi il n'y a plus rien à -8 (une chaine de caractères étant un pointeur sur caractères (machine 32 bits) elle ne prend que 4 octets et donc que de -12 à -9, et aussi pourquoi le long long ne prend que de -32 (jusqu'à -25) et laisse donc de -24 à -21 libre???

est-ce que quelqu'un à une idée? je ne comprend pas le comportement du compilateur

merci d'avance et bon courage :p ^^
Répondre à @xi@g@me

16


  • Ce message vous semble utile, votez !
  • Signaler ce message aux modérateurs
Char Snipeur, le jeudi 23 octobre 2008 à 15:45:03
Salut.
Je suis une quiche grave en assembleur.
Mais pour tes histoires de décalage, j'ai peux être un début de réponse : à cause de l'alignement.
Pour accéder plus vite aux données, des fois le compilateur les décales, car il lit par paquet. Regarde le chapitre 7 de ce livre, c'est à ça que ça m'a fait pensé : http://beuss.developpez.com/tutoriels/pcasm/
Après, il est possible que ça n'est rien à voir. Peut être intercale t'il des données masqué à ces endroits, essai éventuellement de les lire. Salutation !  avant je croyais, maintenant je suis fixé.Jésu­s Christ
Char Snipeur
Répondre à Char Snipeur

17


  • Ce message vous semble utile, votez !
  • Signaler ce message aux modérateurs
kilian, le jeudi 23 octobre 2008 à 16:42:17
Il n'y a plus à -8 parce que ebx etc ecx on t été pushés.
Donc il y a ces deux registres entre (%ebp) et 8(%ebp).
Par contre entre 21 et 24, c'est le mystère... Peut être l'alignement oui.

En tout cas, comme tu l'as vu le comportement d'un compilateur n'est pas facile à prévoir, donc l'idéal c'est d'utiliser des références évoluées à tes variables.

Voilà comment je verrais bien ton code:
#include <stdio.h>

void __attribute__((stdcall)) ecrire(int a)
{
  printf("%d\n", a);
}

void __attribute__((stdcall)) ecrire2(short c, char d, long x, int a)
{
  printf("%d-%d-%d-%d\n", c, d, x, a);
}

void __attribute__((stdcall)) afficher(char * s)
{
  printf("%s\n", s);
}

typedef void (*f_ptr)();

int main(int argc, char * argv[])
{
  void (*ptr)() = (f_ptr)(ecrire);
  void (*ptr2)() = (f_ptr)(afficher);
  short c = 12;
  char d = 'k';
  long x = 285145145;
  int a = 24;
  int b = 35;
  char * tot = "totohffdfdvfgsjhdhjkgsgbdshfejgtrjhdfbvsdjbfjsvjfsyuedbfhndbsjvfjsdbfjhsdgfjgsjgeyugfhjsgfjsvfjgeygesyfv fgsgfeyu/n \n \%d frrty /t fdthdjhskdvnbnjfherkuiugfdhgbn nsejirhtier  et la ca marche encore ???????h";

__asm__ __volatile__(

  // affichage de 35
  "pushl %1\n"
  "call *(%7)\n"
  "add$4, %esp\n"

  // affichage de toto
  "pushl %0\n"
  "call *(%6)\n"
  "add $4, %esp\n"

  // appel de ecrire2
  ecrire2(c, d, x, a);
  // affichage de 24
  "pushl %2\n"
  "pushl %3\n"
  "pushw %4\n"
  "pushw %5\n"
  "call ecrire2\n"
  "add $0xc, %esp\n";
  :
  : "r" (tot), "r"(b), "r"(a), "r"(x), "r"(d), "r"(c), "r"(ptr2), "r"(ptr)
);



C'est un peu spécial et pas facile à expliquer.
Il faudrait que tu lises ça: http://www.ibm.com/developerworks/linux/library/l-ia.html

PS: Je peux pas tester le code ici donc ya sûrement quelques erreurs. Le gâteau est un mensonge!
Répondre à kilian

19


  • Ce message vous semble utile, votez !
  • Signaler ce message aux modérateurs
@xi@g@me, le dimanche 9 novembre 2008 à 18:49:38
je crois comprendre ce que tu veux dire...

cela me semble est une solution, mais j'ai encore quelques questions

en utilisant ta méthode, est-ce qu'il serait possible par exemple de préparer l'appel à la fonction en plusieurs parties?
je m'explique : quand la bibli recoit un pointeur de fonction, et ses paramètres je ne peux pas tout faire directement sinon il me faudrait du code assembleur pour chaque cas.
Ce que je voudrais avoir au final serait un mélange de C(++) et d'asm pour empiler dynamiquement mes paramètres en fonction de ceux qui me sont demandés

ex:
param=0
boucle
switch(param)
si (param = char)
code_assembleur_pour_pusher_char
si (param = int)
code_assembleur_pour_pusher_int
etc....
fin switch
param++
si (param = nb_param) quitter_la_boucle
fin_boucle
code_assembleur_pour_appeler_la_fonction
code_assembleur_pour_nettoyer_la_pile_a_la_fin_de_l_appel_de­_la_fonction

est-ce que cette solution peut marcher dans une DLL en sachant que les utilisateurs donnent les fonctions a appeler une fois la DLL compilée (donc elle ne sait rien avant)?

merci d'avance
Répondre à @xi@g@me

20


  • Ce message vous semble utile, votez !
  • Signaler ce message aux modérateurs
kilian, le dimanche 9 novembre 2008 à 19:06:48
Wep à priori il devrait pas y avoir de problème. Le gâteau est un mensonge!
Répondre à kilian

21


  • Ce message vous semble utile, votez !
  • Signaler ce message aux modérateurs
 @xi@g@me, le dimanche 9 novembre 2008 à 19:19:37
ok merci je vous tiens au jus
+++
Répondre à @xi@g@me

Résultats pour [C/C++] appel dynamique de fonction

Creation d'une fonction ss Excel (Résolu) Bonsoir a tous, voila , j'ai un petit souci sous excel, je desire ecrire une fonction qui me permettrait de changer la couleur d'une case en fonction de son contenu appelé depuis une cellule d'excel (la mise au format conditionnel ne... www.commentcamarche.net/forum/affich-2074377-creation-d-une-fonction-ss-excel
Appel de fonction dans une classe (Résolu) Bonjour, Je découvre un peu la poo. Pardon d'avance si cette question a déjà été posée, je ne l'ai pas trouvée. Ma question est on ne peut plus simple. Voici un bête code qui ne fonctionne pas et j'aimerais savoir pourquoi. Tant que je... www.commentcamarche.net/forum/affich-7186257-appel-de-fonction-dans-une-classe
Concours dans la fonction publique (Résolu) bonjour Je cherche à savoir si il existe des concours dans la fonction publique dans le secteur de la PAO/DAO ou bien le webdesign ce qui me permetterais de chercher aussi dans le secteur publique. Sinon auraient ils d'autres possibilitées pour... www.commentcamarche.net/forum/affich-3604275-concours-dans-la-fonction-publique

Résultats pour [C/C++] appel dynamique de fonction

Les inlines en C++Signification Exemple 1 Inline et headers Exemple 2 Signification Le mot-clé inline est utilisé en C++ et s'applique à une fonction. Il indique au compilateur que chaque appel à la fonction inline devra être remplacé par le corps de cette... www.commentcamarche.net/faq/sujet-11250-les-inlines-en-c
[Linux] Vérifier la réussite de la gravure d'un cdVérifier la réussite de la gravure d'un cd Rappel Principe Fonctionnement Rappel Sous Linux il existe un logiciel vous permettant directement de vérifier l'intégrité d'un fichier par comparaison. C'est md5sum qui permet de calculer la... www.commentcamarche.net/faq/sujet-1923-linux-verifier-la-reussite-de-la-gravure-d-un-cd
Lire les flux audio/vidéo en streamingCette astuce s´adresse a toute personne fatiguée de ne pas pouvoir lire ou lire avec difficulté les fichiers en "streaming" disponible sur le net. MediaPlayerConnectivity Cette solution s'appelle MediaPlayerConnectivity. Fonctionnalités ... www.commentcamarche.net/faq/sujet-8959-lire-les-flux-audio-video-en-streaming

Résultats pour [C/C++] appel dynamique de fonction

Mon clic droit ne fonctionne pas sous ie7 (Résolu)Bonjour, Je ne comprend pas pourquoi je mon clic droit ne fonctionne pas sur les pages web ouvertes avec ie7 Dans la barre d'adresse ça marche j'ai bien les commandes "copier, coller..." mais dans les pages internet je n'ai rien.... www.commentcamarche.net/forum/affich-3435425-mon-clic-droit-ne-fonctionne-pas-sous-ie7
Carte graphique ne fonctionne plus (Résolu)Bonjour, depuis quelques temps, je recoit un message d'erreur à chaque démarrage qui me dit que ATI ne fonctionne pas, car un pilote n'est pas installé ou car il ne fonctionne plus. De plus, je pense qu'il s'agit de ma carte video,... www.commentcamarche.net/forum/affich-2726246-carte-graphique-ne-fonctionne-plus
[SHELL] shell qui appelle une fonction C ? (Résolu)Salut ! Je cherche à faire un script shell qui appelle une fonction C...En gros, j'ai mon fichier C avec une fonction int calcul() par exemple... et mon script appelle cette fonction calcul. Je cherche..mais trouve pas... Si vous avez des... www.commentcamarche.net/forum/affich-3243478-shell-shell-qui-appelle-une-fonction-c