Moebius
J'ai testé aussi la solution avec une variable en datasection et ça fonctionne, c'est plus simple que de modifier la pile et le compteur interne de PB (PSO=..) qui peut évoluer (?) dans le code PB.
Là aussi je vais faire des tests avec au moins 2 ou 3 paramètres array pour voir comment ça se passe.
Je te tiens au courant.
- Progi1984
- Messages : 2659
- Inscription : mar. 14/déc./2004 13:56
- Localisation : France > Rennes
- Contact :

Je te laisse faire pour me donner la meilleure solution. Le développement ne me gène tant que cela apporte de la facilité coté utilisateur.
Merci de ton aide

Site Web : https://rootslabs.net
- Progi1984
- Messages : 2659
- Inscription : mar. 14/déc./2004 13:56
- Localisation : France > Rennes
- Contact :
J'aime bien ce concept car comme tu le dis toi-même, cela reste transparent pour l'utilisateur. J'attends de tes newsDenis a écrit :Mon but est de laisser l'appel Purebasic avec en paramètre le tableau et pas une variable dont on passe l'adresse. Même si ça ajoute 3 ou 4 instructions asm, c'est mieux car de toute façon ces instructions existeront quand même lorsque l'on donnera l'adresse du tableau à la variable. C'est mieux en asm car c'est transparent pour l'utilisateur.

