[C/C++] appel dynamique de fonction
Fermé
@xi@g@me
Messages postés
68
Date d'inscription
lundi 2 juin 2008
Statut
Membre
Dernière intervention
25 septembre 2018
-
7 oct. 2008 à 16:51
@xi@g@me Messages postés 68 Date d'inscription lundi 2 juin 2008 Statut Membre Dernière intervention 25 septembre 2018 - 9 nov. 2008 à 19:19
@xi@g@me Messages postés 68 Date d'inscription lundi 2 juin 2008 Statut Membre Dernière intervention 25 septembre 2018 - 9 nov. 2008 à 19:19
A voir également:
- [C/C++] appel dynamique de fonction
- Tableau croisé dynamique - Guide
- Fonction si et - Guide
- Appel anonyme - Guide
- Liste déroulante dynamique excel - Guide
- Nommez une application d'appel vidéo ou de visioconférence - Guide
17 réponses
kilian
Messages postés
8731
Date d'inscription
vendredi 19 septembre 2003
Statut
Modérateur
Dernière intervention
20 août 2016
1 527
7 oct. 2008 à 19:06
7 oct. 2008 à 19:06
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:
Bien sûr il faut quand même être sûr du type de retour, c'est la moindre des choses :-)
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 :-)
@xi@g@me
Messages postés
68
Date d'inscription
lundi 2 juin 2008
Statut
Membre
Dernière intervention
25 septembre 2018
4
8 oct. 2008 à 00:08
8 oct. 2008 à 00:08
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?
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?
Char Snipeur
Messages postés
9813
Date d'inscription
vendredi 23 avril 2004
Statut
Contributeur
Dernière intervention
3 octobre 2023
1 298
8 oct. 2008 à 08:58
8 oct. 2008 à 08:58
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*.
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*.
kilian
Messages postés
8731
Date d'inscription
vendredi 19 septembre 2003
Statut
Modérateur
Dernière intervention
20 août 2016
1 527
8 oct. 2008 à 10:21
8 oct. 2008 à 10:21
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 *.
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 *.
Vous n’avez pas trouvé la réponse que vous recherchez ?
Posez votre question
@xi@g@me
Messages postés
68
Date d'inscription
lundi 2 juin 2008
Statut
Membre
Dernière intervention
25 septembre 2018
4
8 oct. 2008 à 14:20
8 oct. 2008 à 14:20
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)
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)
kilian
Messages postés
8731
Date d'inscription
vendredi 19 septembre 2003
Statut
Modérateur
Dernière intervention
20 août 2016
1 527
8 oct. 2008 à 14:31
8 oct. 2008 à 14:31
Ca ne change rien. Comment la fonction de la dll va deviner combien de paramètres il faut envoyer, et quels sont leurs types?
@xi@g@me
Messages postés
68
Date d'inscription
lundi 2 juin 2008
Statut
Membre
Dernière intervention
25 septembre 2018
4
8 oct. 2008 à 16:59
8 oct. 2008 à 16:59
on le lui dit par l'appel d'autres fonctions ^^
kilian
Messages postés
8731
Date d'inscription
vendredi 19 septembre 2003
Statut
Modérateur
Dernière intervention
20 août 2016
1 527
8 oct. 2008 à 18:03
8 oct. 2008 à 18:03
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 :-)
Mais bon c'est pas très propre tout ça :-)
@xi@g@me
Messages postés
68
Date d'inscription
lundi 2 juin 2008
Statut
Membre
Dernière intervention
25 septembre 2018
4
8 oct. 2008 à 19:22
8 oct. 2008 à 19:22
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.
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.
Char Snipeur
Messages postés
9813
Date d'inscription
vendredi 23 avril 2004
Statut
Contributeur
Dernière intervention
3 octobre 2023
1 298
9 oct. 2008 à 08:36
9 oct. 2008 à 08:36
Aîe ! ma tête...
Bonne chance, et dit nous si tu y arrive.
Bonne chance, et dit nous si tu y arrive.
kilian
Messages postés
8731
Date d'inscription
vendredi 19 septembre 2003
Statut
Modérateur
Dernière intervention
20 août 2016
1 527
9 oct. 2008 à 09:59
9 oct. 2008 à 09:59
Oui moi aussi bobo les neurones là...
@xi@g@me
Messages postés
68
Date d'inscription
lundi 2 juin 2008
Statut
Membre
Dernière intervention
25 septembre 2018
4
9 oct. 2008 à 14:08
9 oct. 2008 à 14:08
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 ^^'
Après il suffit d'expérimenter ^^'
kilian
Messages postés
8731
Date d'inscription
vendredi 19 septembre 2003
Statut
Modérateur
Dernière intervention
20 août 2016
1 527
9 oct. 2008 à 14:23
9 oct. 2008 à 14:23
Dans VC:
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://www.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 :-)
__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://www.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 :-)
@xi@g@me
Messages postés
68
Date d'inscription
lundi 2 juin 2008
Statut
Membre
Dernière intervention
25 septembre 2018
4
9 oct. 2008 à 21:06
9 oct. 2008 à 21:06
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 ^^')
dès que j'ai le temps j'essaye!!! (avec ce prof de génie logiciel on est pas sorti ^^')
@xi@g@me
Messages postés
68
Date d'inscription
lundi 2 juin 2008
Statut
Membre
Dernière intervention
25 septembre 2018
4
23 oct. 2008 à 15:07
23 oct. 2008 à 15:07
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)
je compile donc ce code en faisant g++ -S, et j'obtiens ceci (simplifié):
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)
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 :
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 :
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)
je m'intéresse à la partie déclaration des variables, et là :
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 ^^
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 ^^
Char Snipeur
Messages postés
9813
Date d'inscription
vendredi 23 avril 2004
Statut
Contributeur
Dernière intervention
3 octobre 2023
1 298
23 oct. 2008 à 15:45
23 oct. 2008 à 15:45
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é : https://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.
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é : https://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.
kilian
Messages postés
8731
Date d'inscription
vendredi 19 septembre 2003
Statut
Modérateur
Dernière intervention
20 août 2016
1 527
23 oct. 2008 à 16:42
23 oct. 2008 à 16:42
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:
C'est un peu spécial et pas facile à expliquer.
Il faudrait que tu lises ça: https://www.ibm.com/developerworks/linux/library/l-ia/index.html
PS: Je peux pas tester le code ici donc ya sûrement quelques erreurs.
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: https://www.ibm.com/developerworks/linux/library/l-ia/index.html
PS: Je peux pas tester le code ici donc ya sûrement quelques erreurs.
@xi@g@me
Messages postés
68
Date d'inscription
lundi 2 juin 2008
Statut
Membre
Dernière intervention
25 septembre 2018
4
9 nov. 2008 à 18:49
9 nov. 2008 à 18:49
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
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
kilian
Messages postés
8731
Date d'inscription
vendredi 19 septembre 2003
Statut
Modérateur
Dernière intervention
20 août 2016
1 527
9 nov. 2008 à 19:06
9 nov. 2008 à 19:06
Wep à priori il devrait pas y avoir de problème.
@xi@g@me
Messages postés
68
Date d'inscription
lundi 2 juin 2008
Statut
Membre
Dernière intervention
25 septembre 2018
4
9 nov. 2008 à 19:19
9 nov. 2008 à 19:19
ok merci je vous tiens au jus
+++
+++