Indirizzamento indiretto
post-incrementato
Con una struttura simile al C (e nell’ intento di fornire
un supporto molto efficiente a questo linguaggio), gli enhanced dispongono
di una modalità di indirizzamento che auto incrementa il puntatore dopo
aver effettuato l’ operazione desiderata.
Viene usata una istruzione specifica :
POSTINCx
dove x è l’ indice (0, 1 o 2) dell’ INDF usato.
La sintassi è semplice :
lsfr FSR2, target ; puntatore su
target
movf POSTINC2, w ; legge dato in W e
incrementa il puntatore
|
Nulla vieta di utilizzare tanto l’ indirizzamento
indiretto semplice che quello incrementato nello stesso momento. Ad esempio,
si vuole muovere il contenuto delle locazioni target e target+1
rispettivamente nei registri W e deposito1, che sta in un banco qualunque
non indicizzato dai BSR :
lsfr FSR2, target
; puntatore su target
movf POSTINC2, w ; legge
dato in W e incrementa puntatore
movff INDF2, deposito1 ; muove target+1 a deposito1
|
In sostanza, la prima riga posiziona il puntatore su target.
La seconda riga copia in W il contenuto di target e , nello stesso tempo,
incrementa FSR2
La terza riga sposta il contenuto di target+1, puntato ora
da FSR2, nella locazione deposito1; essendo una movff a 32bit, non ci sono
limiti negli indirizzamenti.
Da questi semplici esempi si può notare come il set di
istruzioni e la struttura degli enhanced li rendano decisamente superiori e
innovativi rispetto ai mid renge.
Un esempio più complesso può essere il seguente : copiare
128 variabili dal Banco1 al Banco2. Se nei mid range si trattava di
districarsi in un groviglio di puntatori, indici, banchi, negli enhanced la
cosa si risolve con :
start equ 0x100
; inizio del Banco1
destin equ 0x200
; inizio del Banco2
lsfr FSR0, start
; puntatore su target
lsfr FSR1, destin
; puntatore su target
movff POSTINC0,POSTINC1 ; sposta dato da start a
destin
btfss FSR0L, 7
; mossi 80h dati ?
bra loop
; no - un altro loop
....
; si - prosegui
....
; con le successive
istruzioni
|
Se ci sono dubbi sulla riga btfss FSR0L, 7 questo test serve
a determinare quando il bit 7 del puntatore low ha raggiunto 80h (128 dec.),
ovvero la fine del loop (FSRH rimane sempre a zero).
Si poteva fare il test anche su FSR2L, che aumenta nella
stessa misura.
Non c'è nessuna limitazione del numero di puntatori che si
possono utilizzare contemporaneamente in una struttura logica. Ad esempio, lo
spostamento di un' area di memoria in un' altra diventa estremamente semplice.
Ad esempio, vogliamo spostare l' intero contenuto del banco 3 nel banco 4 :
lfsr FSR0,0x300
; FSR0 punta sul banco 3
lfsr FSR1,0x400
; FSR1 punta sul banco 4
loop:
movff POSTINC0,POSTINC1 ; sposta un byte
btfss FSR0H, 2 ;
FSR0 = 0x400 ?
bra loop
;
no, loop |
Estremamente semplice, dato che l' avanzamento degli indici di
puntamento avviene automaticamente e i registri virtuali POSTINCx (come pure
POSTDECx , INDFx e FSRx) sono trattabili come qualsiasi altro registro. Il test
che chiude il loop deriva dal fatto che, come, abbiamo detto prima, gli FSR sono
composti da due bytes, una parte alta, FSRxH ed una bassa, FSRxL.
Quindi , l'
istruzione :
ha caricato 00h in FSR0L e 03h in FSR0H.
Ogni incremento o decremento, agisce sul registro ballo (FSRxL), all'
azzeramento del quale viene modificato il registro alto (FSRxH), come avviene in
un normale contatore a 16 bit.
Per cui, ad esempio :
lfsr FSR0,0x3FE
; FSR0L= FEh FRS0H=03h
movf POSTINC0,w ; FSR0L=
FFh FRS0H=03h
movf POSTINC0,w ; FSR0L=
00h FRS0H=04h
movf POSTINC0,w ; FSR0L=
01h FRS0H=04h |
Questa struttura a 16 bit permette di indirizzare con gli FSR
tutta l' area della memoria RAM e quindi non esiste più un meccanismo come
quello dell' IRP che è necessario sui PIC16.
Indirizzamento indiretto
post-decrementato
In modo del tutto speculare a quanto appena visto, esiste
una istruzione POSTDECx che decrementa automaticamente il puntatore una
volta eseguita l’ istruzione voluta.
Analogamente all’ esempio precedente, spostiamo il contenuto di target in
W e di target-1 in deposito1
lsfr FSR2, target ;
puntatore su target
movf POSTDEC2, w ; legge dato in W e
decrementa puntatore
movff INDF2, deposito1 ; muove target-1 a deposito1
|
In sostanza, la prima riga posiziona il puntatore su target.
La seconda riga copia in W il contenuto di target e , nello stesso tempo, decrementa
FSR2
La terza riga sposta il contenuto di target-1, puntato ora
da FSR2, nella locazione deposito1.
Un altro esempio:
cblock source1
source2
endc
cblock target1
target2
endc
....
....
lsfr FSR2, source2 ; punta FSR2
su source2
movff POSTDEC2, target2 ; carica contenuto di source2
; in target2 |
il che permette di fare anche :
lsfr FSR2,
source2 ; punta FSR2 su source2
movff POSTDEC2, target2 ; carica contenuto di source2
; in target
movff INDF2, target1 ; e il contenuto
di source1 in
; traget1 |
in quanto il primo movff POSTDEC2
ha fatto si che il puntatore FSR2 sia diminuito di uno, puntando quindi a source1.
uesto indirizzamento consente di muoversi all' indietro in
una tabella o un array di dati
Indirizzamento indiretto
pre-incrementato
Esiste anche un indirizzamento in cui l’ incremento del
puntatore avviene prima dell’ esecuzione dell’ istruzione e fa
capo al codice PREINCx.
Un esempio :
lsfr FSR0, start ;
puntatore su start a 0x0100
movf PREINC0, w ; legge dato
start+1 (0x101) in W
|
Questo indirizzamento permette di di utilizzare un puntatore
che sia antecedente alla locazione da puntare.