Indirizzamento indiretto


L'indirizzamento indiretto e' una delle caratteristiche piu' interessanti del PIC 16F84. Grazie a questo sistema e' possibile accedere sia in lettura che in scrittura ad un dato registro GPR in modo indirietto, ovverosia specificandone l'indirizzo sotto forma di dato contenuto in un altro registro.
All'apparenza il meccanismo potrebbe apparire come una complicazione non strettamente necessaria, in realta' e' estremamente utile. Un esempio aiutera' a capirne l'ambito di utilizzo: normalmente per poter accedere in scrittura ad un dato registro occorre specificarne l'indirizzo direttamente nell'istruzione.
Ad esempio, il codice seguente carica
il registo 0x0C con il valore 0xA3:

MOVLW    0xA3
MOVWF    0x0C

Il valore 0x0C e' ovviamente specificato nell'istruzione MOVWF. Fin qui niente di male. Ma come si potrebbe fare per caricare tutti i registri GPR con il medesimo valore 0xA3? Con il metodo tradizionale l'unico sistema e' quello di ripetere l'istruzione MOVWF per tutti i registri, in questo modo:

MOVLW    0xA3
MOVWF    0x0C
MOVWF    0x0E
MOVWF    0x0F
...
...
...
MOVWF    0x4F

L'operazione richiede quindi la ripetizione di MOVWF ben 68 volte, con grande spreco di memoria di programma. In effetti non si possono creare cicli per ripetere MOVWF in quanto l'indirizzo del registro corrente deve essere necessariamente codificato nell'istruzione (non e' un dato che si puo' incrementare di uno).
Per risolvere il problema ci viene in contro il sistema dell'indirizzamento indiretto. Grazie ad esso si puo' accedere ad un dato registro GPR tramite due registri di appoggio:
  • FSR
  • INDF
FSR si trova all'indirizzo di memoria 0x04 ed e' mappato in entrambi i banchi RAM.
INDF si trova all'indirizzo di memoria 0x00 ed e' mappato in entrambi i banchi RAM.
Per vedere la loro posizione in memoria RAM consultare la sezione "Memoria RAM/FLASH/EEPROM".

Il registro FSR serve per specificare l'indirizzo di memoria del registro che vogliamo accedere; per farlo e' sufficiente scrivere il relativo indirizzo in questo registro. Una volta fatto questo, tutte le eventuali letture e scritture effettuate nel registro INDF saranno svolte come se si stesse effettivamente accedendo al registro in questione  e puntato da FSR.


Esempio:
Scrivere una subroutine che cancella tutti i registri GPR (il primo registro GPR e' alla locazione 0x0C e l'ultimo alla locazione 0x4F)

FSR    EQU    0x04
INDF   EQU    0x00
STATUS EQU    0x03

:clearall
MOVLW  0x0C           ;inizializzo il puntatore al primo registro GPR
MOVWF  FSR            ;e lo scrivo nel registro FSR
next:
CLRF   INDF           ;cancello il contenuto di INDF
INCF   FSR            ;incremento di uno il puntatore
MOVF   FSR,0
SUBLW  0x50
BTFSS  STATUS,2       ;se FSR=0x50 vai a RETURN, altrimenti vai a next
GOTO   next
RETURN