Lezione 06
π PIC16 β From Zero to Hero Β· Lezione 06
Rotazioni e complemento π
RLF
RRF
COMF
SWAPF
Spostare bit, invertire byte, scambiare nibble β tutto attraverso il Carry.
π― Cosa impari in questa lezione
- Il concetto di registro a 9 bit (C + 8 bit dati) usato da RLF e RRF
RLF f,dβ ruota a sinistra attraverso il CarryRRF f,dβ ruota a destra attraverso il CarryCOMF f,dβ complemento a 1 di un registroSWAPF f,dβ scambia nibble alto e basso- Applicazioni pratiche: moltiplicazione Γ2, divisione Γ·2, shift a 16 bit
π Scheda lezione
| Modulo | 1 β Assembly Base |
| Lezione | 06 di 42 |
| Livello | ββ Principiante+ |
| Tempo | ~25 minuti |
| Istruzioni | 4 nuove |
| Flag STATUS | RLF/RRF β C | COMF β Z | SWAPF β nessuno |
π§ Il registro a 9 bit β C come estensione
RLF e RRF non ruotano solo gli 8 bit del registro: includono il flag C come nono bit. Puoi immaginarlo come un registro a 9 bit dove C Γ¨ il bit piΓΉ significativo (per RLF) o il bit di ingresso (per RRF). Questo design Γ¨ intenzionale: permette di fare shift su numeri a 16 bit o piΓΉ, concatenando piΓΉ rotazioni.
β RLF f,d β ruota a sinistra attraverso Carry
RLF f,dOgni bit si sposta di una posizione verso sinistra. Il vecchio bit 7 entra nel flag C; il vecchio C entra come bit 0. Equivale a moltiplicare per 2 β con il carry che cattura l’eventuale overflow del bit piΓΉ significativo.
REG EQU 0x0C
; Moltiplicazione per 2 (REG * 2)
; Prima: azzerare C per non introdurre bit spuri
BCF STATUS, C ; C = 0
RLF REG, F ; REG = REG * 2 (se REG=0x15, diventa 0x2A)
; C=1 se overflow (il valore superava 127)
; RLF con d=W: non modifica REG
BCF STATUS, C
RLF REG, W ; W = REG*2, REG invariato
; Shift a 16 bit: REG_HI:REG_LO spostati a sinistra di 1
REG_LO EQU 0x0C
REG_HI EQU 0x0D
BCF STATUS, C ; azzera C
RLF REG_LO, F ; b7 di REG_LO β C
RLF REG_HI, F ; C (=old b7 di LO) β b0 di REG_HI
β οΈ Sempre azzerare C prima di RLF/RRF se vuoi un risultato pulito. Il flag C conserva il valore dell’ultima operazione che lo ha modificato β se dimentichi di azzerarlo, entra nel byte come bit sprio e il risultato sarΓ sbagliato.
β‘ RRF f,d β ruota a destra attraverso Carry
RRF f,dOgni bit si sposta di una posizione verso destra. Il vecchio bit 0 entra nel flag C; il vecchio C entra come bit 7. Equivale a dividere per 2 β con C che cattura il bit perso (il “resto” della divisione).
; Divisione per 2 (REG / 2) β divisione intera
BCF STATUS, C ; C = 0 (vogliamo MSB = 0)
RRF REG, F ; REG = REG / 2 (se REG=0x2A, diventa 0x15)
; C = vecchio bit 0 (il “resto” della divisione)
; Estrarre il bit 0 di REG senza distruggerlo
RRF REG, W ; W = REG>>1, C = vecchio bit 0 di REG
; ora puoi testare C con BTFSC/BTFSS STATUS,C
; Shift a 16 bit verso destra: REG_HI:REG_LO
BCF STATUS, C
RRF REG_HI, F ; b0 di HI β C
RRF REG_LO, F ; C (=old b0 di HI) β b7 di LO
π‘ C come “resto”: dopo RRF REG, F con C=0 iniziale, il flag C contiene il bit 0 originale di REG. Se era 1, il numero era dispari; se era 0, era pari. Questo Γ¨ il modo PIC di fare if (n % 2 != 0).
β’ COMF f,d β complemento a 1
COMF f,dCOMplement File register. Inverte ogni bit del registro: 0β1 e 1β0. Γ il complemento a 1 (NOT logico). Non va confuso con il complemento a 2 (che si ottiene con COMF + INCF). Modifica solo Z β C e DC rimangono invariati.
; Complemento a 1 (NOT)
COMF REG, F ; ogni bit di REG invertito
; Complemento a 2 (negazione aritmetica) = COMF + INCF
COMF REG, F ; passo 1: complemento a 1
INCF REG, F ; passo 2: +1 β complemento a 2 = -REG
; COMF verso W: REG non viene modificato
COMF REG, W ; W = ~REG, REG invariato
; Caso particolare: COMF di 0xFF β W=0x00, Z=1
MOVLW 0xFF
MOVWF REG
COMF REG, W ; W = 0x00, Z = 1
β£ SWAPF f,d β scambia i nibble
SWAPF f,dScambia il nibble alto (bit 7..4) con il nibble basso (bit 3..0). Non modifica nessun flag β nΓ© C, nΓ© DC, nΓ© Z. Γ l’unica istruzione di manipolazione byte completamente “silenziosa” sui flag. Usatissima per conversioni BCD e per spostare nibble senza disturbare lo stato corrente.
; Estrarre nibble alto in W come nibble basso (senza AND)
SWAPF REG, W ; W = nibble alto di REG ora in posizione bassa
ANDLW 0x0F ; W = solo nibble originalmente alto (ripulito)
; SWAPF usata in interrupt per salvare W senza toccare STATUS
; (tecnica classica del PIC16 β approfondita nel modulo interrupt)
W_SAVE EQU 0x0E
SWAPF W, W ; β non esiste! W non ha indirizzo diretto
; Il trucco corretto per salvare W nell’ISR:
MOVWF W_SAVE ; salva W senza toccare STATUS
; … codice ISR …
SWAPF W_SAVE, F ; passo 1 del ripristino sicuro
SWAPF W_SAVE, W ; passo 2: W restaurato senza toccare Z
π Tecnica avanzata β doppio SWAPF: usare SWAPF f,F seguito da SWAPF f,W Γ¨ il modo classico PIC per leggere un registro in W senza modificare il flag Z (che MOVF invece modificherebbe). TornerΓ utile nella gestione degli interrupt.
π Riepilogo β le 4 istruzioni a confronto
| Istruzione | Operazione | Cosa entra | Cosa esce | C | Z | Note |
|---|---|---|---|---|---|---|
RLF f,d | shift β 1 bit | vecchio C β b0 | vecchio b7 β C | β | β | Γ2; azzerare C prima |
RRF f,d | shift β 1 bit | vecchio C β b7 | vecchio b0 β C | β | β | Γ·2; azzerare C prima |
COMF f,d | NOT f | β | β | β | β | complemento a 1 |
SWAPF f,d | nibble swap | β | β | β | β | nessun flag modificato! |
π» Programma β verifica bit per bit
; ============================================
; Lezione 06 β RLF, RRF, COMF, SWAPF
; Prof. D.Bertolino Β· WebPicSimulator
; ============================================
LIST p=16F84A
#include <p16f84a.inc>
REG EQU 0x0C
ORG 0x00
; — RLF —
MOVLW 0x15 ; REG = 0001 0101
MOVWF REG
BCF STATUS, C ; C = 0
RLF REG, F ; [1] REG=? C=? (Γ2)
RLF REG, F ; [2] REG=? C=? (Γ4 del valore originale)
; RLF con overflow
MOVLW 0xA0 ; REG = 1010 0000 (bit 7 = 1)
MOVWF REG
BCF STATUS, C
RLF REG, F ; [3] REG=? C=? (overflow!)
; — RRF —
MOVLW 0x54 ; REG = 0101 0100
MOVWF REG
BCF STATUS, C
RRF REG, F ; [4] REG=? C=? (Γ·2)
; RRF con bit 0 dispari
MOVLW 0x55 ; REG = 0101 0101 (dispari)
MOVWF REG
BCF STATUS, C
RRF REG, F ; [5] REG=? C=? (bit 0 = 1 β C)
; — COMF —
MOVLW 0xB4
MOVWF REG
COMF REG, W ; [6] W=? Z=?
; — SWAPF —
MOVLW 0xA3
MOVWF REG
SWAPF REG, W ; [7] W=? REG=?
FINE GOTO FINE
END
Mostra soluzione
| # | Istruzione | REG prima | REG dopo | W | C | Note |
|---|---|---|---|---|---|---|
| 1 | RLF REG,F | 0x15 = 0001 0101 | 0x2A = 0010 1010 | β | 0 | Γ2, b7 era 0 β C=0 |
| 2 | RLF REG,F | 0x2A = 0010 1010 | 0x54 = 0101 0100 | β | 0 | Γ4 del valore originale 0x15 |
| 3 | RLF REG,F | 0xA0 = 1010 0000 | 0x40 = 0100 0000 | β | 1 | b7=1 β C=1, overflow |
| 4 | RRF REG,F | 0x54 = 0101 0100 | 0x2A = 0010 1010 | β | 0 | Γ·2, b0 era 0 β C=0 |
| 5 | RRF REG,F | 0x55 = 0101 0101 | 0x2A = 0010 1010 | β | 1 | b0=1 β C=1 (numero dispari) |
| 6 | COMF REG,W | 0xB4 | 0xB4 (invariato) | 0x4B | β | ~0xB4=0x4B, Z=0 |
| 7 | SWAPF REG,W | 0xA3 | 0xA3 (invariato) | 0x3A | β | nibble scambiati, REG intatto |
ποΈ Prova tu!
- Partendo da
REG = 0x01(solo il bit 0 acceso), esegui 8 volteRLF REG,F(con C azzerato prima di ogni RLF). Traccia il valore di REG e C dopo ogni step. Cosa noti al 9Β° passo? - Calcola
-37in complemento a 2 a 8 bit usandoCOMFeINCF. Prima converti 37 in hex, poi applica le due istruzioni. Verifica nel simulatore. - Sfida: usando solo le istruzioni imparate finora (inclusi SWAPF e le operazioni logiche), estrai il nibble alto di
REG = 0xC7come valore 0x0C (senza offset) in W. Quante istruzioni ti servono?
π‘ Esercizio 3: SWAPF REG,W porta il nibble alto in posizione bassa di W β poi cosa serve per pulire il nibble alto rimasto? Una sola istruzione logica.
β Quiz rapido
1. REG = 0x80, C = 0. Dopo RLF REG,F: quanto vale REG? Quanto vale C?
Mostra risposta
REG = 0x00 (tutti i bit si spostano a sinistra, il bit 7 era l’unico a 1 ed Γ¨ “caduto” in C). C = 1. Questo Γ¨ il modo per testare se il bit 7 di un registro Γ¨ 1: dopo RLF con C=0, se C=1 allora b7 era 1.
2. Qual Γ¨ la differenza tra COMF f,F e COMF f,W?
Mostra risposta
COMF f,F sovrascrive il registro f con il suo complemento (f viene modificato). COMF f,W mette il complemento in W e lascia f invariato β utile quando vuoi lavorare con il complemento senza distruggere il valore originale.
3. PerchΓ© SWAPF Γ¨ utile nell’ISR (Interrupt Service Routine)?
Mostra risposta
PerchΓ© Γ¨ l’unica istruzione che puΓ² leggere/scrivere un registro senza toccare nessun flag STATUS. Nell’ISR bisogna salvare e ripristinare W preservando esattamente lo stato dei flag. Il doppio SWAPF (SWAPF f,F poi SWAPF f,W) permette di caricare un valore in W senza alterare Z, C o DC.
4. REG = 0x37, C = 0. Dopo RRF REG,F poi di nuovo RRF REG,F: quanto vale REG?
Mostra risposta
Passo 1: 0x37 = 0011 0111, RRF β 0x1B = 0001 1011, C=1 (bit 0 era 1). Passo 2: C=1 entra come b7 β 0x8D = 1000 1101, C=1 (bit 0 di 0x1B era 1). Attenzione: il C del passo 1 influenza il passo 2 β Γ¨ fondamentale controllare il C tra una rotazione e l’altra se si vuole uno shift pulito.
Prossima lezione β
Lezione 07 β Il registro STATUS approfondito
C, DC, Z, RP0, RP1, IRP, TO, PD β ogni bit spiegato in dettaglio.
Cambio banco, reset state e la trappola del bank switching.
Β© Prof. D. Bertolino Β· PIC16 From Zero to Hero Β· WebPicSimulator Β· Lezione 06