Lezione 7 di 43

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 Carry
  • RRF f,d β€” ruota a destra attraverso il Carry
  • COMF f,d β€” complemento a 1 di un registro
  • SWAPF f,d β€” scambia nibble alto e basso
  • Applicazioni pratiche: moltiplicazione Γ—2, divisione Γ·2, shift a 16 bit

πŸ“‹ Scheda lezione

Modulo1 β€” Assembly Base
Lezione06 di 42
Livello⭐⭐ Principiante+
Tempo~25 minuti
Istruzioni4 nuove
Flag STATUSRLF/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.

Il registro a 9 bit β€” RLF e RRF attraverso il Carry RLF (Rotate Left through carry) C 0 b7 b6 b5 b4 b3 b2 b1 b0 1 0 1 1 0 1 0 0 RLF C’ 1 ← vecchio b7 nuovo byte: 0110 1000 C entra come b0 RRF (Rotate Right through carry) C 0 b7 b6 b5 b4 b3 b2 b1 b0 1 0 1 1 0 1 0 1 RRF C’ 1 ← vecchio b0 nuovo byte: 0101 1010 C entra come b7
Figura 1 β€” RLF e RRF: C fa parte del registro a 9 bit. Il bit che “cade fuori” diventa il nuovo C.

β‘  RLF f,d β€” ruota a sinistra attraverso Carry

Sintassi
RLF f,d
Operazione
C ← b7, b0 ← old C
Flag
C soltanto
Cicli
1

Ogni 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

Sintassi
RRF f,d
Operazione
C ← b0, b7 ← old C
Flag
C soltanto
Cicli
1

Ogni 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

Sintassi
COMF f,d
Operazione
NOT f β†’ dest
Flag
Z soltanto
Cicli
1

COMplement 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.

COMF β€” complemento a 1 prima = 10110100 = 0xB4 COMF = 01001011 = 0x4B (ogni bit invertito, Z=0) Nota: 0xB4 + 0x4B = 0xFF (complemento a 1 + originale = 0xFF)

; 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

Sintassi
SWAPF f,d
Operazione
f<3:0> ↔ f<7:4>
Flag
nessuno
Cicli
1

Scambia 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.

SWAPF β€” scambia nibble alto e basso nibble alto A nibble basso 3 = 0xA3 SWAPF nibble alto 3 nibble basso A = 0x3A nessun flag modificato
Figura 2 β€” SWAPF: nibble alto e basso si scambiano. 0xA3 β†’ 0x3A.

; 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

IstruzioneOperazioneCosa entraCosa esceCZNote
RLF f,dshift ← 1 bitvecchio C β†’ b0vecchio b7 β†’ Cβœ…β€”Γ—2; azzerare C prima
RRF f,dshift β†’ 1 bitvecchio C β†’ b7vecchio b0 β†’ Cβœ…β€”Γ·2; azzerare C prima
COMF f,dNOT fβ€”β€”β€”βœ…complemento a 1
SWAPF f,dnibble 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
#IstruzioneREG primaREG dopoWCNote
1RLF REG,F0x15 = 0001 01010x2A = 0010 1010β€”0Γ—2, b7 era 0 β†’ C=0
2RLF REG,F0x2A = 0010 10100x54 = 0101 0100β€”0Γ—4 del valore originale 0x15
3RLF REG,F0xA0 = 1010 00000x40 = 0100 0000β€”1b7=1 β†’ C=1, overflow
4RRF REG,F0x54 = 0101 01000x2A = 0010 1010β€”0Γ·2, b0 era 0 β†’ C=0
5RRF REG,F0x55 = 0101 01010x2A = 0010 1010β€”1b0=1 β†’ C=1 (numero dispari)
6COMF REG,W0xB40xB4 (invariato)0x4Bβ€”~0xB4=0x4B, Z=0
7SWAPF REG,W0xA30xA3 (invariato)0x3Aβ€”nibble scambiati, REG intatto

πŸ‹οΈ Prova tu!

  1. Partendo da REG = 0x01 (solo il bit 0 acceso), esegui 8 volte RLF REG,F (con C azzerato prima di ogni RLF). Traccia il valore di REG e C dopo ogni step. Cosa noti al 9Β° passo?
  2. Calcola -37 in complemento a 2 a 8 bit usando COMF e INCF. Prima converti 37 in hex, poi applica le due istruzioni. Verifica nel simulatore.
  3. Sfida: usando solo le istruzioni imparate finora (inclusi SWAPF e le operazioni logiche), estrai il nibble alto di REG = 0xC7 come 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