Bonjour à tous.
Je ne sais si cette étude doit être placée ici. Vous pouvez la déplacer.
Je cherche à améliorer un algorithme de tri stable et rapide, pour permettre des ordres de tri de toute table à 1 dimension de structure complexe sur plusieurs zones sans pour autant détruire le tri relatif précédemment réalisé, exemple tri par insertion.
Avec un module généralisé qui puisse accepter toute table à 1 dimension de structure aussi complexe que vous le désirez.
Comme les algos de tri sont connus depuis longtemps le tri par insertion se trouve être l’un des tris stables les plus rapides.
Il me reste, compte tenu de la complexité de la structure que je ne connais pas puisque l’utilisateur (programmeur) peut utiliser toute structure, de trouver un swap mémoire généralisé .pour les échanges pendant la commande de tri. (Il faut déplacer toute une entité d’indice x de la structure complexe vers un indice y<>x).
J’ai d’abord utilisé PB et ensuite ASM
En PB comme en ASM il existe 3 méthodes de base pour échanger 2 zones de mémoire élémentaire soit mem1 et mem2 2 zones élémentaires de type connu
1) méthode avec une mémoire supplémentaire.
memtemp=mem1
mem1=mem2
mem2=memtemp
2) méthode avec XOR ou ! comme opérateur
mem1 ! mem2 ;; dans mem1 ou exclusif de mem1 et mem2
mem2 ! mem1 ;; dans mem2 on retrouve mem1
mem1 ! mem2 ;; enfin dans mem1 on retrouve mem2
Code : Tout sélectionner
mem1.q=$789ABCDE
mem2.q=$FEDCBA98
Debug Hex(mem1)+" "+Hex(mem2)
mem1 ! mem2
; Debug Hex(mem1)+" "+Hex(mem2)
mem2 ! mem1
; Debug Hex(mem1)+" "+Hex(mem2)
mem1 ! mem2
Debug Hex(mem1)+" "+Hex(mem2)
Debug " c'est OK"
swap mem1, mem2
Voici le prg de comparaison en PB
Code : Tout sélectionner
ProcedureDLL.q _nbcs()
; ; ; L'instruction RDTSC est un mnémonique pour ReaD Time Stamp Counter.
; ; ; L'instruction retourne dans le couple de registre EDX:EAX le nombre de ticks1 écoulés depuis la dernière remise à zéro du processeur
; ; ; (Reset).
!RDTSC
ProcedureReturn
EndProcedure
Macro _q_t_
"
EndMacro
Macro _n(__n)
_q_t_#__n#=_q_t_+Str(__n)+" "
EndMacro
Macro _s(__S)
_q_t_#__S#=_q_t_+__S+" "
EndMacro
Macro _NL
"N°L="+Str(#PB_Compiler_Line)+" ** "
EndMacro
maxi=100000
maxi=maxi & $FFFFFFFE ; ;; force la variable maxi à être paire
; Nombre pair pour voir l'échange entre mem1 et mem2 la boucle for démarrant à 0 réalise une itération de plus
; alors que la boucle loop xxx réalise le nombre exact d'itération
mem1.l=1234567890
mem2.l=987654321
mes1$=_n(mem1)+_n(mem2)+#LF$
debo.q=_nbcs()
For i=0 To maxi
Next
delta.q=_nbcs()-debo
deb.Q=_nbcs()
For i=0 To MAXI
Swap mem1, mem2
Next
fin.q=_nbcs()
mes1$+_n(mem1)+_n(mem2)+#LF$
debm.q=_nbcs()
For i=0 To maxi
memtemp.q=mem1
mem1=mem2
mem2=memtemp
Next
finm.q=_nbcs()
mes1$+" av xor "+_n(mem1)+_n(mem2)+#LF$
debx.q=_nbcs()
For i=0 To maxi
mem1 ! mem2
mem2 ! mem1
mem1 ! mem2
Next
finx.q=_nbcs()
mes1$+" ap xor "+_n(mem1)+_n(mem2)+#LF$
mes1$+_n(mem1)+_n(mem2)+#LF$
mes1$+" NB cycles SWAP ="+_n(fin-deb-delta)+#LF$
mes1$+" Nb cycles MOV ="+_n(finm-debm-delta)+#LF$
mes1$+" Nb cycles XOR ="+_n(finx-debx-delta)+#LF$
MessageRequester("essaicycle machine",mes1$)
Mise en œuvre de ces méthodes avec une structure de table complexe.
Je présente ci-dessous 3 prg en PB
Swapcopy méthode de la mémoire supplémentaire la plus simple mais aussi la plus lente.
swapPB méthode avec swap en mode récursif
swapPBN méthode avec swap en mode itératif
et dans un premier temps un PRG asm avec les mêmes références que pour PB c'est-à-dire en prenant XCHG reg,[mem] comme méthode d’échange
La méthode XOR n’est pas présentée ici car plus lente que le swap (vous pouvez remplacer dans le PRG swappb Swap x,y par
X ! y
Y !x
X ! y
Regardez le résultat.
Code : Tout sélectionner
Macro _q_t_
"
EndMacro
Macro _n(__n)
_q_t_#__n#=_q_t_+Str(__n)+" "
EndMacro
Macro _s(__S)
_q_t_#__S#=_q_t_+__S+" "
EndMacro
Macro _NL
"N°L=" + Str(#PB_Compiler_Line) + " ** "
EndMacro
Procedure SWAPCOPY(*ADR1,*ADR2,LONG)
Static *mem
If flag=0
; *mem=AllocateMemory(Long,#PB_Memory_NoClear)
*mem=AllocateMemory(long*4) ; vous pouvez auglmenter cette valeur
flag=1
EndIf
CopyMemory(*ADR1,*Mem,Long)
CopyMemory(*ADR2,*ADR1,Long)
CopyMemory(*Mem,*ADR2,Long)
EndProcedure
Structure Brack
StructureUnion
Va.a[0]
Vw.b[0]
Vi.i[0]
Vl.l[0]
Vq.q[0]
Vs8.s{8}[0]
vs.s{131072}; vous pouvez augmentez cette valeur
EndStructureUnion
EndStructure
Procedure SWAPPB(*ADR1.brack,*ADR2.brack,LONG)
Static flag=0
Protected Restd.l,QDIV.l
If flag=0
CompilerIf #PB_Compiler_Unicode=1:;;;Egal 1 si l'exécutable est compilé en mode unicode, égal 0 sinon.
CompilerError "Il faut passer en ASCII pas en UNICODE, désolé."
CompilerEndIf
flag=1
EndIf
restd=long
Select LONG
Case 0
ProcedureReturn
Case 1,2,3
Qdiv=LONG
; RESTD=LONG
For i=0 To QDIV-1
Swap *ADR1\Va[i],*adr2\Va[i]
RESTD-1
Next
ProcedureReturn RESTD
Case 4,5,6,7
; Qdiv=LONG/4
; RESTD=LONG
Swap *ADR1\Vl[0],*ADR2\Vl[0]
RESTD-4
If restd>0
SWAPPB(@*ADR1\Vl[1],@*ADR2\Vl[1],restd)
Else
ProcedureReturn restd
EndIf
Default
Qdiv=LONG/8
; RESTD=LONG
For i=0 To QDIV-1
Swap *ADR1\Vq[i],*ADR2\Vq[i]
RESTD-8
Next
If restd>0
SWAPPB(@*ADR1\Vq[i],@*ADR2\Vq[i],restd)
Else
ProcedureReturn restd
EndIf
EndSelect
EndProcedure
;
Procedure SWAPPBN(*ADR1.brack,*ADR2.brack,LONG)
Static flag=0
Protected Restd.l,QDIV.l
If flag=0
CompilerIf #PB_Compiler_Unicode=1:;;;Egal 1 si l'exécutable est compilé en mode unicode, égal 0 sinon.
CompilerError "Il faut passer en ASCII pas en UNICODE, désolé."
CompilerEndIf
flag=1
EndIf
restd=LONG
iq=0
While restd>0
Select restd
Case 0
ProcedureReturn restd
Case 1,2,3
ia=long-restd
While restd>0
Swap *ADR1\Va[ia],*ADR2\Va[ia]
ia+1
RESTD-1
Wend
Case 4,5,6,7
il=iq*2
Swap *ADR1\Vl[il],*ADR2\Vl[il]
restd-4
Default
While restd>7
Swap *ADR1\Vq[iq],*ADR2\Vq[iq]
RESTD-8
iq+1
Wend
EndSelect
Wend
ProcedureReturn restd
EndProcedure
Procedure SwapASMEX(*adr1,*adr2,long);; PRG PAPIPP avec option ! sur toutes les instructions
; Debug _h(rreax)+_h(rrebx)+_h(rrecx)+_h(rredx)+_h(rresi)+_h(rredi)+_h(rresp)+_h(rrebp)
Protected REBX,RESI,REDI,RECX
; EnableASM
!MOV esi,[p.p_adr1]
!MOV edi,[p.p_adr2]
!MOV ecx,[p.v_long]
!SHR ecx,2
!JE SwapASMEX_BclFin1
!SwapASMEX_BclDep1:
!MOV eax,[esi+ecx*4-4]
!xchg eax,[edi+ecx*4-4]
!MOV [esi+ecx*4-4],eax
!DEC ecx
!JNZ SwapASMEX_BclDep1
; LOOP SwapASMEX_BclDep1 ; cette instruction ralentit un peu le prg
!SwapASMEX_BclFin1:
; swap du reste de la division long/4
!MOV ecx,[p.v_long]
!ADD esi,ecx
!ADD edi,ecx
!AND ecx,3
!JE SwapASMEX_BclFin2
!SUB esi,ecx
!SUB edi,ecx
!SwapASMEX_BclDep2:
!MOV al,[esi+ecx-1]
; !MOV dl,[edi+ecx-1]
; !MOV [esi+ecx-1],dl
; !MOV [edi+ecx-1],al
!XCHG al,[edi+ecx-1];;;;;; Allonge le temps de 3 cycles machine pour chaque appel par rapport aux 4 instructions précédentes
!MOV[esi+ecx-1],al ;;;;;; 3instructions en commentaire
!DEC ecx
!JNZ SwapASMEX_BclDep2
;
; LOOP SwapASMEX_BclDep2; cette instruction ralentit un peu le prg
;
!SwapASMEX_BclFin2:
; DisableASM
EndProcedure
Procedure SwapASMXO(*adr1,*adr2,long);; PRG PAPIPP avec option ! sur toutes les instructions
; Debug _h(rreax)+_h(rrebx)+_h(rrecx)+_h(rredx)+_h(rresi)+_h(rredi)+_h(rresp)+_h(rrebp)
Protected REBX,RESI,REDI,RECX
; EnableASM
!MOV esi,[p.p_adr1]
!MOV edi,[p.p_adr2]
!MOV ecx,[p.v_long]
!SHR ecx,2
!JE SwapASMXO_BclFin1
!SwapASMXO_BclDep1:
!MOV eax,[esi+ecx*4-4]
!XOR eax,[edi+ecx*4-4]
!XOR [esi+ecx*4-4],eax
!XOR [edi+ecx*4-4],eax
!DEC ecx
!JNZ SwapASMXO_BclDep1
; LOOP SwapASMXO_BclDep1 ; cette instruction ralentit un peu le prg elle remplace DEC ... JNZ ...
!SwapASMXO_BclFin1:
; swap du reste de la division long/4
!MOV ecx,[p.v_long]
!ADD esi,ecx
!ADD edi,ecx
!AND ecx,3
!JE SwapASMXO_BclFin2
!SUB esi,ecx
!SUB edi,ecx
!SwapASMXO_BclDep2:
!MOV al,[esi+ecx-1]
!MOV dl,[edi+ecx-1]
!MOV [esi+ecx-1],dl
!MOV [edi+ecx-1],al
!DEC ecx
!JNZ SwapASMXO_BclDep2
;
; LOOP SwapASMXO_BclDep2 ;;cette instruction ralentit un peu le prg elle remplace DEC ... JNZ ...
;
!SwapASMXO_BclFin2:
; DisableASM
EndProcedure
Procedure SwapASM(*adr1,*adr2,long);; PRG PAPIPP avec option ! sur toutes les instructions
; Debug _h(rreax)+_h(rrebx)+_h(rrecx)+_h(rredx)+_h(rresi)+_h(rredi)+_h(rresp)+_h(rrebp)
Protected REBX,RESI,REDI,RECX
; EnableASM
!MOV esi,[p.p_adr1]
!MOV edi,[p.p_adr2]
!MOV ecx,[p.v_long]
!mov ebx,ecx
!SHR ecx,2
!JE SwapASM_BclFin1
!SwapASM_BclDep1:
!MOV eax,[esi+ecx*4-4]
!MOV edx,[edi+ecx*4-4]
!MOV[esi+ecx*4-4],edx
!MOV[edi+ecx*4-4],eax
!DEC ecx
!JNZ SwapASM_BclDep1
!SwapASM_BclFin1:
!MOV ecx,ebx
!AND ecx,3 ;;;; swap du reste de la division long/4
!JE SwapASM_BclFin2
!ADD esi,ebx
!ADD edi,ebx
!SUB esi,ecx
!SUB edi,ecx
!SwapASM_BclDep2:
!MOV al,[esi+ecx-1]
!MOV dl,[edi+ecx-1]
!MOV[esi+ecx-1],dl
!MOV[edi+ecx-1],al
!DEC ecx
!JNZ SwapASM_BclDep2
; LOOP SwapASM_BclDep2
;
!SwapASM_BclFin2:
; DisableASM
EndProcedure
Procedure SwapASMo(*adr1,*adr2,long);; PRG PAPIPP avec option ! sur toutes les instructions
!MOV esi,[p.p_adr1]
!MOV edi,[p.p_adr2]
!MOV ecx,[p.v_long]
!MOV ebx,ecx
!SHR ecx,2
!JE SwapASMo_BclFin1
!SwapASMo_BclDep1:
!mov eax,[esi]
!mov edx,[edi]
!mov [esi],edx
!mov [edi],eax
; !XCHG eax,[edi] ;;;;;; Allonge le temps de 3 cycles machine pour chaque appel par rapport aux 4 instructions précédentes
; !MOV[esi],eax
!ADD esi,4
!ADD edi,4
; !loop SwapASMo_BclDep1 ;;; Allonge le temps par rapport aux deux instructions suivantes
!DEC ecx
!JNZ SwapASMo_BclDep1
!SwapASMo_BclFin1:
; !MOV ecx,ebx
; !AND ecx,3
!and ebx,3
!JE SwapASMo_BclFin2
!mov ecx,ebx
!SwapASMo_BclDep2:
!mov al,[esi]
!mov dl,[edi]
!mov [esi],dl
!mov [edi],al
; !XCHG al,[edi];;;;;; Allonge le temps de 3 cycles machine pour chaque appel par rapport aux 4 instructions précédentes
; !MOV[esi],al
!INC esi
!INC edi
; !loop SwapASMo_BclDep2;;; Allonge le temps par rapport aux deux instructions suivantes
!DEC ecx
!JNZ SwapASMo_BclDep2
!SwapASMo_BclFin2:
EndProcedure
A1$="DuPont Jean Jacques Durand Jean Pierre Michel Martin______------_____-"
A2$="1234567890123456789012345678901234567890123456789012345678901234567890"
Long=Len(A1$)
*adr1=@A1$
*adr2=@A2$
MAXI=1000000
For longst=Len(A1$) To 8 Step -7
A1$=Left(A1$,longst)
A2$=Left(A2$,longst)
Long=Len(A1$)
;;;; ou ces 2 instructions
; long=longst
; *adr1+1
;
;
;;;; ****** Décommentez les lignes suivantes pour vérifier le bon fonctionnement des différents prg de swap
; Debug "SWAPCOPY(*ADR1,*ADR2,LONG)"+_n(long)+_n(long%8);+#LF$
; Debug _nl+_s(A2$)+"///"+_s(A1$)+_n(*adr1)+_n(*adr2)+_n(long)+_n(Len(A1$));+#LF$
; SWAPCOPY(*ADR1,*ADR2,LONG)
; Debug _NL+_s(A2$)+"///"+_s(A1$);+#LF$
; SWAPCOPY(*ADR1,*ADR2,LONG)
;
; Debug "SWAPPB(*ADR1,*ADR2,LONG)"+_n(long)+_n(long%8);+#LF$
; Debug _nl+_s(A2$)+"///"+_s(A1$)+_n(*adr1)+_n(*adr2)+_n(long)+_n(Len(A1$));+#LF$
; SWAPPB(*ADR1,*ADR2,LONG)
; Debug _NL+_s(A2$)+"///"+_s(A1$);+#LF$
; SWAPPB(*ADR1,*ADR2,LONG)
;
; Debug "SWAPPBN(*ADR1,*ADR2,LONG)"+_n(long)+_n(long%8);+#LF$
; Debug _nl+_s(A2$)+"///"+_s(A1$)+_n(*adr1)+_n(*adr2)+_n(long)+_n(Len(A1$));+#LF$
; SWAPPBN(*ADR1,*ADR2,LONG)
; Debug _NL+_s(A2$)+"///"+_s(A1$);+#LF$
; SWAPPBN(*ADR1,*ADR2,LONG)
;
; Debug "SWAPASMEX(*ADR1,*ADR2,LONG)"+_n(long)+_n(long%8);+#LF$
; Debug _nl+_s(A2$)+"///"+_s(A1$)+_n(*adr1)+_n(*adr2)+_n(long)+_n(Len(A1$));+#LF$
; SWAPASMEX(*ADR1,*ADR2,LONG)
; Debug _NL+_s(A2$)+"///"+_s(A1$);+#LF$
; SWAPASMEX(*ADR1,*ADR2,LONG)
;
; Debug "SWAPASMXO(*ADR1,*ADR2,LONG)"+_n(long)+_n(long%8);+#LF$
; Debug _nl+_s(A2$)+"///"+_s(A1$)+_n(*adr1)+_n(*adr2)+_n(long)+_n(Len(A1$));+#LF$
; SWAPASMXO(*ADR1,*ADR2,LONG)
; Debug _NL+_s(A2$)+"///"+_s(A1$);+#LF$
; SWAPASMXO(*ADR1,*ADR2,LONG)
;
; Debug "SWAPASM(*ADR1,*ADR2,LONG)"+_n(long)+_n(long%8);+#LF$
; Debug _nl+_s(A2$)+"///"+_s(A1$)+_n(*adr1)+_n(*adr2)+_n(long)+_n(Len(A1$));+#LF$
; SWAPASM(*ADR1,*ADR2,LONG)
; Debug _NL+_s(A2$)+"///"+_s(A1$);+#LF$
; SWAPASM(*ADR1,*ADR2,LONG)
;
; Debug "SWAPASMO(*ADR1,*ADR2,LONG)"+_n(long)+_n(long%8);+#LF$
; Debug _nl+_s(A2$)+"///"+_s(A1$)+_n(*adr1)+_n(*adr2)+_n(long)+_n(Len(A1$));+#LF$
; SWAPASMO(*ADR1,*ADR2,LONG)
; Debug _NL+_s(A2$)+"///"+_s(A1$);+#LF$
; SWAPASMO(*ADR1,*ADR2,LONG)
;
;
; Debug "*****************************************************************************************************************"
:
;;;; ***** Vous pouvez commentez les lignes suivantes en conservant la dernière ligne NEXT pour le contrôle des lignes précédentes
debut$=""
debut$+#LF$+#LF$+"***** SWAPCOPY(*ADR1,*ADR2,LONG)"+_n(long)+_n(Len(A1$))+_n(long%8)+#LF$
debut$+_s(A1$)+"///"+_s(A2$)+_n(*adr1)+_n(*adr2)+#LF$
time_d.q=ElapsedMilliseconds()
For i=0 To maxi
SWAPCOPY(*ADR1,*ADR2,LONG)
Next
debut$+_s(A1$)+"///"+_s(A2$)+#LF$+" temps en ms="+Str(ElapsedMilliseconds()-time_d)+" pour "+Str(i)+" itérations"+" longueur="+Str(long)
SWAPCOPY(*ADR1,*ADR2,LONG)
debut$+#LF$+#LF$+"***** SWAPPB(*ADR1,*ADR2,LONG)"+_n(long)+_n(Len(A1$))+_n(long%8)+#LF$
debut$+_s(A1$)+"///"+_s(A2$)+_n(*adr1)+_n(*adr2)+#LF$
time_d.q=ElapsedMilliseconds()
For i=0 To maxi
SWAPPB(*ADR1,*ADR2,LONG)
Next
debut$+_s(A1$)+"///"+_s(A2$)+#LF$+" temps en ms="+Str(ElapsedMilliseconds()-time_d)+" pour "+Str(i)+" itérations"+" longueur="+Str(long)
SWAPPB(*ADR1,*ADR2,LONG)
debut$+#LF$+#LF$+"***** SWAPPBN(*ADR1,*ADR2,LONG)"+_n(long)+_n(Len(A1$))+_n(long%8)+#LF$
debut$+_s(A1$)+"///"+_s(A2$)+_n(*adr1)+_n(*adr2)+#LF$
time_d.q=ElapsedMilliseconds()
For i=0 To maxi
SWAPPBN(*ADR1,*ADR2,LONG)
Next
debut$+_s(A1$)+"///"+_s(A2$)+#LF$+" temps en ms="+Str(ElapsedMilliseconds()-time_d)+" pour "+Str(i)+" itérations"+" longueur="+Str(long)
SWAPPBN(*ADR1,*ADR2,LONG)
debut$+#LF$+#LF$+"***** SWAPASMEX(*ADR1,*ADR2,LONG)"+_n(long)+_n(Len(A1$))+_n(long%8)+#LF$
debut$+_s(A1$)+"///"+_s(A2$)+_n(*adr1)+_n(*adr2)+#LF$
time_d.q=ElapsedMilliseconds()
For i=0 To maxi
SWAPASMEX(*ADR1,*ADR2,LONG)
Next
debut$+_s(A1$)+"///"+_s(A2$)+#LF$+" temps en ms="+Str(ElapsedMilliseconds()-time_d)+" pour "+Str(i)+" itérations"+" longueur="+Str(long)
SWAPASMEX(*ADR1,*ADR2,LONG)
;;;;;************************************************************************************
;;; **** Commentez la ligne suivante pour comparer tous les prg ASM ********************
;;;;;************************************************************************************
Goto fin_premier_essai
debut$+#LF$+#LF$+"***** SWAPASMXO(*ADR1,*ADR2,LONG)"+_n(long)+_n(Len(A1$))+_n(long%8)+#LF$
debut$+_s(A1$)+"///"+_s(A2$)+_n(*adr1)+_n(*adr2)+#LF$
time_d.q=ElapsedMilliseconds()
For i=0 To maxi
SWAPASMXO(*ADR1,*ADR2,LONG)
Next
debut$+_s(A1$)+"///"+_s(A2$)+#LF$+" temps en ms="+Str(ElapsedMilliseconds()-time_d)+" pour "+Str(i)+" itérations"+" longueur="+Str(long)
SWAPASMXO(*ADR1,*ADR2,LONG)
debut$+#LF$+#LF$+"***** SWAPASM(*ADR1,*ADR2,LONG)"+_n(long)+_n(Len(A1$))+_n(long%8)+#LF$
debut$+_s(A1$)+"///"+_s(A2$)+_n(*adr1)+_n(*adr2)+#LF$
time_d.q=ElapsedMilliseconds()
For i=0 To maxi
SWAPASM(*ADR1,*ADR2,LONG)
Next
debut$+_s(A1$)+"///"+_s(A2$)+#LF$+" temps en ms="+Str(ElapsedMilliseconds()-time_d)+" pour "+Str(i)+" itérations"+" longueur="+Str(long)
SWAPASM(*ADR1,*ADR2,LONG)
debut$+#LF$+#LF$+"***** SWAPASMO(*ADR1,*ADR2,LONG)"+_n(long)+_n(Len(A1$))+_n(long%8)+#LF$
debut$+_s(A1$)+"///"+_s(A2$)+_n(*adr1)+_n(*adr2)+#LF$
time_d.q=ElapsedMilliseconds()
For i=0 To maxi
SWAPASMO(*ADR1,*ADR2,LONG)
Next
debut$+_s(A1$)+"///"+_s(A2$)+#LF$+" temps en ms="+Str(ElapsedMilliseconds()-time_d)+" pour "+Str(i)+" itérations"+" longueur="+Str(long)
SWAPASMO(*ADR1,*ADR2,LONG)
fin_premier_essai:
MessageRequester("Essai 4 ou 7 programmes en SWAP",debut$)
;
Next
J’ai donc réalisé un autre test sur les commandes ASM
Code : Tout sélectionner
ProcedureDLL.q _nbcs()
; ; L'instruction RDTSC est un mnémonique pour ReaD Time Stamp Counter.
; ; L'instruction retourne dans le couple de registre EDX:EAX le nombre de ticks1 écoulés depuis la dernière remise à zéro du processeur
; ; (Reset).
!RDTSC
ProcedureReturn
EndProcedure
Macro _q_t_
"
EndMacro
Macro _n(__n)
_q_t_#__n#=_q_t_+Str(__n)+" "
EndMacro
Macro _s(__S)
_q_t_#__S#=_q_t_+__S+" "
EndMacro
Macro _NL
"N°L="+Str(#PB_Compiler_Line)+" ** "
EndMacro
maxi=1000
maxi=maxi | $00000001
; Nombre impair pour voir l'échange entre mem1 et mem2 la boucle loop xxx réalise le nombre exact d'itération
; alors que for démarrant à 0 réalise une itération de plus
mem1.l=1234567890
mem2.l=987654321
mes1$=_n(mem1)+_n(mem2)+#LF$
debo.q=_nbcs()
EnableASM
MOV ecx,[v_maxi]
!ldebo:
LOOP ldebo
; DisableASM
delta.q=_nbcs()-debo
deb.Q=_nbcs()
; EnableASM
MOV ecx,[v_maxi]
!ldebxch:
MOV ebx,[v_mem1]
XCHG ebx,[v_mem2]
MOV[v_mem1],ebx
LOOP ldebxch
; DisableASM
fin.q=_nbcs()
mes1$+_n(mem1)+_n(mem2)+#LF$
debm.q=_nbcs()
; EnableASM
MOV ecx,[v_maxi]
!ldebmov:
MOV ebx,[v_mem1]
MOV edi,[v_mem2]
MOV[v_mem1],edi
MOV[v_mem2],ebx
LOOP ldebmov
; DisableASM
finm.q=_nbcs()
mes1$+" av xor "+_n(mem1)+_n(mem2)+#LF$
debx.q=_nbcs()
; EnableASM
MOV ecx,[v_maxi]
!ldebxor:
MOV ebx,[v_mem1]
XOR ebx,[v_mem2]
XOR[v_mem1],ebx
XOR[v_mem2],ebx
LOOP ldebxor
DisableASM
finx.q=_nbcs()
mes1$+" ap xor "+_n(mem1)+_n(mem2)+#LF$
mes1$+_n(mem1)+_n(mem2)+#LF$
mes1$+" NB cycles XCHG = "+_n(fin-deb-delta)+#LF$
mes1$+" Nb cycles MOV ="+_n(finm-debm-delta)+#LF$
mes1$+" Nb cycles XOR ="+_n(finx-debx-delta)+#LF$
MessageRequester("essaicycle machine",mes1$)
J’ai modifier le PRG ASM avec l’option MOV et l’option XOR
Voici donc 3 autres prg ASm optimisés que vous pouvez tester en commentant la ligne goto xxxx
A+