- Pensez à lire les règles durant votre visite, il n'y en a pas beaucoup, mais encore faut-il les respecter .
- N’hésitez pas à faire des remarques et/ou suggestions sur le Forum, dans le but de l'améliorer et de rendre vos prochaines visites plus agréables.
- Vous pouvez regarder votre "panneau de l'utilisateur" afin de configurer vos préférences.
- Un passage par "l'utilisation du forum" est recommandé pour connaître les fonctionnalités du forum.
--- L’équipe FantasPic ---
Modérateur : mazertoc
Bien que cette directive ne soit certainement pas la plus utilisée, en ayant eu besoin récemment et ayant trébuché sur quelques difficultés, je tente de vous faire partager mon expérience.
Une description, plutôt sommaire est donnée dans l'aide :
- Menu de MPLAB Help/Topics...,
sélectionner MPASM Assembler
dans l'onglet développer Directives
et dans la liste sélectionner while (la dernière)
par exemple, à l'analyse de
Code : Tout sélectionner
variable V = 0
while V != .3
nop
nop
nop
V+=1
endw
l'assembleur va générer 9 nop comme en témoigne le fichier .lst généré :
Code : Tout sélectionner
MPASM 5.51 TESTMACROTEST3.ASM 6-19-2018 14:58:09 PAGE 9
LOC OBJECT CODE LINE SOURCE TEXT
VALUE
0000 00082 variable V = 0
00083 while V != .3
0008 0000 00084 nop
0009 0000 00085 nop
000A 0000 00086 nop
00000001 00087 V+=1
000B 0000 00084 nop
000C 0000 00085 nop
000D 0000 00086 nop
00000002 00087 V+=1
000E 0000 00084 nop
000F 0000 00085 nop
0010 0000 00086 nop
00000003 00087 V+=1
00088 endw
Imaginons que ce traitement, plutôt que d'être composé de trois nop peu utiles nécessite une boucle à répéter un certain nombre de fois, sept par exemple.
Le source suivant donne une idée de ce que ce pourrait être :
Code : Tout sélectionner
variable V = 0
movlw .7
movwf Cmpt1
while V != 3
; début de traitement
nop
Test1_1
; corps du traitement
nop
nop
decf Cmpt1,f
btfss STATUS,Z
goto Test1_1
; sortie du traitement
nop
V+=1
endw
L'assembleur déclare une erreur (deux fois)
Error[116] E:\DOCUMENTS DE JJ\MES PROJETS MPLAB\TEST-MACROSTEST\BYTE\V3\TESTMACROTEST3.ASM 89 : Address label duplicated or different in second pass (Test1_1)
On aurait pu s'y attendre, le préprocesseur de l'assembleur répétant trois fois le corps de la boucle while, il répété aussi l'étiquette Test1_1 d'où les deux erreurs.
Si on examine le fichier .lst généré :
Code : Tout sélectionner
MPASM 5.51 TESTMACROTEST3.ASM 6-19-2018 15:22:06 PAGE 10
LOC OBJECT CODE LINE SOURCE TEXT
VALUE
0000 00083 variable V = 0
0008 3007 00084 movlw .7
0009 00A2 00085 movwf Cmpt1
00086 while V != 3
00087 ; début de traitement
000A 0000 00088 nop
000B 00089 Test1_1
00091 ; corps du traitement
000B 0000 00092 nop
000C 0000 00093 nop
000D 0000 00097 nop
0011 03A2 00103 decf Cmpt1,f
0012 1D03 00104 btfss STATUS,Z
0013 280B 00105 goto Test1_1
00107 ; sortie du traitement
0014 0000 00108 nop
00000001 00109 V+=1
00087 ; début de traitement
0015 0000 00088 nop
Error[116] : Address label duplicated or different in second pass (Test1_1)
0016 00089 Test1_1
00091 ; corps du traitement
0016 0000 00092 nop
0017 0000 00093 nop
0018 0000 00097 nop
001C 03A2 00103 decf Cmpt1,f
001D 1D03 00104 btfss STATUS,Z
001E 280B 00105 goto Test1_1
00107 ; sortie du traitement
001F 0000 00108 nop
00000002 00109 V+=1
00087 ; début de traitement
0020 0000 00088 nop
Error[116] : Address label duplicated or different in second pass (Test1_1)
0021 00089 Test1_1
00091 ; corps du traitement
0021 0000 00092 nop
0022 0000 00093 nop
0023 0000 00097 nop
0027 03A2 00103 decf Cmpt1,f
0028 1D03 00104 btfss STATUS,Z
0029 280B 00105 goto Test1_1
00107 ; sortie du traitement
002A 0000 00108 nop
00000003 00109 V+=1
00110 endw
On constate que l'assembleur généré en 001E un 280B alors qu'on espérait un 2816 et en 0029 un 280B alors qu'on attendait un 2821. Il garde la première valeur attribuée à Test1_1, ce qui n'est pas scandaleux. De toute façon, pas de .hex généré, il faut donc modifier le source.
J'avais vu une directive "local" (voir dans l'aide) qui, bien qu'elle soit présentée comme permettant de manipuler des variables locales à une macro correspondait bien à la situation. Je tente ma chance
Code : Tout sélectionner
variable V = 0
movlw .7
movwf Cmpt1
while V != 3
; début de traitement
nop
local Test1_1=$
; corps du traitement
nop
nop
nop
decf Cmpt1,f
btfss STATUS,Z
goto Test1_1
; sortie du traitement
nop
V+=1
endw
Plus d'erreur, voici le .lst généré :
Code : Tout sélectionner
MPASM 5.51 TESTMACROTEST3.ASM 6-19-2018 15:22:06 PAGE 10
LOC OBJECT CODE LINE SOURCE TEXT
VALUE
0000 00083 variable V = 0
0008 3007 00084 movlw .7
0009 00A2 00085 movwf Cmpt1
00086 while V != 3
00087 ; début de traitement
000A 0000 00088 nop
000B 00089 local Test1_1=$
00091 ; corps du traitement
000B 0000 00092 nop
000C 0000 00093 nop
000D 0000 00097 nop
0011 03A2 00103 decf Cmpt1,f
0012 1D03 00104 btfss STATUS,Z
0013 280B 00105 goto Test1_1
00107 ; sortie du traitement
0014 0000 00108 nop
00000001 00109 V+=1
00087 ; début de traitement
0015 0000 00088 nop
0016 00089 local Test1_1=$
00091 ; corps du traitement
0016 0000 00092 nop
0017 0000 00093 nop
0018 0000 00097 nop
001C 03A2 00103 decf Cmpt1,f
001D 1D03 00104 btfss STATUS,Z
001E 2816 00105 goto Test1_1
00107 ; sortie du traitement
001F 0000 00108 nop
00000002 00109 V+=1
00087 ; début de traitement
0020 0000 00088 nop
0021 00089 local Test1_1=$
00091 ; corps du traitement
0021 0000 00092 nop
0022 0000 00093 nop
0023 0000 00097 nop
0027 03A2 00103 decf Cmpt1,f
0028 1D03 00104 btfss STATUS,Z
0029 2821 00105 goto Test1_1
00107 ; sortie du traitement
002A 0000 00108 nop
00000003 00109 V+=1
00110 endw
On peut observer que les goto génèrent le code attendu. Bonne intuition.
Cependant, il est loin d'être rare que l'on ne soit pas amené à sauter à l’occurrence suivante de la boucle sans traiter ses dernières instructions par exemple :
Code : Tout sélectionner
variable V = 0
movlw .7
movwf Cmpt1
while V != 3
; début de traitement
nop
local Test1_1=$
; corps du traitement
nop
nop
goto Test1_2
nop
Test1_2
decf Cmpt1,f
btfss STATUS,Z
goto Test1_1
; sortie du traitement
nop
V+=1
endw
Inutile même de lancer un assemblage, il est clair que Test1_2 sera définie plusieurs fois
Essayons la manipe précédente en remplaçant l'étiquette Test1_2 par local Test1_2 = $. On obtient une erreur :
Error[113] E:\DOCUMENTS DE JJ\MES PROJETS MPLAB\TEST-MACROSTEST\BYTE\V3\TESTMACROTEST3.ASM 94 : Symbol not previously defined (Test1_2)
En fait c'est assez normal, quand on imagine la boucle while développée, son corps est recopié 3 fois successivement, dans la première copie, l'étiquette Test1_2 n'a pas été rencontrée d'où l'erreur
Essayons de tromper l'assembleur en lui faisant générer une première version du corps de boucle qui ne contiendra que l'étiquette
Code : Tout sélectionner
variable V = 0xffffffff
movlw .7
movwf Cmpt1
while V != .3 || V==0xffffffff
; début de traitement
nop
local Test1_1=$
; corps du traitement
if V!= 0xffffffff
nop
nop
goto Test1_2
nop
nop
nop
endif
local Test1_2 = $
nop
decf Cmpt1,f
btfss STATUS,Z
goto Test1_1
; sortie du traitement
nop
V+=1
endw
Une seule remarque sur ce code, remarquez l'initialisation de V à 0xFFFFFFFF, en effet, V est une variable 32 bits, je ne sais pas où c'est mentionné dans l'aide. J'ai essayé 0xFF et 0x FFFF qui, bien sûr, incrémentés ne donnent pas 0 sur 32 bits et du coup, pour atteindre 3, on dépasse de beaucoup le nombre de 256, maximum de répétition d'une boucle while.
Examinons le .lst généré :
Code : Tout sélectionner
MPASM 5.51 TESTMACROTEST3.ASM 6-19-2018 16:51:35 PAGE 10
LOC OBJECT CODE LINE SOURCE TEXT
VALUE
FFFF 00083 variable V = 0xffffffff
0008 3007 00084 movlw .7
0009 00A2 00085 movwf Cmpt1
00086 while V != .3 || V==0xffffffff
00087 ; début de traitement
000A 0000 00088 nop
000B 00089 local Test1_1=$
00090 ; corps du traitement
00091 if V!= 0xffffffff
00092 nop
00093 nop
00094 goto Test1_2
00095 nop
00096 nop
00097 nop
00098 endif
000B 00099 local Test1_2 = $
000B 0000 00100 nop
000C 03A2 00101 decf Cmpt1,f
000D 1D03 00102 btfss STATUS,Z
000E 280B 00103 goto Test1_1
00104 ; sortie du traitement
000F 0000 00105 nop
00000000 00106 V+=1
00087 ; début de traitement
0010 0000 00088 nop
0011 00089 local Test1_1=$
00090 ; corps du traitement
00091 if V!= 0xffffffff
0011 0000 00092 nop
0012 0000 00093 nop
0013 280B 00094 goto Test1_2
0014 0000 00095 nop
0015 0000 00096 nop
0016 0000 00097 nop
00098 endif
0017 00099 local Test1_2 = $
0017 0000 00100 nop
0018 03A2 00101 decf Cmpt1,f
0019 1D03 00102 btfss STATUS,Z
001A 2811 00103 goto Test1_1
00104 ; sortie du traitement
001B 0000 00105 nop
00000001 00106 V+=1
00087 ; début de traitement
001C 0000 00088 nop
001D 00089 local Test1_1=$
00090 ; corps du traitement
00091 if V!= 0xffffffff
001D 0000 00092 nop
001E 0000 00093 nop
001F 2817 00094 goto Test1_2
0020 0000 00095 nop
0021 0000 00096 nop
0022 0000 00097 nop
00098 endif
0023 00099 local Test1_2 = $
0023 0000 00100 nop
0024 03A2 00101 decf Cmpt1,f
0025 1D03 00102 btfss STATUS,Z
0026 281D 00103 goto Test1_1
00104 ; sortie du traitement
0027 0000 00105 nop
00000002 00106 V+=1
00087 ; début de traitement
0028 0000 00088 nop
0029 00089 local Test1_1=$
00090 ; corps du traitement
00091 if V!= 0xffffffff
0029 0000 00092 nop
002A 0000 00093 nop
002B 2823 00094 goto Test1_2
002C 0000 00095 nop
002D 0000 00096 nop
002E 0000 00097 nop
00098 endif
002F 00099 local Test1_2 = $
002F 0000 00100 nop
0030 03A2 00101 decf Cmpt1,f
0031 1D03 00102 btfss STATUS,Z
0032 2829 00103 goto Test1_1
00104 ; sortie du traitement
0033 0000 00105 nop
00000003 00106 V+=1
00107 endw
première remarque, en 0013 on trouve 280B ; le premier goto Test1_2 renvoie en arrière, première occurrence de l'étiquette Test1_1 rencontrée, on aurait préféré trouver 2817, c'est en fait ce qu'on avait cru écrire. Dans cet exemple précis, cela n'a pas d'importance puisque les instructions sont les mêmes aux deux adresses, cependant, cela nous a obligé de conserver les instructions de décrémentation du compteur Cmpt1, il y a donc lieu de lui donner une valeur initiale de 8 au lieu de 7.
On constate que ce type de traitement tient beaucoup de l'équilibriste. Une solution beaucoup plus simple est de se passer d'étiquette grâce à l'opérateur $, toutes mes excuses à ceux qui ne l'aiment pas (dont je suis).
Code : Tout sélectionner
variable V = 0
movlw .7
movwf Cmpt1
while V != .3
; début de traitement
nop
local Test1_1=$
; corps du traitement
nop
nop
goto $+4 ; Test1_2
nop
nop
nop
nop
decf Cmpt1,f
btfss STATUS,Z
goto Test1_1
; sortie du traitement
nop
V+=1
endw
Encore faut-il qu'on soit en mesure de calculer le déplacement à ajouter au $ et qu'il ne dépende pas de V, donc de l’occurrence de la boucle while !
Cordialement.
Retourner vers « Langage ASM »
Qui est en ligne
Utilisateurs parcourant ce forum : Aucun utilisateur enregistré et 55 invités