Esercitazioni
PIC - Assembly
|
Le direttive di MPASM
Le direttive (directives) appaiono simili alle istruzioni, ma
si tratta di "istruzioni" dirette al compilatore, in generale
indipendenti dal modello di microcontroller, e che hanno come
scopo il controllo della compilazione. Possiamo dividerle in vari tipi:
- direttive di controllo che permettono di realizzare sezioni di codice
assemblato secondo particolari condizioni
- direttive relative ai dati, che gestiscono l' allocazione in memoria e
provvedono ai riferimenti simbolici
- direttive di listato, che condizionano il formato del file .lst (spazi,
paginazione, titolo, ecc)
- macro direttive, che controllano l' esecuzione e l' allocazione dei dati
attraverso macro definizioni
- direttive relative al file oggetto, che ne permettono la creazione
In generale, le direttive:
- non possono iniziare in prima colonna, ad eccezione di #define
- supportano una label, ad eccezione di alcune, come glogal,
extern, ecc
- sono "parole riservate" e non possono essere usate altro
che per la loro funzione
Va notato che MPASM accetta i nomi delle direttive e degli opcodes sia
in maiuscolo che in minuscolo, quindi
END o end
e bsf o
BSF sono equivalenti.
L' uso del maiuscolo e del minuscolo fanno parte dello stile
personale del programmatore, anche se l' attenersi ad una qualche linea
guida è altrettanto utile dell' ordine formale del sorgente.
|
Per quanto riguarda il punto 1, va tenuto presente il limite della prima
colonna di testo, che l' Assembler considera rigorosamente, dato che la
posizione è determinante, ad esempio, per la dichiarazione di una label
durante la compilazione.
Nella prima colonna del testo sorgente possono iniziare i commenti, le label
che vengono in tal modo definite ed alcune direttive. Tutto il resto (opcodes,
label di macro e la gran parte delle direttive) NON può iniziare in prima
colonna, pena una segnalazione di errore del compilatore e l' impossibilità
di generare il codice oggetto.
Questa necessità fa si che la "forma" con cui è scritto il
sorgente sia meno che mai un mero fatto estetico. Si potranno usare uno spazio
(space) o più oppure una o più tabulazioni (tab) per separare gli elementi
in una riga o allontanarne l' inizio dalla prima colonna.
Per quanto riguarda il terzo punto, i nomi delle direttive e delle funzioni
dell' Assembler e gli mnemonici degli opcodes non possono essere usati per
altre funzioni. Così pure le label specificate nel file processore.inc
non possono essere usate se non per indicare quanto specificato. Questo è
evidente, dato che la stessa label non può essere duplicata con riferimento a
diversi valori.
Ricordiamo che la label è un simbolo che sottintende un valore esadecimale,
sia esso un indirizzo, un numero, la posizione di un bit in un registro, ecc.
Quindi ogni label deve essere univoca e se possono esistere label a cui è
attribuito uno steso valore, non possono esistere label uguali a cui sono
attribuiti valori diversi. Altrimenti come potrebbe il compilatore, che
trasforma le label in valori binari, eseguire correttamente il suo lavoro?
Molte direttive hanno la possibilità di accettare diverse forme del nome, per
mantenere la compatibilità con vecchie versioni dell' Assembler.
Le direttive di MPASM sono circa 56. Il già citato MPASM
User's Guide riporta queste direttive e le regole per il
loro uso.
Tra le direttive di uso comune, esistono alcune funzioni logiche per
condizionare la compilazione.
Ad esempi0:
#if
LCDLINENUM == 1 ; 1 line module - N=0
movlw LCD_1L
; low nibble b'0000' 1 line, 5x7
#else
; more lines module - N=1
movlw LCD_2L
; low nibble b'1000' 2 lines, 5x7
#endif
oppure
VARIABLE vCNT
; local variable
vCNT = LCDNIBBLE
; assign pre-defined constant
WHILE vCNT > 0x0
; perform loop to insert shift
rlncf LCDbuf1, w
; shift data to aligne w/ output pins
vCNT -= 1
ENDW
Ma è C? No, per nulla. Si tratta dell' uso delle direttive di controllo
che condizionano la compilazione.
Va compreso in modo molto chiaro che questi elementi logici riguardano
la compilazione e NON l' esecuzione del programma.
In questo senso i cicli if e while
hanno la stessa funzione logica che avrebbero in un sorgente C,
ma non agiscono creando funzioni che opereranno durante l' esecuzione
del programma, bensì agiscono solo ed esclusivamente durante la compilazione,
determinando le istruzioni che entreranno a far parte dell' oggetto.
|
Nel primo esempio, il senso è: se la variabile LCDLINENUM
è uguale a 1, il compilatore considererà la linea movlw
LCD_1L , altrimenti la
linea movlw LCD_2L.
Nel secondo caso, fino a che counter vCNT è
maggiore di 0, il compilatore inserirà istruzioni rlncf
LCDbuf1, w nell' eseguibile.
Un esempio più chiaro si potrà avere considerando questo impiego del
ciclo if-else-endif:
#ifdef ___18F13K22
LIST p=18F13K22
; Definizione del processore
#include <p18F13K22.inc>
#else
LIST p=18F14K22
; Definizione del processore
#include <p18F14K22.inc>
#endif
A seconda del processore definito, sarà compilato il
relativo set di riferimento.
|