Fonction DLL avec arguments

cs_Arnotic Messages postés 933 Date d'inscription dimanche 1 avril 2001 Statut Membre Dernière intervention 9 janvier 2012 - 13 mars 2003 à 11:45
littlefl Messages postés 21 Date d'inscription lundi 10 mars 2003 Statut Membre Dernière intervention 2 juillet 2003 - 14 mars 2003 à 13:23
Bonjour,

J'ai une DLL avec une fonction qui prend 2 arguments (en C (char*, int).

Lorsque je la charge j'ai aucun problème mais lors de l'appel à la fonction ca plante :

mov myda, "test"
mov lgda, 4
invoke GetProcAddress,hDLL,ADDR FuncWrite
mov lpWriteData, eax
push lgda
push myda
call lpWriteData

Alors qu'une fonction sans argument j'arrive très bien à la faire fonctionner :/

Merci de votre aide.

------------------------------------------
Arnotic
Mail : info@mistersp.com

12 réponses

filter Messages postés 42 Date d'inscription mercredi 8 janvier 2003 Statut Membre Dernière intervention 16 mai 2003
13 mars 2003 à 12:48
> Bonjour,
Bonjour,

> J'ai une DLL avec une fonction qui prend 2 arguments (en C (char*, int).
1 argument POINTEUR.

> mov myda, "test"
> mov lgda, 4
Comment sont reserve lgda et myda????

> push lgda
> push myda
Faux. Je suppose que t'utilise le syntax de MASM, (sinon, precise lequel.). Alors essai plutot

push offset myda
0
cs_Arnotic Messages postés 933 Date d'inscription dimanche 1 avril 2001 Statut Membre Dernière intervention 9 janvier 2012
13 mars 2003 à 13:07
salut,

merci de ton aide
je déclare :
LOCAL lgda:WORD
LOCAL myda:DWORD

oui effectivement j'utilise masm 8.

------------------------------------------
Arnotic
Mail : info@mistersp.com
0
littlefl Messages postés 21 Date d'inscription lundi 10 mars 2003 Statut Membre Dernière intervention 2 juillet 2003
13 mars 2003 à 17:46
Bonjour, je connais un peu l'ASM et je pense que dans ton cas (Arnotic), on ne peut pas faire un push offset myda parce-que myda est local donc on doit faire :
lea eax,myda
push eax

Mais sinon, tu devrais mettre les [] autour des noms des variables, ça serait plus clair je pense.
0
filter Messages postés 42 Date d'inscription mercredi 8 janvier 2003 Statut Membre Dernière intervention 16 mai 2003
13 mars 2003 à 19:14
>>on ne peut pas faire un push offset myda parce-que myda est
>>local donc on doit faire :
>> lea eax,myda
>> push eax
>

Absolument, vrai. OFFSET s'applique seulement aux variables globals, vu qu'il utilise le debut du segment data comme point de repere. En meme temps les variables local sont sur le stack et on n'a aucun moyen de calculer leur address reel dans la memoire. LEA est la bonne instruction ici. Btw, ct ca la raison pour laquelle j'ai demande comment ils sont declares tes donnes.;oP

> Bonjour, je connais un peu l'ASM et je pense que dans ton cas
>>(Arnotic),
Bonjour,
Tu connais pas si peu d'asm. J'ai vu des "grands specs" qui ignorent des details de ce genre;oP
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
cs_Arnotic Messages postés 933 Date d'inscription dimanche 1 avril 2001 Statut Membre Dernière intervention 9 janvier 2012
13 mars 2003 à 19:45
ok,
j'ai mis ca sa plante plus sauf que les paramèetre ne sont pas transmi
mov eax, "test"
mov bx, 4
push eax
push bx
call lpWriteData
?

------------------------------------------
Arnotic
Mail : info@mistersp.com
0
littlefl Messages postés 21 Date d'inscription lundi 10 mars 2003 Statut Membre Dernière intervention 2 juillet 2003
13 mars 2003 à 21:17
> ok,
> j'ai mis ca sa plante plus sauf que les paramèetre ne sont pas transmi
> mov eax, "test"
> mov bx, 4
> push eax
> push bx
> call lpWriteData

