1

Salut, je voulais faire ce code juste pour tester:

Je veux appeler une fonction dont je connais l'adresse avec un nb variable d'arguments.

#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>

void coucou(int i, int j) {
	printf("&i=0x%p\n",&i);
	printf("&j=0x%p\n",&j);
	printf("coucou=%d %d\n",i,j);
}

void callfuncv(void* ptr, ...) {

	va_list ap;
	va_start(ap, ptr);
	
	void (*fonction)(void*);
	
	printf("Function address 0x%p\n",ptr);
	printf("              ap 0x%p\n",ap);

	fonction=ptr;

	(*fonction)(ap);
	printf("Done.");
	
	va_end(ap);
}

int main(int argc, char *argv[])
{
	coucou(2,3);
	printf("\n");
	callfuncv(&coucou, 2, 3);
	
}


Voici ce que ca me donne:
E:\_doc\C\devcpp\arg_test>arg_test
&i=0x0022FF50
&j=0x0022FF54
coucou=2 3

Function address 0x004012A0
              ap 0x0022FF54
&i=0x0022FF30
&j=0x0022FF34
coucou=2293572 2293588
Done.
E:\_doc\C\devcpp\arg_test>


Je me rends compte que AP pointe au bon endroit (j'ai vérifié que (int) (*ap) = 2 )

Ici, ca m'embête, parce que je voudrais qu'au 2e appel, on ait aussi &i=0x22FF54.

Quand j'appelle ma fonction par (*fonction)(ap); il me semble que ca va dire à la fonction de commencer à récupérer ses args à partir de 0x22FF54. Mais en fait, non, il fait un autre stack frame (normal en fait après quelque réflexion...)

En écrivant ce post je viens de réfléchir qu'il ne me faudrait pas faire un appel de fonction, mais un asm "jmp ptr". Mais comment lui dire où sont les arguments? en bidouillant SP? et comment être sûr que mes arguments sont passés par la pile?

Est ce bien ça?
N'y a-t-il aucun autre moyen?

Merci par avance.

2

Tu n'as pas moyen de faire ça en C... Les arguments variables, c un gros hack pour pas que printf soit trop chiant à utiliser, point. Si tu veux que ta fonction puisse prendre un nb d'arguments décidé par exemple en runtime, tu es obligé de faire une autre variante qui prend en argument le tableau des paramètres...

« The biggest civil liberty of all is not to be killed by a terrorist. » (Geoff Hoon, ministre des transports anglais)

3

Je suis assez nul en asm.

Je voudrais tester ca:

void callfuncv(void* ptr, ...) {

	va_list ap;
	va_start(ap, ptr);
	
	void (*fonction)(void*);
	
	printf("Function address 0x%p\n",ptr);
	printf("              ap 0x%p\n",ap);

	__asm {
		push esp
		mov esp, DWORD PTR [ap]
		mov eax, DWORD PTR [ptr]
  	  	jmp eax
		pop esp
	}
	printf("Done.");
	
	va_end(ap);
}


Mais cela ne marche pas, car j'utilise dev-cpp qui veut un truc bizarre avec l'asm (ca je le sais, mais je ne sais pas comment tongue)
En plus je sais pas ce que vaut mon code qui devrait faire ce que je veux selon ce que j'ai compris de l'asm x86 grin

Aidez moi, je sens que je perds du temps: "il vaut mieux un qui sait que 100 qui cherchent..."

Edit: cross!

4

Essaye de remplacer __asm { bla } par asm("bla"); et en rajoutant des % devant les noms de registres (et aussi en inversant l'ordre des arguments je crois triso)

« The biggest civil liberty of all is not to be killed by a terrorist. » (Geoff Hoon, ministre des transports anglais)

5

	asm ("
		push %esp
		mov %esp, DWORD PTR [ap]
		mov %eax, DWORD PTR [ptr]
  		jmp %eax
		pop %esp
 ");


Assembler messages:
Error: junk `PTR [ap]' after expression
Error: junk `PTR [ptr]' after expression
Warning: indirect jmp without `*'

cry

Nan sérieux elle est où la merde?

En en plus, est ce que ce code ferait ce que je veux? Pas la peine de m'embêter sinon ^^

6

./1:
Tu peux pas.
Par contre tu peux:
1. Declarer coucou comme:
void coucou(va_list p); //
Et qu'il recupere les arguments de lui meme.

2. Utiliser les fonctions de profile de GCC qui peuvent etre inclusent dans chaque appel de fonction.

3. Utiliser les extensions de GCC pour transmettre des arguments, mais tu dois avoir une idee du nombre d'arguments max possibles.

7

8

Je precise que j'ai jamais essayer le ./4 :

Using the built-in functions described below, you can record the
arguments a function received, and call another function with the same
arguments, without knowing the number or types of the arguments.

You can also record the return value of that function call, and
later return that value, without knowing what data type the function
tried to return (as long as your caller expects that data type).

- Built-in Function: void * __builtin_apply_args ()
This built-in function returns a pointer to data describing how to
perform a call with the same arguments as were passed to the
current function.

The function saves the arg pointer register, structure value
address, and all registers that might be used to pass arguments to
a function into a block of memory allocated on the stack. Then it
address, and all registers that might be used to pass arguments to
a function into a block of memory allocated on the stack. Then it
returns the address of that block.

- Built-in Function: void * __builtin_apply (void (*FUNCTION)(), void
*ARGUMENTS, size_t SIZE)
This built-in function invokes FUNCTION with a copy of the
parameters described by ARGUMENTS and SIZE.

The value of ARGUMENTS should be the value returned by
`__builtin_apply_args'. The argument SIZE specifies the size of
the stack argument data, in bytes.

This function returns a pointer to data describing how to return
whatever value was returned by FUNCTION. The data is saved in a
block of memory allocated on the stack.

It is not always simple to compute the proper value for SIZE. The
value is used by `__builtin_apply' to compute the amount of data
that should be pushed on the stack and copied from the incoming
argument area.
- Built-in Function: void __builtin_return (void *RESULT)
This built-in function returns the value described by RESULT from
the containing function. You should specify, for RESULT, a value
returned by `__builtin_apply'.

9

Extrait de la doc de GCC, a utiliser sous licence GDL.

10

Pas de problème, c'est juste perso.

En fait mon truc c'est pour pallier à un manque de visual basic: il veut bien filer l'adresse d'une fonction avec AddressOf, mais ne fournit aucun moyen de l'utiliser. Et impossible de faire des casts à la [return_type (*ptr_func)(args);] Donc je me démerde. smile

Merci pour ta doc, je crois qu'elle va m'aider hehe

11

si c du .NET, tu dois pouvoir t'arranger en passant par d'autres langages...

« The biggest civil liberty of all is not to be killed by a terrorist. » (Geoff Hoon, ministre des transports anglais)

12

T'es sur qu'une fonction Visual Basic passe ses arguments par la pile ?

13

.net, que dalle. VB6 pawa. Bon, on s'en fout.

Quand je fais une DLL il faut que je déclare mes exports en __stdcall. Je pense bien que ca utilise la pile, non?

14

Pour les exports, pas pour les fonctions VB je pense...

(et pis vb<7 sux ^^)

« The biggest civil liberty of all is not to be killed by a terrorist. » (Geoff Hoon, ministre des transports anglais)

15

En plus de ta syntaxe assembleur totalement incorrecte, tu ne peux pas faire un pop %esp pour restaurer la pile parce que pop lit sur %esp, justement.

Sinon, la syntaxe correcte (mais qui ne fonctionnerait quand-même pas, cf. ci-dessus pour le problème de cette routine) est:
	asm volatile (
		"\tpushl %%esp\n"
		"\tmovl (%0),%%esp\n"
		"\tmovl (%1),%%eax\n"
  		"\tjmp *%%eax\n"
		"\tpopl %%esp\n"
	::"r"(ap),"r"(ptr):"eax");
avatar
Mes news pour calculatrices TI: Ti-Gen
Mes projets PC pour calculatrices TI: TIGCC, CalcForge (CalcForgeLP, Emu-TIGCC)
Mes chans IRC: #tigcc et #inspired sur irc.freequest.net (UTF-8)

Liberté, Égalité, Fraternité

16

oui ne t'inquiète pas je reconnais volontiers mon incompétence très forte en asm ^^
j'ai laissé tomber pour le moment, ca me gonfle un peu!