Page 1 sur 1

Casse tête Power Basic -> PB et ou C -> PB

Publié : mar. 18/janv./2005 23:28
par Marc
Je dois adapter un code Power Basic en PB mais je bute sur le code suivant:

------------------------------------------------------------------------
...
Declare Sub AddActionProcType(ByVal IDNum As Long, ByRef zName As Asciiz, ByRef Hint As Asciiz, ByRef Params As Asciiz) ', ByVal NumParams As Byte)
.
.
.
Sub xnbAddAction(ByVal IDNum As Long, zName As Asciiz, zHint As Asciiz, Params As Asciiz, ByVal NumParams As Byte)

' Do not edit. This is to match Delphi's calling conventions.
Asm push eax
Asm xor eax,eax
Asm mov al, NumParams
Asm push eax
Asm push eax

Call Dword nbAddAction Using AddActionProcType(IDNum, zName, zHint, Params)
Asm pop eax
End Sub

------------------------------------------------------------------------
Dans le call nbAddAction est une adresse de fonction connue

Mon code PB:

Procedure nbAddAction (IDNum.w,*Name,*HInt,*Params ,NumParams.b)
; -----------------------------Do Not Modify this function-------------------------------
PUSH eax
XOR eax,eax
MOV al,NumParams
PUSH eax
PUSH eax
CallFunctionFast(*xnbAddAction,IDNum,*Name,*HInt,*Params)
POP eax

EndProcedure

Celà ne fonctionne pas, c'est comme si le EndProcedure ne se fasait pas.

Version C qui fonctionne:

.
.
typedef void(__stdcall *AddActionProcType)(int IDNum,char* Name, char* Hint,char Params[]/*,BYTE NumParams*/);
.
.
.
void nbAddAction(int IDNum,char* Name, char* Hint,char Params[],BYTE NumParams){
/Do not edit. This is to match Delphi's calling conventions.
__asm{
push eax
xor eax,eax
mov al,NumParams
push eax
push eax
}
xnbAddAction(IDNum,Name,Hint,Params);
__asm pop eax;
}

C'est certainement une histoire de pile, mais là j'ai besoin d'un peu d'aide car je sèche depuis qques jours.

Merci

Publié : mer. 19/janv./2005 11:50
par Gillouz
Salut Marc,

Juste comme cela, en regardant le code vite fait.

Il me semble que ton problème vient du fait que l’adresse de retour de ta fonction n’est pas bonne, c’est pour cela que le endprocedure ne fonctionne pas, le registre EIP est envoyé aux pâquerettes.

Voyons cela plus en détail :

La fonction CallFunctionFast de purebasic prend en charge les arguments par rapport à la pile, l’appel de la fonction se fait par EAX, d’où le Fast. (JMP EAX)
Dans ton code tu poses les arguments sur la pile avec une série de push, puis tu appels la fonction CallFunctionFast en lui proposant de nouveaux arguments qu’elle va s’empresser de mettre sur la pile aussi.

Du coup tu as deux fois tes arguments sur la pile (ce n’est pas vraiment exact car il y a un décalage), lors du endprocedure purebasic fait simplement un ret ??, ?? représente le nombre de DWORD à enlever de la pile, puis JMP ESP pour retourner au prog, tout cela dans le RET (<= pour novice en l’assembleur), le problème c’est que la pile n’est pas remise dans le même état qu’à l’appel de la procédure et l’adresse de retour n’est plus bonne.

Conclusion,
La solution la plus simple serait de faire comme ceci.

Procedure nbAddAction (a.l,b.l,c.l,d.l,e.l,f.l)

EndProcedure

!push 7
!push 6
!push 5
!push 9
!push 9
!push 9
Resultat = CallFunctionFast(@nbAddAction ())
End
C’est le nombre de paramètres passés à nbAddAction qui va déterminer la valeur du RET et tu auras une bonne adresse de retour, si c’est une fonction externe il faut savoir si c’est elle qui s’occupe de gérer la pile ou pas.

Bon, je ne dis pas que c’est la solution ni que je n’ai pas dis de conneries, seulement une piste sans conviction, à creuser.

Amicalement, Gillouz.

Je cherche toujours

Publié : mer. 19/janv./2005 22:33
par Marc
Merci pour tes explications et je vais continuer....

xnbAddAction est une fonction d'un programme ecrit en Delphi et fait partie d'un programme: NEOBOOK.

On peut ecrire des PlugIns pour Neobook et moi j'essais d'adapter un code de plugin ecrit en C et aussi un exemple écrit en Power Basic.

Flut et reflut, je dois pouvoir y arriver avec PureBasic.