Arf, alors déjà ce n'est pas MOV mais LEA. Bon après voici la liste des choses que je pense ne pas être bonnes (corrige moi Filter si je me trompe ;p) :
- MOV BX, 4 est inutile, il vaut mieux écrire PUSH 4
- En ASM 80x86, tous les types supérieurs au BYTE sont stockés de manière inversée en mémoire, donc faire MOV DWORD PTR [<var>],"<str>" est une mauvaise solution car 1. ça n'inclue pas le zéro terminal pour une SZ (ce qui n'ets aps le acs ici mais autant le rappeler ;) et 2. ça va le stocker à l'envers (enfin je crois).
- En général, les chaînes se déclarent globales.
- Met l'opérateur d'indexage, c'est bcp plus lisible ! Et comme ça des programmeur NASM pourront te venir en aide car sous NASM, l'assembleur exige la présence des [].
- Met l'opérateur de taille (enfin je connais aps son nom, si qqun sait ?) je veux dire <size> PTR comme DWORD PTR ou BYTE PTR. C'est également plus lisible et là aussi les utilisateurs de NASM pourront te lire ^^.
- Evite les registres 16 bits qd ton code est en 32 bits car même si tu gagnes 1 word dans une instruction comme
MOV <reg16>, tu les perds avec des instructions comme PUSH BX (1 byte de perdu puisque génération du préfixe de changement de taille d'opérande).

Bon, voilà un exemple non testé d'un code qui appel une fonction C (la syntaxe C ets celle de BC++/VC++ et la syntaxe ASM est celle de MASM.

/* test.c */

__declspec( dllexport ) void print( char *_string, unsigned _length ) {
/* implémentation */
}

; test.asm

.data
_string db "test"

_print$ = -4
test proc near

; chargement de la DLL, je ne vasi aps détailler, tu sais faire

; _print$ est le pointeur sur la fonction
push 4
push offset _string
call near ptr _print$[ebp]
add esp, 8

Filter : Je ne sais pas qui sont tes grands specialistes mais ils sont quelque peu newbie si je puis me permettre ;p.
Enfin, disons que cela relève plus de la connaissance de MASM que de la connaissance de l'ASM. Comme quoi, il vaut mieux ne pas abuser de la syntaxe "simpliste" (simplifiée diront certains ;) de MASM sous peine de ne plus savoir ce que l'on fait ^^.
0
cs_Arnotic Messages postés 933 Date d'inscription dimanche 1 avril 2001 Statut Membre Dernière intervention 9 janvier 2012
13 mars 2003 à 21:57
merci pour toutes ses explications mais malheureusement lorsque je lance le programme j'ai un msg de windows me disant que le prog est planté :/

arf, je comprend vraiment, surtout que les fonctions paramètre ca passe niquel :/
------------------------------------------
Arnotic
Mail : info@mistersp.com
0
filter Messages postés 42 Date d'inscription mercredi 8 janvier 2003 Statut Membre Dernière intervention 16 mai 2003
13 mars 2003 à 22:02
> - MOV BX, 4 est inutile, il vaut mieux écrire PUSH 4
Je n'utilise pas MASM et je ne suis pas tres sur mais en gas on fais pushl, et si je me trompe pas l'instruction correspondant en MASM c pushd, alors au lieu de:
push 4
je ferrais
pushd 4
Meme, si en mode 32 bits, la valeur sur le stack est DWORD par defaut.

> - En général, les chaînes se déclarent globales.
On peut meme dire. TOUJOURS les chaines se declarent globales;o)