Site Web : https://rootslabs.net
- Progi1984
- Messages : 2659
- Inscription : mar. 14/déc./2004 13:56
- Localisation : France > Rennes
- Contact :
http://www.purebasic.fr/english/viewtopic.php?t=35956
Site Web : https://rootslabs.net
PSn correspond au décalage des variables locales (esp évolue) augmenté de la valeur des registres sauvegardés. Cette valeur sert à corriger le déplacement avec esp pour retrouver les paramètres.
Pour moi c'est constant confimé par Fred mais il me semble avoir vu du code asm avec PSn qui variait, peut-être ai-je rêvé (?)
Je vais faire encore quelques tests et te proposer 2 solutions. Une par la pile et une par une variable en datasection (ou plusieurs selon le nombre de paramètres array()).
- Progi1984
- Messages : 2659
- Inscription : mar. 14/déc./2004 13:56
- Localisation : France > Rennes
- Contact :
J'attends tes propositions. Merci beaucoup de ton aide.
Site Web : https://rootslabs.net
Ces modifs n'entrainent pas de modification de ton fichier descripteur.
Pour commencer , je vais rappeler comment sont empilés les paramètres lors de l'appel d'une fonction en StdCall.
On prend un exemple avec 2 paramètres de type long
Code : Tout sélectionner
Fonction(Param1.l, Param2.l)
On empile
Param2
On empile
Param1
Puis l'adresse de retour de la procédure va être empilée.
Lorsque l'on est sur la 1ere instruction de la procédure, le registre esp pointe l'adresse de retour, schématiquement c'est comme ça (la représentation est à l'envers car lorsque l'on empile un élément, esp décroit, c'est juste une représentation).
Code : Tout sélectionner
_____________
| |
| xxxx | <-- ESP pointe l'adresse ou est stocké l'adresse de retour
|_____________| (4 octets)
| |
| xxxx | <-- à ESP + 4 on a le 1er paramètre
|_____________|
| |
| xxxx | <-- à ESP + 8 on a le 2eme paramètre
|_____________|
Après la dernière instruction asm PB (qui est un RET avec une valeur après comme RET 4), on va écrire une Macro d'alignement et écrire la datasection avec notre ou nos variable's) utilisée(s) pour corriger.
Il y a autant de variables (Long) que de paramètres Array.
Le principe :
On crée une variable en DataSection, c'est une variable globale mais qui n'est connue que de la Procedure, elle n'est pas public.
Le code asm ajouté charge dans le registre edx (registre volatile donc utilisable sans problème) la valeur du paramètre Array qui est réellement l'adresse du tableau.
Puis on écrit dans la variable en DataSection, cette valeur.
Ensuite, le paramètre correspondant au tableau est modifié pour recevoir l'adresse de la variable en datasection.
Tout ça est fait en 3 instructions.
Voici un exemple pour le code PB suivant :
Code : Tout sélectionner
ProcedureDLL S08_GetVarL(Num.l, Array MyArrayL.l(1))
ProcedureReturn MyArrayL(Num)
EndProcedure
Dans l'exemple, le paramètre est à la position 2 (2eme paramètre).
Dans ce cas, le déplacement à ajouter à esp pour retomber sur le 2eme paramètre vaut +8. Je mettrais la formule pour calculer cet offset un peu après.
D'ou les instructions asm suivantes en considérant que la variable en datasection s'appelle
Code : Tout sélectionner
_Pt_Tableau_1
Code : Tout sélectionner
Offset = 8 ; notre décalage à ajouter à esp
; on charge dans edx la valeur du 2eme paramètre
MOV edx, dword [esp+Offset]
; on écrit la valeur dans notre variable
MOV dword [_Pt_Tableau_1], edx
; on modifie le paramètre en y écrivant l'adresse de la variable en datasection
MOV dword [esp+Offset], _Pt_Tableau_1
Un élément que je n'ai pas évoqué c'est la taille des paramètres.
tous les paramètres ont un taille de 4 octets sauf les paramètres quad et les double. Les byte, word etc sont passés comme des paramètres ayant une taille de 4 octets.
Pour calculer l'offset, il faut avoir la position du paramètre tableau et la taille des paramètres qui précèdent.
Voilà sous forme de If / EndIf comment calculer
Position vaut la position du paramètre Array
offset est la valeur à trouver
Code : Tout sélectionner
offset = 0
If position = 1
offset = 4
Else
For i = 1 To (position-1)
offset + SizeOf(parametre(i))
Next i
offset + 4
EndIf
L'adresse _Pt_Tableau_1 évoluera pour chaque paramètre en modifiant le 1 en 2 pour le 2eme tableau, en 3 pour le 3eme tableau, c'est pas très difficile.
Code : Tout sélectionner
_Pt_Tableau_1
_Pt_Tableau_2 ; 2eme tableau
_Pt_Tableau_3 ; 3eme tableau
_Pt_Tableau_n ; n ieme tableau
Voilà exactement le code:
Code : Tout sélectionner
Macro align value { rb (value-1) - ($-_S08_GetVarL + value-1) mod value }
Et maintenant voici la datasection pour un seul tableau en paramètre, datasection qui est en lecture/écriture.
Il y a une première étiquette que je viens d'expliquer, elle est utilisée par la macro
Il y a ensuite l'appel de la macro d'alignement sur 32 bits (=4 octets)
Il y a ensuite l'étiquette
Code : Tout sélectionner
_Pt_Tableau_1:
Le code de la datasection précédée de la macro devient :
Code : Tout sélectionner
Macro align value { rb (value-1) - ($-_S08_GetVarL + value-1) mod value }
section '.Tableau' readable writeable
_S08_GetVarL:
align 4
_Pt_Tableau_1:
rd 1
Code : Tout sélectionner
section '.Tableau' readable writeable
_S08_GetVarL:
align 4
_Pt_Tableau_1:
rd 1
_Pt_Tableau_2:
rd 1
_Pt_Tableau_3:
rd 1
J'arrête là pour les explications, je vais poster ce soir un ou deux exemples avec le code asm modifié.
Code PB
Code : Tout sélectionner
ProcedureDLL S08_GetVarL(Num.l, Array MyArrayL.l(1))
ProcedureReturn MyArrayL(Num)
EndProcedure
Code : Tout sélectionner
format MS COFF
public PB_S08_GetVarL
_Procedure0:
PB_S08_GetVarL:
PUSH ebp
PUSH ebx
PS0=16
XOR eax,eax
PUSH eax
MOV eax,dword [esp+PS0+4]
MOV dword [esp+0],eax
MOV ebx,dword [esp+PS0+0]
MOV edx,[esp+0]
MOV ebp,dword [edx]
SAL ebx,2
MOV eax,dword [ebp+ebx]
JMP _EndProcedure1
XOR eax,eax
_EndProcedure1:
ADD esp,4
POP ebx
POP ebp
RET 8
Voici le code asm modifié:
Le code modifié est compilable
Code : Tout sélectionner
format MS COFF
public PB_S08_GetVarL
_Procedure0:
PB_S08_GetVarL:
;////////////////////////////////////////////////
; Code PB de la fonction
; ProcedureDLL S08_GetVarL(Num.l, Array MyArrayL.l(1))
; ProcedureReturn MyArrayL(Num)
; EndProcedure
; calcul de l'offset
;offset = 0
;If position = 1
; offset = 4
;Else
; For i = 1 To (position-1)
; offset + SizeOf(parametre(i))
; Next i
; offset + 4
;EndIf
; Position = 2
; Le calcul à la main donne 8
Offset = 8
MOV edx, dword [esp+Offset]
; on écrit la valeur
MOV dword [_Pt_Tableau_1], edx
MOV dword [esp+Offset], _Pt_Tableau_1
;////////////////////////////////////////////////
PUSH ebp
PUSH ebx
PS0=16
XOR eax,eax
PUSH eax
MOV eax,dword [esp+PS0+4]
MOV dword [esp+0],eax
MOV ebx,dword [esp+PS0+0]
MOV edx,[esp+0]
MOV ebp,dword [edx]
SAL ebx,2
MOV eax,dword [ebp+ebx]
JMP _EndProcedure1
XOR eax,eax
_EndProcedure1:
ADD esp,4
POP ebx
POP ebp
RET 8
;////////////////////////////////////////////////
Macro align value { rb (value-1) - ($-_S08_GetVarL + value-1) mod value }
section '.Tableau' readable writeable
_S08_GetVarL:
align 4
_Pt_Tableau_1:
rd 1
;////////////////////////////////////////////////
Code : Tout sélectionner
Dim AnyArrayL.l(11)
For i = 0 To 10
AnyArrayL(i) = i*10
Next
For i = 0 To 10
Debug S08_GetVarL(i, AnyArrayL())
Next
3 tableaux en paramètres
Code PB
Code : Tout sélectionner
ProcedureDLL S08_GetVarL_2(Array MyArrayL.l(1), Num.l, Array MyArrayL_1.l(1), Array MyArray_2_L.l(1))
ProcedureReturn MyArrayL(Num) + MyArrayL_1(Num) + MyArray_2_L.l(Num)
EndProcedure
Code : Tout sélectionner
format MS COFF
public PB_S08_GetVarL_2
_Procedure4:
PB_S08_GetVarL_2:
PUSH ebp
PUSH ebx
PUSH edi
PS4=28
XOR eax,eax
PUSH eax
PUSH eax
PUSH eax
MOV eax,dword [esp+PS4+0]
MOV dword [esp+0],eax
MOV eax,dword [esp+PS4+8]
MOV dword [esp+4],eax
MOV eax,dword [esp+PS4+12]
MOV dword [esp+8],eax
MOV ebx,dword [esp+PS4+4]
MOV edx,[esp+0]
MOV ebp,dword [edx]
SAL ebx,2
MOV ebx,dword [ebp+ebx]
MOV edi,dword [esp+PS4+4]
MOV edx,[esp+4]
MOV ebp,dword [edx]
SAL edi,2
ADD ebx,dword [ebp+edi]
MOV edi,dword [esp+PS4+4]
MOV edx,[esp+8]
MOV ebp,dword [edx]
SAL edi,2
ADD ebx,dword [ebp+edi]
MOV eax,ebx
JMP _EndProcedure5
XOR eax,eax
_EndProcedure5:
ADD esp,12
POP edi
POP ebx
POP ebp
RET 16
Voici le code asm modifié:
Le code modifié est compilable
Code : Tout sélectionner
format MS COFF
public PB_S08_GetVarL_2
_Procedure4:
PB_S08_GetVarL_2:
;////////////////////////////////////////////////
; Code PB de la fonction
; ProcedureDLL S08_GetVarL_2(Array MyArrayL.l(1), Num.l, Array MyArrayL_1.l(1), Array MyArray_2_L.l(1))
; ProcedureReturn MyArrayL(Num) + MyArrayL_1(Num) + MyArray_2_L.l(Num)
; EndProcedure
; calcul de l'offset du premier tableau
;--------------------------------------
;offset = 0
;If position = 1
; offset = 4
;Else
; For i = 1 To (position-1)
; offset + SizeOf(parametre(i))
; Next i
; offset + 4
;EndIf
; Position = 1
; Le calcul à la main donne 4
Offset = 4
MOV edx, dword [esp+Offset]
; on écrit la valeur
MOV dword [_Pt_Tableau_1], edx
MOV dword [esp+Offset], _Pt_Tableau_1
;
; Fin des instructions pour le premier tableau
;--------------------------------------
; calcul de l'offset du second tableau
;--------------------------------------
; Position = 3
; Taille du 1er paramètre 4 et taille du second 4 octets
; Le calcul à la main donne 12
Offset = 12
MOV edx, dword [esp+Offset]
; on écrit la valeur
MOV dword [_Pt_Tableau_2], edx
MOV dword [esp+Offset], _Pt_Tableau_2
;
; Fin des instructions pour le second tableau
;--------------------------------------
; calcul de l'offset du troisième tableau
;--------------------------------------
; Position = 4
; Taille du 1er paramètre 4, taille du second 4 et taille du 3eme 4 octets
; Le calcul à la main donne 16
Offset = 16
MOV edx, dword [esp+Offset]
; on écrit la valeur
MOV dword [_Pt_Tableau_3], edx
MOV dword [esp+Offset], _Pt_Tableau_3
;
; Fin des instructions pour le troisième tableau
;--------------------------------------
;////////////////////////////////////////////////
PUSH ebp
PUSH ebx
PUSH edi
PS4=28
XOR eax,eax
PUSH eax
PUSH eax
PUSH eax
MOV eax,dword [esp+PS4+0]
MOV dword [esp+0],eax
MOV eax,dword [esp+PS4+8]
MOV dword [esp+4],eax
MOV eax,dword [esp+PS4+12]
MOV dword [esp+8],eax
MOV ebx,dword [esp+PS4+4]
MOV edx,[esp+0]
MOV ebp,dword [edx]
SAL ebx,2
MOV ebx,dword [ebp+ebx]
MOV edi,dword [esp+PS4+4]
MOV edx,[esp+4]
MOV ebp,dword [edx]
SAL edi,2
ADD ebx,dword [ebp+edi]
MOV edi,dword [esp+PS4+4]
MOV edx,[esp+8]
MOV ebp,dword [edx]
SAL edi,2
ADD ebx,dword [ebp+edi]
MOV eax,ebx
JMP _EndProcedure5
XOR eax,eax
_EndProcedure5:
ADD esp,12
POP edi
POP ebx
POP ebp
RET 16
;////////////////////////////////////////////////
Macro align value { rb (value-1) - ($-_S08_GetVarL_2 + value-1) mod value }
section '.Tableau' readable writeable
_S08_GetVarL_2:
align 4
_Pt_Tableau_1:
rd 1
_Pt_Tableau_2:
rd 1
_Pt_Tableau_3:
rd 1
;////////////////////////////////////////////////
Code : Tout sélectionner
Dim AnyArrayL.l(11)
Dim AnyArrayL_1.l(11)
Dim AnyArrayL_2.l(11)
For i = 0 To 10
AnyArrayL(i) = i*10
AnyArrayL_1(i) = i*100
AnyArrayL_2(i) = i*5
Next
Debug ""
For i = 0 To 10
Debug S08_GetVarL_2(AnyArrayL(), i, AnyArrayL_1(), AnyArrayL_2())
Next
- Progi1984
- Messages : 2659
- Inscription : mar. 14/déc./2004 13:56
- Localisation : France > Rennes
- Contact :
Je ne sais pas si tu te rends compte mais tu es génial. Je viens de passer à peine une heure pour adapter tes explications à mon code et intégrer la notions de tableaux en paramètre.
Félicitations

