Esercitazioni
PIC - Assembly
|
Opcodes
L' elemento fondamentale dell' Assembly è l' uso degli opcodes, ovvero
dei codici mnemonico del set di istruzioni tipiche del processore. Esistendo
diverse famiglie di processori a 8 bit (con core a 12/14/16 bit) e altre
famiglie con bus dati a 16 e 32 bit, i set di istruzioni saranno differenti,
ma, trattandosi di processori RISC, ci sarà comunque un numero limitato
di istruzioni da apprendere (da 33 a poco più di 70 per i PIC a 8 bit).
Potete trovare qui il set di istruzioni di:
- Baseline
- Midrange
- Enhaced Midrange
- PIC18F
Osserviamo che i codici delle istruzioni sono degli acronimi mnemonici,
ovvero delle abbreviazioni che cercano di ricordare all' utente la loro
funzione.
Ad esempio, se vogliamo portare a livello 1 un determinato bit di una
locazione di RAM, registro di controllo o port di I/O, i microcontroller PIC
dispongono di una istruzione specifica:
bsf
è mnemonico per bit set
on
file.
Per Microchip valgono le seguenti convenzioni:
set |
portare a livello 1 |
clear |
portare a livello 0 |
file |
registro, registro speciale (SFR), locazione RAM |
SFR |
Special File Register, i registri di controllo di I/O e
delle funzioni
integrate |
Quindi bsf -bit set on
file- comanda di portare a livello 1 il bit specificato nel file in
oggetto. Così:
bsf 20,3
dice al processore di portare a livello 1 il bit 3 del registro 20h.
Analogamente, per portare a 0 il bit, si userà l' opcode:
bcf
bit clear
on file, ovvero portare a livello 0 il bit specificato nel file in
oggetto. Così:
bcf 20,3
dice al processore di portare a livello clear = 0 nel registro 20h il bit 3.
- Una linea di opcode non può iniziare nella prima colonna
- Ogni opcode occupa una sola linea.
- La linea può essere
completata con un commento.
|
La
sintassi della linea che contiene una istruzione è:
spazio/tab |
opcode |
spazio/tab |
oggetto |
spazio/tab |
;commento
opzionale |
quindi:
spazio/tab |
bsf
|
spazio/tab |
6,5 |
spazio/tab |
;set
bit 5 del file 6 |
Lo spazio/tab iniziale serve ad evitare che l' opcode inizi in prima
colonna, posizione riservata dall' Assembler a label, commenti e ad alcune
direttive.
In questo caso, l' oggetto è
composto dall' indirizzo del registro (file) [6],
separato da una virgola dal bit [5]
a cui è diretta l' istruzione.
Nella sintassi dell' Assembly, la virgola è un elemento di
separazione e concatenazione tra diversi elementi di una stessa
operazione. |
Ogni opcode presenta caratteristiche proprio e troviamo opcode con e senza
oggetto. Ad esempio:
nop
;questo opcode non ha oggetto
return
;anche questo non ha oggetto
retlw 0
;questo
ha come oggetto 0
movlw
0xFF ;l'oggetto è FFh
;la linea successiva non ha commento
btfsc
4,7
Da notare che non ci sono regole particolari per gli spazi, che possono
essere anche creati con TAB; il loro uso adeguato consente di allineare
ordinatamente gli elementi delle righe in modo da rendere il più facile
possibile la lettura del testo. In questo senso, una forma ordinata è
assolutamente fondamentale per una facile comprensione di quanto scritto e per
poter intervenire efficientemente in fase di debug. Ad esempio, una scrittura
del genere:
nop
;questo opcode non ha oggetto
return
;anche questo non ha oggetto
retlw 0 ;questo
ha come oggetto 0
movlw
0xFF ;l'oggetto è FFh
;la linea successiva non ha commento
btfsc
4,7
pur essendo identica come risultato di compilazione alla precedente, il suo
disordine la rende molto meno comprensibile. Peraltro, l'omissione di commenti
rende ancor più incomprensibile il sorgente.
La conoscenza del set di istruzioni consente di utilizzarle adeguatamente,
compresi gli effetti "collaterali" sui flag dello STATUS.
Gli esempi presentati sono tipiche di linee di un sorgente Assembly per microcontroller
PIC, dove vengono inserite le istruzioni, gli oggetti delle stesse ed
eventuali commenti esplicativi.
In effetti Assembly, come base, non è altro che un modo per utilizzare mnemonici (opcodes)
al posto dei valori binari delle istruzioni native del processore.
Da notare che, trattando opcodes, un Assembly è relativo a una
famiglia specifica di microprocessori o microcontroller.
La filosofia secondo
la quale è stato realizzato un certo chip può essere assai diversa da quella
usata da un altro costruttore. Quindi ogni prodotto (ARM, PIC, ST6, Z80, 8051,
ecc) ha un suo proprio Assembly, basato sul proprio set di istruzioni: ne risulta che
un sorgente Assembly scritto per un tipo di processore non è portabile su un' altro.
Dove occorre una conversione completa del programma da un processore ad
un' altro differente, la cosa può essere anche difficoltosa. E' come
se ogni processore parlasse una sua propria "lingua" e il passaggio
dall' una all' altra richiede una vera e propria traduzione.
Nel casso in cui si rimanga nella stessa famiglia (ad esempio portare
un programma da PIC16F84 a PIC16F628) , la cosa potrà anche essere
semplice, riguardando processori che hanno la stessa filosofia di base e
le cui differenze consistono essenzialmente nelle periferiche integrate.
|
In pratica, siccome ogni famiglia di microprocessori o microcontroller
dispone di caratteristiche e strutture diverse, esistono Assembly diversi
per ognuna di esse e Assembler altrettanto dedicati, anche se le regole
generali sono molto simili.
MPASM è un Assembler adeguato a tutti i PIC di Microchip a 8 bit. Un ASM30
supporta gli altri PIC (dsPIC, PIC24, PIC30).
Nella scelta di altri prodotti, compresi linguaggi a livello più elevato,
verificate che il microcontroller che intendete utilizzare risulti presente
nella lista di compatibilità del linguaggio.
Una conoscenza del set di istruzioni del processore usato è assolutamente
indispensabile per programmare in Assembly, ma, rispetto alle convenzioni e
regole da conoscere per utilizzare altri linguaggi, si tratta di ben poca
cosa, dato che i PIC sono processori RISC, ovvero con un set di istruzioni
ridotto, che va da una trentina ad una ottantina a seconda della famiglia di
appartenenza. Inoltre tutti i set di istruzione sono analoghi, derivando da
una unica filosofia di base del progetto dei processori; in sostanza si tratta
di un set base molto semplice che viene arricchito da altri opcodes con l'
aumentare della complessità e delle prestazioni della CPU.
|