> - Evite les registres 16 bits qd ton code est en 32 bits car même si tu gagnes 1 word dans une instruction comme
> MOV <reg16>, tu les perds avec des instructions comme PUSH BX (1 byte de perdu puisque génération du préfixe de changement de taille d'opérande).

En plus, tt instruction 16 bit et plus lent a cause des penalties....

Arnotic, declare ton string LOCAL aSt[5]:BYTE
mets dedans 4 't''s avec un
"dec ecx
jnz"
Ajoute le 0 de la fin. (Tu devra utiliser, byte ptr 0).
En gros fait ton code du genre:
lea eax, aStr
mov ecx,4
FILLSTRING: mov [eax], byte ptr 't'
inc eax
loop FILLSTRING (ou dec + jnz ou n'importe koi.)
mov [eax], byte ptr 0
lea eax,aStr
pushd 24
pushd eax
call blablabla
Ouufff, j'en ai marre..... a plus si t'as tjs des problemes.....
0
littlefl Messages postés 21 Date d'inscription lundi 10 mars 2003 Statut Membre Dernière intervention 2 juillet 2003
13 mars 2003 à 22:57
-- avant tout, désolé pour l'orthographe et la grammaire déplorable de ce post car je suis légèrement endormi ;p --

Urg, là je ne sais pas trop... si ça concerne les paramètres, vérifie que tu ne te trompes pas de convention d'appel (c'est stupide mais ça arrive ;).
Pour rappel ,pour ceux qui ne le sauraient pas :
Les conventions (à l'appel) :
C :
on passe les arguments à l'envers et on clean the stack
STDCALL :
on passe les arguments à l'envers et on ne clean pas le stack
SYSCALL :
pareil que STDCALL
PASCAL :
on passe les args à l'endroit et on ne clean pas le stack
THISCALL (VC++ only) :
alors là, this se passe dans ECX et les autres arguments de droite à gauche et on ne clean pas le stack sauf si c une fonction a VARARG (quoique ds le cas où la fonction prend des args variables je ne sais plus, faudrait vérifier...)
FASTCALL (VC++) :
on passe les deux premiers args ds ECX et EDX et le reste à la manière d'un STDCALL et on ne clean pas le stack
FASTCALL (BC++) :
pareil que le FASTCALL de MS sauf que là on utilise EAX pour passer le premier argument, ECX le 2sd et EDX le troisième

Bon ce sont les principaux qd on programme en C/ASM (je ne connais que ces deux langages, enfin 3 avec le C++).

Voilà, donc si tu appelles une fonction C faudra aps oublier de nettoyer la pile, et si tu appelles une fonction STDCALL faudra surtt pas le nettoyer. Sinon, je ne vois vraiment pas, je n'ai aps pour habitude d'utiliser les DLLs en linkage dynamique donc Filter, je te laisse la parole, mon ptit niveau d'ASM s'arrête là ;).

Sinon, fais nous voir ta source en entier, ptet qu'on en saura plus. (je dis ça mais ça serait plutôt ptet que Filter en saura plus pk moi je crois que là... ;pp).

Dis, Filter, c'est quoi GAS ? Moi je connais que, et ce exclusivement sous win32, MASM, NASM, FASM, SPASM et la syntaxe K&R pour l'inclusion dans du C... Et personnellement je ne prog qu'avec MASM, NASM et avec du C + ASM inline. Même si la dernière fois que j'ai touché de l'ASM pur remonte à qq temps ;).
Sinon, sous MASM je crois que PUSHD existe mais ce n'est pas une instruction du proc donc vaut mieux aps l'utiliser, il vaut mieux faire PUSH DWORD PTR qui lui est une instruction du proc avec un opérande DWORD.
Pour les strings, sauf s'il veut faire MOV pour chaque lettre ;p.

Après, pour ton code, euh, je pense qu'il est préférable de mettre un saut conditionnel et pas un LOOP car c'ets plus rapide m'enfin c'est comme on le sent ;).
Pourquoi tu PUSH 24 ?? o.O la taille de la chaîne n'est-elle pas de 4 ? Et pour finir, au lieu de faire deux fois LEA pour charger l'adresse, tu devrais dès le début, PUSH sur la pile, les arguments (y compris EAX donc un LEA de moins) et après tu remplies la chaîne, comme FILLSTRING ne modifie pas la pile les args restent ;).

Bon, chui fatigué lol.
@+ littlefl
0
filter Messages postés 42 Date d'inscription mercredi 8 janvier 2003 Statut Membre Dernière intervention 16 mai 2003
14 mars 2003 à 10:47
>>Dis, Filter, c'est quoi GAS ? Moi je connais que, et ce
>>exclusivement sous win32, MASM, NASM, FASM, SPASM et la
>>syntaxe K&R pour l'inclusion dans du C... Et personnellement >> ne prog qu'avec MASM, NASM et avec du C + ASM inline.
>> Même si la dernière fois que j'ai touché de l'ASM pur remonte
>>à qq temps ;). Sinon, sous MASM je crois que PUSHD existe
>>mais ce n'est pas une instruction du proc donc vaut mieux aps
>>l'utiliser, il vaut mieux faire PUSH DWORD PTR qui lui est une
>>instruction du proc avec un opérande DWORD.
>>Pour les strings, sauf s'il veut faire MOV pour chaque lettre ;p.

GAS est l'assembeur AT & T syntax sur les systems Linux/Unix(ou AS parfois). C aussi le syntax qui est utiliser quand on ecrit inline avec GCC. Je ne suis pas habituer a l'asm sous win32(ce qui ne signifie pas que je l'ignore completement), parsk la plupart de temps c exactement inline avec GCC que j'utilise. Si tu utilise souvent ASM & C dans tes programmes, c beaucoup plus commode de s'habitue a le faire directement inline que d'ecrire c fichiers pur asm, les compile en code objet et faire un link avec les fichiers du C.....


>>Après, pour ton code, euh, je pense qu'il est préférable de
>>mettre un saut conditionnel et pas un LOOP car c'ets plus
>>rapide m'enfin c'est comme on le sent ;).