@All :
Release de la 0.5 :
Code : Tout sélectionner
* ADDED : Parameter with default value
* ADDED : Parameter with type : linked list
* ADDED : Parameter with type : tables
* IMPROVED : Deleting of content of directories (!now : Deleting recursively main directory)
* IMPROVED : Clearing ASM Codes (a lot of newlines)
* IMPROVED : Step 2 : in first function, moving asm detection code to second function
* DONE : Tests with all Samples
Site Web : https://rootslabs.net
Faut pas exagérerProgi1984 a écrit :@Denis :
Je ne sais pas si tu te rends compte mais tu es génial. Je viens de passer à peine une heure pour adapter tes explications à mon code et intégrer la notions de tableaux en paramètre.

Je me demande qu'elles sont les limites en codage PB pour une librairie, le fait que Fred passe l'adresse du tableau au lieu d'un pointeur.
Pour ton exemple 08, voici ce que ça donne les modifs par la pile, il y a un peu plus de modifs et on doit modifier PSn.
Code asm d'origine:
Code : Tout sélectionner
format MS COFF
public PB_S08_GetVarL
_Procedure0:
PB_S08_GetVarL:
PUSH ebp
PUSH ebx
PS0=16
XOR eax,eax
PUSH eax
MOV eax,dword [esp+PS0+0]
MOV dword [esp+0],eax
MOV ebx,dword [esp+PS0+4]
MOV edx,[esp+0]
MOV ebp,dword [edx]
SAL ebx,2
MOV eax,dword [ebp+ebx]
JMP _EndProcedure1
XOR eax,eax
_EndProcedure1:
ADD esp,4
POP ebx
POP ebp
RET 8
Code : Tout sélectionner
format MS COFF
public PB_S08_GetVarL
_Procedure0:
PB_S08_GetVarL:
;////////////////////////////////////////////
; ajouté
; on met sur la pile la valeur passée en paramètre
; qui est l'adresse du tableau
PUSH dword [esp+4]
; on charge dans edx l'adresse de la pile ou l'on vient de mettre la valeur
LEA edx, [esp]
; on écrase le paramètre Tableau par l'adresse calculée dans edx
MOV dword [esp+8], edx
;////////////////////////////////////////////
PUSH ebp
PUSH ebx
;////////////////////////////////////////////
; on modifie PS0 (on ajoute 4 pour chaque parametre array)
PS0=16+4 ; PS0=16 --> + 4 car on a empilé un long sur 4 octets
;////////////////////////////////////////////
XOR eax,eax
PUSH eax
MOV eax,dword [esp+PS0+0]
MOV dword [esp+0],eax
MOV ebx,dword [esp+PS0+4]
MOV edx,[esp+0]
MOV ebp,dword [edx]
SAL ebx,2
MOV eax,dword [ebp+ebx]
JMP _EndProcedure1
XOR eax,eax
_EndProcedure1:
ADD esp,4
POP ebx
POP ebp
;////////////////////////////////////////////
; on ajuste le pointeur de pile
; la valeur à mettre dans esp est:
; nombre param array multiplié par 4
; ici 1 x 4 = 4
ADD esp,4
;////////////////////////////////////////////
RET 8
- Progi1984
- Messages : 2659
- Inscription : mar. 14/déc./2004 13:56
- Localisation : France > Rennes
- Contact :

Site Web : https://rootslabs.net
- Progi1984
- Messages : 2659
- Inscription : mar. 14/déc./2004 13:56
- Localisation : France > Rennes
- Contact :
Donc mieux vaut il que je laisse avec la modif par une variable en datasection ou que j'utilise par modif de la pile ?
Site Web : https://rootslabs.net