Merci Ollivier de ta réponse.
J’avais déjà anticipé les remarques que tu fais. Et c’est pourquoi ma demande n’était pas claire.
Pour l’élégance de la programmation je préfère les formes explicites du type y=f(x) à la place des forme implicites f(x,y)=0
Elles permettent d’affecter immédiatement une valeur à une info, d’imbriquer les fonctions. Elles sont beaucoup plus souples et plus sûres d’emploi que les fonctions implicites et elles ressemblent aux instructions de PB.
Prenons l'exemple d'une addition sur une structure flottant étendu sur 80 bits interne à Intel.
Essayons de réaliser une addition de type X=A+B+C avec la forme implicite.
Avec cette forme et afin de ne pas alourdir ce post je prends la routine de conversion que j’ai placée dans le précédent post tout en fonction implicite. Ces routines sont extraites d’une de mes lib qui sont toutes en fonctions implicites.(environ 60 routines) Je ne suis pas rebuté par les pointeurs bien au contraire .mais l’imbrication des fonctions est impossible ce qui n’est pas le cas pour une fonction explicite.
Soit une fonction ADD(X,Y,Z) avec X premier paramètre comme résultat et avec pour objectif (X=A+B+C)
on a Add(X,A, Add(X,B,C) si l’écriture est possible, l’exécution est impossible puisque Add(X,B,C) ne sort qu’une valeur 0 ce qui provoque une erreur à l’exécution. On sera donc obligé pour l’opération X=A+B+C d’utiliser une variable intermédiaire Y qu’il faudra définir ou d’utiliser 2 fois la variable X.
De plus l’adresse du résultats est un paramètre que certains auteurs placent soit en premier soit en dernier .et les erreurs de syntaxe ne sont pas rares.(Il faut souvent faire référence à la documentation)
Tout ceci me parait lourd.
Alors pour éviter cette lourdeur j’ai essayé de sortir par adresse une fonction explicite ADD appelé ici lfadde
Exemple sur l’addition
Code : Tout sélectionner
Procedure.l lfadde(*y.lf,*z.lf);x=y+z
; Protected x.lf
Static x.lf
;****************************************************************************************************************
; Pour utiliser les infos Pb dans ASM suivant les différents cas observez les consignes suivantes
; ATTENTION RESPECTER la CASSE sinon erreur dans ASM
; ; Attention noninfo avec global v_nominfo
; ; Attention noninfo avec static s_nomprocedure.v_nominfo
; ; Attention noninfo avec protected p.v_nominfo
; ; Attention noninfo avec share v_nominfo
; ; Attention noninfo avec rien p.v_nominfo
; attention pour les pointeurs remplacer v_ par p_
;****************************************************************************************************************
FINIT
MOV ebx,*z
! fld tword [ebx]
FST st1
MOV ebx,*y
! fld tword [ebx]
FADD st0,st1
; MOV ebx,*x
! fstp tword [s_lfadde.v_x]
ProcedureReturn @x
EndProcedure
J’ai essayé d’utiliser l’option protected mais j’ai eu des pertes d’info que je n’ai pas trop approfondies c’est pourquoi j’utilise Static. .L’imbrication est possible mais il faut faire très attention à la priorité dans l’exécution les opérations et les écrasements de valeurs sont courantes car l’adresse est toujours la même
Il faut donc sauvegarder les résultats s’ils peuvent encore servir après chaque groupe d’opération
Avec par exemple copymemory(*source, *destination, longueur) mais cela est un peu lourd
L’exemple suivant le montre :
Code : Tout sélectionner
Structure ten
vq.q
vw.w
EndStructure
Structure lf
StructureUnion
fword.w[5]
tbyte.b[10]
vw.w[5]
vu.u[5]
vc.c[10]
vb.b[10]
vs${10}
vs.s{1}[10]
vt.ten
EndStructureUnion
EndStructure
ProcedureDLL.s _mh(*ad,lng)
For i=0 To lng-1
num.q=PeekC(*ad+i)
cart$=cart$+Chr(num)
hexs.s=hexs.s+RSet(Hex(num),2,"0")+" "
Next
; sort.s=RSet(Hex(*ad),8,"0")+" "+hexs+ " "+cart$
sort.s="$"+Hex(*ad)+" "+hexs+" "+cart$
ProcedureReturn sort
EndProcedure
Procedure lf2lf(*x.lf,*y.quad,typ.s="quad")
tp.s{1}=Mid(UCase(Trim(typ)),1,1)
FINIT
MOV ebx,*y
Select tp
Case "W" ;en 16 bits
FILD word[ebx]
Case "L" ; en 32 bits
FILD dword[ebx]
Case "I" ; en 32 bits
FILD dword[ebx]
Case "F" ; en float simple précision 32 bits
FLD dword[ebx]
Case "Q" ; en 64 bits
FILD qword[ebx]
Case "D" ; en 64 bits
FLD qword[ebx]
Case "T" ; en 80 bits
FLD tword[ebx]
EndSelect
MOV ebx,*x
FSTP tword[ebx]
EndProcedure
Procedure lfadd(*x.lf,*y.lf,*z.lf);x=y+z
FINIT
MOV ebx,*z
! fld tword [ebx]
FST st1
MOV ebx,*y
! fld tword [ebx]
FADD st0,st1
MOV ebx,*x
! fstp tword [ebx]
EndProcedure
Procedure.l lfadde(*y.lf,*z.lf);x=y+z
; Protected x.lf
Static x.lf
;****************************************************************************************************************
; Pour utiliser les infos Pb dans ASM suivant les différents cas observez les consignes suivantes
; ATTENTION RESPECTER la CASSE sinon erreur dans ASM
; ; Attention noninfo avec global v_nominfo
; ; Attention noninfo avec static s_nomprocedure.v_nominfo
; ; Attention noninfo avec protected p.v_nominfo
; ; Attention noninfo avec share v_nominfo
; ; Attention noninfo avec rien p.v_nominfo
; attention pour les pointeurs remplacer v_ par p_
;****************************************************************************************************************
FINIT
MOV ebx,*z
! fld tword [ebx]
FST st1
MOV ebx,*y
! fld tword [ebx]
FADD st0,st1
; MOV ebx,*x
! fstp tword [s_lfadde.v_x]
ProcedureReturn @x
EndProcedure
Procedure.s LF_DECOMPOS(*y.lf,SIG=0)
Define M.lf,md.d,E.w
!fninit ;
MOV ebx,*y
FLD tword[EBX]
!fxtract ;Extrait la Valeur de la Mantisse (st0) et l' Exponsant (st1) en base 2
!fstp qword[p.v_md] ;Mantisse
!fistp word [p.v_E] ;Exposant
expo$=Str(E)
mantd$=StrD(md,18)
ProcedureReturn mantd$+"*"+expo$+" ="+StrD(md*Pow(2,e))
EndProcedure
Define X.lf,A.lf,B.lf,C.lf,Y.lf,es.lf,*TE.lf,*XE.lf; pour fonction explicite
AD.D=12345.67E10
BD.D=14567.89E10
CD.D=00975.86E10
Debug lf2lf(@A,@AD,"D") ; résultat du debug dépend de la valeur du procedurereturn ici 0
lf2lf(@B,@BD,"D")
lf2lf(@C,@CD,"D")
Debug lfadd(@Y,@B,@C) ;; résultat du debug dépend de la valeur du procedurereturn ici 0
lfadd(@X,@Y,@A)
Debug _mh(@x,10)
;essai d'imbrication avec des fonctions implicites
; lfadd(@x,@A,lfadd(@X,@B,@C)) ; impossible d'imbriquer des fonctions implicites (Accès mémoire invalide erreur de lecture à l'adresse ..
Debug *xe
; en imbriquant les fonctions c'est nettement moins lourd
*xe=lfadde(lfadde(@A,@B),@c) ; ici cela fonctionne très bien mais on ne peut conserver le résultat sans le sauver car ...
Debug "********** val de *XE ***********"
Debug lf_decompos(*xe)
Debug _mh(*xe,10)
*YE=lfadde(@B,@A) ; fonction explicite avec passage par adresse
Debug "********** val de *YE ***********"
Debug lf_decompos(*YE)
Debug _mh(*Ye,10)
; mais que devient *XE? La valeur a été écrasée c'est normal puisque nous avons la même adresse pour *XE et *YE
Debug "********** val de *XE écrasé ***********"
Debug lf_decompos(*XE)
Debug _mh(*Xe,10)
En conclusion:
1) les fonctions implicites ne peuvent être imbriquées, ce qui alourdi la programmation
Leur mise en œuvre demande plus d’effort.
2) les fonctions explicites avec transfert du résultat par adresse peuvent être imbriquées en respectant les priorités, mais le résultat doit être sauvegardé avant d’utiliser à nouveau cette fonction, car la valeur précédente sera écrasée.
3) les fonctions explicites avec transfert par valeur sont les plus souples, les plus sûres et les plus faciles à mettre en œuvre. J’attends donc cette possibilité pour des zones >8 bytes et pouvant comporter $00 au moins en sortie(*1) de fonction
car en entrée je n'ai pas étudié le cas. Mais si cela pouvait être fait ce serait le TOP
Je pense au contraire que cette contrainte est nécessaire. Maintenant, je n'en ai pas la preuve.
Je me suis aussi posé cette question.
Tout d’abord j’ai montré dans le premier post que pour passer une chaîne libre et bien que le programmeur utilise le passage par valeur en sortie c’est une adresse qui est passée. Donc toutes les fonctions string seront bien limitées par $00. et les opérations sur cette chaîne donnent les mêmes résultats corrects
Par contre ce que je demande c’est la modification de la routine de copie des chaînes FIXE " _SYS_AssignFixedString@8" que j’ai trouvé à la sortie de la routine pour assigner la valeur à la variable externe à la routine et c’est la seule modification que je demande ce qui n’aurait aucune incidence sur les autres fonctions string puisque les fonctions string fonctionnent bien sur les chaînes libres qui ne sont limitées que par $00(*1).
J’ai réalisé des essais sur les chaînes FIXES (les libres fonctionnent très bien) mais je n’ai pas trouvé de bug (prg ici) donc la demande est réalisable.
Code : Tout sélectionner
; Conversion mémoire sortie Hexa
Procedure.s _mh(*ad,lng)
For i=0 To lng
num.c=PeekC(*ad+i)
cart$=cart$+Chr(num)
hexs.s=hexs.s+RSet(Hex(num),2,"0")+" "
Next
sort.s=RSet(Hex(*ad),8,"0")+" "+hexs+" "+cart$
ProcedureReturn sort
EndProcedure
; 1 2 3 4 5 6 7 8 9 10
; 1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
b.s{100}="12345678901234567890 purebasic est le meilleur langage purebasic est très bon 12345678901234567890 +"
; b.s{10}="1234567890"
Debug _mh(@b,100)
Gosub routinestr
LEA eax,dword[v_b]
XOR bx,bx
MOV[eax+50],bx
Debug "*********************** La chaine fixe a en position 50 $0000 *********************************"
Debug _mh(@b,50)
Debug _mh(@b+51,50)
Gosub routinestr
End
routinestr:
Debug " 1 2 3 4 5 6 7 8 9 10"
Debug "1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890"
Debug b +" long="+Str(Len(b))
Debug "CountString(B,'bon 1234567')="+Str(CountString(B,"bon 1234567"))
Debug "FindString(B,'purebasic',50)="+Str(FindString(B,"purebasic",50))
; Debug "InsertString(B,'FFFFF',50)="+Str(InsertString(B,"FFFFF",50))
Debug "RemoveString(B,'purebasic')="+RemoveString(B,"purebasic")
Debug "ReplaceString(B,'purebasic','PB',#PB_String_NoCase,50)="+ReplaceString(B,"purebasic","PB",#PB_String_NoCase,50)
Debug "ReverseString(B)="+ReverseString(B)
Debug "StringByteLength(B)="+Str(StringByteLength(B))
For i=1 To 15
Debug "StringField(B,i,' ') i="+Str(i)+" "+StringField(B,i," ")
Next
Debug "LCase(B)="+LCase(B)
Debug "RSet(B, 110 ,'_')="+ RSet(B, 110 ,"_")
Debug "LSet(B, 110,'_')="+ LSet(B,110,"_")
Debug "UCase(B)="+UCase(B)
Debug "Right(B, 60)="+Right(B,60)
Debug "Left(B, 60)="+ Left(B, 60)
Return
De toute manière ceci n’est pas de notre ressort mais de celui des concepteurs de PB qui doivent faire des essais.
Ceci fait aussi partie de la demande mais à priori il n'y a pas de problème.
(*1) la routine " _SYS_AssignFixedString" bien qu'elle connaisse la longueur de chaîne à copier s'arrête de copier lorsqu'elle
rencontre $00. Je demande simplement que cette routine copie tout ce qu'elle rencontre sur la longueur demandée.
A+