Bien sur que c + rapide.... (rien n'est _ rapide qu'un "dec ecx jnz"(1 cycle sur >PIII)(btw, il y avait un discussion recent sur comp.lang.asm.x86 a propos de la vitesse de "LOOP")... mais dans ce cas ca faisait deux instruction au lieu d'un, et j'avais pas trop envie d'ecrire

Pourquoi tu PUSH 24 ?? o.O la taille de la chaîne n'est-elle pas de 4 ?
>>Oui, je push un int comme ca, avec le meme effet je pouvais faire push 0x87665453, j'ai pas du tt dis que c le code a compile...;P En + il a pas dit que c la taille de la chaine ca peut bien etre son age, un entier > a 2 ou.....

>>Et pour finir, au lieu de faire deux fois LEA pour charger
>>l'adresse, tu devrais dès le début, PUSH sur la pile, les
>>arguments (y compris EAX donc un LEA de moins) et après
>>tu remplies la chaîne, comme FILLSTRING ne modifie pas la
>>pile les args restent ;).

Un facon de faire, sans doute....(oublie pas que c pas pour moi que j'ai ecris ce code....;P)

>>je n'ai aps pour habitude d'utiliser les DLLs en linkage
>>dynamique donc Filter, je te laisse la parole, mon ptit niveau
>>d'ASM s'arrête là ;).

Et moi sous Linux, j'utilise que des DLL's....lol....;o)..
0
cs_Arnotic Messages postés 933 Date d'inscription dimanche 1 avril 2001 Statut Membre Dernière intervention 9 janvier 2012
14 mars 2003 à 11:47
Super ! ! :)
Ca ne plante plus est la DLL me retourn 0 ! :)
Merci beacoup, par contre j'ai une dernière question à vous poser : comment faire pour créer une chaine que je push du type (en C) : sprintf(Commande, "%c%s%c%c%c", 01, "AT+START", 13, 10, 04); et en même temps récupérer le nombre de caractère de cette chaine pour l'envoyer aussi en paramètre.

Merci beaucoup pour votre aide j'ai beaucoup apris je vais m'inscrire en news group :)

encore merci
------------------------------------------
Arnotic
Mail : info@mistersp.com
0
littlefl Messages postés 21 Date d'inscription lundi 10 mars 2003 Statut Membre Dernière intervention 2 juillet 2003
14 mars 2003 à 13:23
Filter : Arf je devais vraiment être endormi hier lol, qd je disais K&R c'était AT&T lol. Bah si alors je connais la syntaxe mais pas GCC (puisque je ne prog pas sous Linux ;).
J'ai même jamais touché à Linux ;p.

Je vais te dire pkoi je ne prog pas en ASM inline ;). C'est tout bête, c'est que sous win32, les deux principaux compilos sont VC++ et BC++ (j'ai les deux en lignes de commande et C++Builder aussi). Mais alors le problème avec BC++ c'est qu'il faut posséder TASM (et je ne suis jamais arrivé à me procurer une version fonctionnelle, ou alors je ne suis jamais parvenu à faire marcher ça lol) ou un autre assembleur compatible TASM (càd aucun à moins de reécrire toutes les commandes propres à TASM avec le preprocesseur mais c'est long et chiant ;p). Et avec VC++, le compilateur gère l'ASM inline mais est tellement pourri (je le sais car j'ai longuement étudier le code ASM produit par les deux compilos avant d'en choisir un ;). Donc finallement, je me retrouve avec deux compilos qui ont chacun un gros défaut ! Pour les autres, je n'ai pas eu le courage de les tester, après avoir lu des sources ASM produites par les deux compilos pendant des heure ça m'a pas encouragé à reocmmencer ;).

Mais dis moi, tu connaîtrais pas une liste des instructions et des cycles sur des procs récents ? Parce-que moi j'ia jamais trouvé.

Euh, et aussi, sous Linux, ça marche comment pour les application et els librairies dynamiques ? (je suppose qu'ils n'utilisent pas le même format que sous win ;p)

Arnotic, j'ai pas bien compris ton problème (le dernier), Tu veux créer une chaîne de caractère comme on en crée avec la fonction sprintf du C ? Parce-que dans ce cas, c'est chaud lol, faut, soit écrire toi même la fonction et l'algo, soit utiliser la fonction de l'API win32 wsprintf() et ça fait un peu la même chose que sprintf().
0
Rejoignez-nous