Ecrire un programme C utilisant des fonctions faites en assembleurs... - C++ - Programmation
Marsh Posté le 01-12-2002 à 02:07:52
pour ce que je vais te décrire, je me base sur Watcom C/C++ à l'époque ou je codais en asm sous dos avec un dos-extender (dos4gw/pmodew):
étant donné que c'était du mode protégé, l'idée reste valable.
alors l'idéal:
jouer avec les #pragma et autres __fastcall pour que tes fonctions "extern" ayent leurs paramètres de passés par les registre et non par la pile.
les fonctions cotés asm doivent être déclarés de la manière suivante, dans le segment TEXT:
_TEXT SEGMENT DWORD PUBLIC 'CODE' ; déclaration du segment de code
PUBLIC FunctionAsm_ ; FunctionAsm_ sera "exporté" (nom de symbole conservé dans le .obj)
FunctionAsm_ PROC NEAR ; déclaration de la fonction
...
...
FunctionAsm_ ENDP
_TEXT ENDS ; fin du segment de code
le "_" semble être relativement standard aux compilateurs C.
attention: si tu link avec du c++, la déclaration de la fonction sera alors:
extern "C" FunctionAsm(int....);
ce qui était génial avec le watcom, c'est que tu pouvais forcer les paramètres dans chaque registre avec un truc style:
extern int yopla(int a, int b);
#pragma aux yopla parm [ecx] [esi] value [edx];
le int retourné se retrouvant dans edx, a dans ecx et b dans esi.
Marsh Posté le 01-12-2002 à 02:09:03
je pense qu'il manque peut être le "_" au nom de fonction f.
à la limite fait une fonction à la con en C, dump le code asm et observe les conventions de nommage...
Marsh Posté le 01-12-2002 à 02:28:14
Bon ca marche presque (le linkage est passé) manque plus qu'à trouver comment les paramettres sont passé et retrouver
Dans le code en ASM j'ai fait comme t'as dit sauf qu'il fallait mettre le _ devant le nom
Dans le code c fallait préciser en en-tete extern "C" f(int...)
Parceque comme je compilais mes fichier C sous visual ce con me les compilait comme si ct du C++ donc ca marchait pas donc fallait effectivement passer le "C"
Marsh Posté le 01-12-2002 à 03:42:19
Bon j'ai compris comment paser des paramettre de mon programme C vers mon code ASM.
En fait si une fonction admet comme paramettre:
f(int A, int B, int C)
le programe empile dans le stack
C puis B puis A puis EIP
donc pour recup les param dans le sous prog suffit de faire:
Code :
|
Et là ca marche
Maintenant me faudrait recupérer les donner du code asm vers le prog C. Si quelqu'un connait la procédure qui est utilisé ce serait cool
Si quelqu'un sait aussi comment sont passées les structure ce serait bien aussi qu'il m'explique. Pour l'instant j'ai pas encore bcp tester mais j'ai l'impression qu'on empile tous les membre de la struct (mais j'ai pas capter dans quel ordre)
Marsh Posté le 01-12-2002 à 08:28:23
EIP
Mais kesskidi ?
Ah ok, ESP, ton Stack pointer...
Marsh Posté le 01-12-2002 à 10:46:47
Il y a une norme pour ça, il va peut-être falloir que tu cherches un peu pour trouver la bonne réponse. Voici ce qu'en j'en sais en attendant :
- Tout les résultats qui tiennent sur un registre ( int, char, void * ... ) passent leur résultat sur EAX.
- Ta struct doit avoir en mémoire exactement la même organisation que si elle avait été allouée sur le tas.
PS : Pourquoi tu met ESP dans EBP ? Il me semble que faire MOV EAX,[ESP+4] ça marche très bien aussi et c'est pas plus lent, non ?
Marsh Posté le 01-12-2002 à 11:43:38
Kristoph:ESP n'est pas un registre d'indexe donc on est obligé de passer par EBP.
Meme qd le resultat tient sur un int j'arrive pas à le recup dans EAX. J'ai l'impression que c passer par pile aussi
Tetedeiench: EIP Bah oui on empile toujour l'adresse de retour.
Code :
|
Marsh Posté le 01-12-2002 à 11:59:45
pour le passage de param, fouille dans la msdn, y'a un article qui décrit tres bien ca. (par contre pour ce genre de sport il déconseille _fastcall car c + chiant de retrouver ou sont les paramètres)
le retour se fait comme ca (du moins, sous visu)
taille du type de retour :
4o : retour dans EAX
8o : retour dans EDX:EAX
+8 : passage a ta fonction d'un pointeur vers la structure de retour, pointeur stocké dans EAX. Donc tu colles le resultat a l'adresse mémoire pointé par ledit pointeur
Par contre, gaffe, parfois visu fait des trucs louche. J'avais une structure de 8o, mais vu qu'y avait des fonction dedans, visu la passait comme une struct de taille supérieur
si tu veux appeler des fonctions de type __thiscall, il te faut mettre "this" dans edx (tjs sous visu)
Pense a cleaner la pile a la fin de ta fonction, aussi
Marsh Posté le 01-12-2002 à 13:08:07
sombresonge a écrit a écrit : Kristoph:ESP n'est pas un registre d'indexe donc on est obligé de passer par EBP. Meme qd le resultat tient sur un int j'arrive pas à le recup dans EAX. J'ai l'impression que c passer par pile aussi |
As tu seulement essayé d'utiliser [ESP+4] ? Depuis le 386 on peut utiliser pratiquement n'importe quel registre comme registre d'indirection, et même faire des truc plus sioux encore.
Marsh Posté le 01-12-2002 à 17:02:28
EBP est le "frame" pointer pour les compilos C/C++, en fait les "anciens" compilos n'étaient pas capable de maintenir/réévaluer l'offset des paramètres dans la pile au fur et à mesure que des données/structures étaint "alloués" sur la pile.....
ils faisaient donc un truc style:
func:
push ebp
mov ebp,esp
push eax
mov eax,[ebp+....] ;// accès à un paramètre
...
sub esp,16 ;// allocation de 4 longs
...
mov DWORD PTR[esp],edx ;// copie d'un registre dans un long "alloué"
...
pop eax
pop ebp
ret
alors que maintenant les compilos savent tout faire par esp...
Marsh Posté le 01-12-2002 à 17:06:57
Autant que je me souvienne, il doit etre possible de faire des trucs de ce genre sur 386
MOV EAX,[ESP+8*EBX]
Alors se limiter à EBX
Marsh Posté le 05-12-2002 à 03:37:18
bjone a écrit a écrit : EBP est le "frame" pointer pour les compilos C/C++, en fait les "anciens" compilos n'étaient pas capable de maintenir/réévaluer l'offset des paramètres dans la pile au fur et à mesure que des données/structures étaint "alloués" sur la pile..... ils faisaient donc un truc style: func: push ebp mov ebp,esp push eax mov eax,[ebp+....] ;// accès à un paramètre ... sub esp,16 ;// allocation de 4 longs ... mov DWORD PTR[esp],edx ;// copie d'un registre dans un long "alloué" ... pop eax pop ebp ret alors que maintenant les compilos savent tout faire par esp... |
Oui, mais le nom meme ebp viens de sa fonction primaire :
ebp = Base Pointer
esp = Stack pointer ( eip c'est pour ca que ca me fait marrer )
Donc forcement
De plus, vous utilisez gcc sous linux, il vous pondera un joli
push %ebp
movl %ebp, %esp
du plus bel effet
Marsh Posté le 05-12-2002 à 11:03:29
au lieu de transmettre la valeur de ta variable à l'ASM tu passse la référence mémoire de ta variable.
et pares tu écris directement depuis l'assembleur dans ton adresse memoire.
Marsh Posté le 01-12-2002 à 01:51:53
Voilà j'ai envie de faire un programe C qui utiliserait des fonction que j'aurai ecrit et compilé avec un assembleur séparer (MASM par exemple). Le problème c que je vois pas comment faire au nivo des noms des procédures.
En gros j'ai envie de faire un truc dans ce gout là:
Programme en C:
Programme en asm:
Mais ça, ça marche pas j'ai une erreur au nivo de l'édition de lien. Ca me dit que f est introuvable
Donc si quelqu'un sait comment faire ca ca m'aiderait pas mal.
NB: me dite pas d'utiliser l'assembleur inline c pas possible pour des raison de portabilité entre autre
Message édité par sombresonge le 01-12-2002 à 01:54:40