Lezione 03
🎓 PIC16 — From Zero to Hero · Lezione 03
Il registro W e le prime istruzioni 📦
MOVLW MOVWF MOVF CLRW CLRF
Le cinque istruzioni fondamentali per muovere dati.
🎯 Cosa impari in questa lezione
- Perché il registro W è il centro di tutto nel PIC16
MOVLW k— caricare una costante in WMOVWF f— copiare W in un registro RAMMOVF f,d— leggere un registro RAM (verso W o verso sé stesso)CLRW— azzerare WCLRF f— azzerare un registro RAM- Come il simulatore mostra ogni movimento in tempo reale
📋 Scheda lezione
| Modulo | 1 — Assembly Base |
| Lezione | 03 di 42 |
| Livello | ⭐ Principiante |
| Tempo | ~25 minuti |
| Istruzioni | 5 nuove |
| Flag STATUS | Z (solo CLRW, CLRF, MOVF) |
🧠 Il registro W — la “mano” della CPU
Nel PIC16 quasi tutto passa per il registro W (Working register). Non ha un indirizzo RAM — è un registro interno all’ALU, a 8 bit, accessibile direttamente in ogni operazione. Puoi pensarlo come la mano della CPU: per spostare qualcosa da un posto a un altro, quasi sempre devi prima prenderlo in W.
Questa architettura si chiama accumulatore: tutte le operazioni aritmetiche e logiche usano W come operando implicito. È diversa da architetture con molti registri generali (come ARM o x86) — ma per 8 bit e 35 istruzioni è la scelta giusta: semplice, prevedibile, facile da tenere in testa.
① MOVLW k — carica una costante in W
MOVLW kMOVe Literal to W. Copia la costante k (un valore da 0 a 255) dentro W. È l’istruzione più usata in assoluto — ogni volta che vuoi mettere un valore specifico in W, usi questa.
MOVLW 0x05 ; W = 0x05 (5 in decimale)
MOVLW 0xFF ; W = 0xFF (255 in decimale)
MOVLW 0x00 ; W = 0x00 (0 in decimale)
MOVLW 42 ; W = 42 (decimale, meno comune)
MOVLW b’10110011′ ; W = 0xB3 (binario — utile per maschere)
⚠️ MOVLW non modifica nessun flag. Anche se carichi 0x00, il flag Z rimane invariato. Se vuoi azzerare W e settare Z, usa CLRW.
② MOVWF f — copia W in un registro RAM
MOVWF fMOVe W to File register. Copia il contenuto di W nel registro f. Il valore in W rimane invariato — è una copia, non uno spostamento. Il parametro f può essere un indirizzo numerico (0x0C) o un nome simbolico (PORTB, CONTATORE).
CONTATORE EQU 0x0C ; dichiaro variabile in GPR
VALORE EQU 0x0D ; seconda variabile
MOVLW 0x0A ; W = 10
MOVWF CONTATORE ; RAM[0x0C] = 10 — W resta 10
MOVWF VALORE ; RAM[0x0D] = 10 — stessa copia!
; Accendo tutti i LED su PORTB in 2 istruzioni:
MOVLW 0xFF
MOVWF PORTB ; tutti i pin RB0–RB7 alti
💡 MOVLW + MOVWF è la coppia più usata nel codice PIC. Quasi ogni inizializzazione si fa così: prima carichi il valore in W, poi lo scrivi dove serve.
③ MOVF f,d — leggi un registro RAM
MOVF f,dMOVe File register. Legge il registro f e lo copia nella destinazione d. La destinazione è controllata dal parametro d:
d = W (oppure d = 0)
Il valore di f viene copiato in W. Uso tipico: leggere un registro per poi usarlo in un’operazione.
MOVF CONTATORE, W
; ora W = valore di CONTATORE
d = F (oppure d = 1)
Il valore rimane in f — apparentemente inutile. Ma aggiorna il flag Z. Serve per testare se un registro è zero senza modificarne il valore.
MOVF CONTATORE, F
; Z=1 se CONTATORE vale 0
; Z=0 se CONTATORE è diverso da 0
CONTATORE EQU 0x0C
RISULTATO EQU 0x0D
; Copio CONTATORE in RISULTATO (passando per W)
MOVF CONTATORE, W ; W = CONTATORE
MOVWF RISULTATO ; RISULTATO = W = CONTATORE
; Leggo PORTA e metto su PORTB (copia porta)
MOVF PORTA, W ; W = stato pin PORTA
MOVWF PORTB ; PORTB = stessa configurazione
🔍 Nota importante: non esiste un’istruzione “copia registro in registro” diretta. Per copiare f1 in f2 devi sempre passare per W: MOVF f1,W poi MOVWF f2. Due istruzioni, due cicli di clock.
④ CLRW — azzera W
CLRWCLeaR W. Azzera il registro W e setta sempre il flag Z a 1. Non ha parametri — c’è un solo W. Equivale a MOVLW 0x00 con la differenza che setta Z.
CLRW ; W = 0x00, Z = 1
; Confronto con MOVLW 0:
MOVLW 0x00 ; W = 0x00, Z NON viene modificato
CLRW ; W = 0x00, Z = 1 (garantito)
⑤ CLRF f — azzera un registro RAM
CLRF fCLeaR File register. Azzera il registro all’indirizzo f e setta Z a 1. Più efficiente di MOVLW 0x00 / MOVWF f perché usa una sola istruzione e non tocca W.
CONTATORE EQU 0x0C
CLRF CONTATORE ; RAM[0x0C] = 0, Z = 1, W invariato
CLRF PORTB ; tutti i pin PORTB a 0 (LED spenti)
CLRF TRISB ; tutti i pin PORTB come output
; (ricorda: TRISB è nel banco 1!)
💡 CLRF TRISB è il modo più compatto per impostare tutti i pin di PORTB come output in una sola istruzione. Lo vedrai spesso nell’inizializzazione di qualsiasi programma con LED.
📊 Riepilogo — le 5 istruzioni a confronto
| Istruzione | Operazione | W dopo | RAM f dopo | Flag Z | Cicli |
|---|---|---|---|---|---|
MOVLW k | k → W | = k | invariata | — | 1 |
MOVWF f | W → f | invariato | = W | — | 1 |
MOVF f,W | f → W | = f | invariata | aggiornato | 1 |
MOVF f,F | f → f (test) | invariato | invariata | aggiornato | 1 |
CLRW | 0 → W | = 0 | invariata | 1 (sempre) | 1 |
CLRF f | 0 → f | invariato | = 0 | 1 (sempre) | 1 |
💻 Programma completo — Step by step nel simulatore
Carica questo programma, poi premi Step una volta per ogni istruzione. Per ogni step compila la tabella qui sotto — alla fine avrai una mappa completa di come si muovono i dati.
; ============================================
; Lezione 03 — MOV e CLR in azione
; Prof. D.Bertolino · WebPicSimulator
; ============================================
LIST p=16F84A
#include <p16f84a.inc>
VAR_A EQU 0x0C ; prima variabile
VAR_B EQU 0x0D ; seconda variabile
VAR_C EQU 0x0E ; terza variabile
ORG 0x00
; STEP 1
MOVLW 0x42 ; carica 0x42 in W
; STEP 2
MOVWF VAR_A ; VAR_A = 0x42
; STEP 3
MOVLW 0xFF ; W ora vale 0xFF
; STEP 4 — VAR_A non cambia, W sì
MOVF VAR_A, W ; W torna a 0x42, Z=0
; STEP 5
MOVWF VAR_B ; VAR_B = 0x42 (copia di VAR_A)
; STEP 6 — azzera W, setta Z
CLRW ; W = 0, Z = 1
; STEP 7 — azzera VAR_C, W non cambia
CLRF VAR_C ; VAR_C = 0, Z = 1
; STEP 8 — test Z con MOVF,F
MOVF VAR_B, F ; W invariato, Z=0 (VAR_B = 0x42 ≠ 0)
FINE GOTO FINE
END
Compila la tabella ad ogni Step. Controlla i valori nel pannello registri del simulatore:
| Step | Istruzione | W | VAR_A (0x0C) | VAR_B (0x0D) | VAR_C (0x0E) | Z |
|---|---|---|---|---|---|---|
| inizio | — | 0x00 | 0x00 | 0x00 | 0x00 | 0 |
| 1 | MOVLW 0x42 | ? | — | — | — | — |
| 2 | MOVWF VAR_A | — | ? | — | — | — |
| 3 | MOVLW 0xFF | ? | — | — | — | — |
| 4 | MOVF VAR_A,W | ? | — | — | — | ? |
| 5 | MOVWF VAR_B | — | — | ? | — | — |
| 6 | CLRW | ? | — | — | — | ? |
| 7 | CLRF VAR_C | — | — | — | ? | ? |
| 8 | MOVF VAR_B,F | — | — | — | — | ? |
Mostra soluzione completa
| Step | W | VAR_A | VAR_B | VAR_C | Z |
|---|---|---|---|---|---|
| 1 | 0x42 | 0x00 | 0x00 | 0x00 | 0 (non toccato) |
| 2 | 0x42 | 0x42 | 0x00 | 0x00 | 0 |
| 3 | 0xFF | 0x42 | 0x00 | 0x00 | 0 |
| 4 | 0x42 | 0x42 | 0x00 | 0x00 | 0 (0x42 ≠ 0) |
| 5 | 0x42 | 0x42 | 0x42 | 0x00 | 0 |
| 6 | 0x00 | 0x42 | 0x42 | 0x00 | 1 |
| 7 | 0x00 | 0x42 | 0x42 | 0x00 | 1 |
| 8 | 0x00 | 0x42 | 0x42 | 0x00 | 0 (0x42 ≠ 0) |
🏋️ Prova tu!
- Scrivi un programma che mette il valore
0xA5in VAR_A, poi lo copia in VAR_B e VAR_C. Verifica nel simulatore che tutti e tre abbiano lo stesso valore. - Aggiungi al programma una sequenza che azzera VAR_B con
CLRFe poi testa se VAR_A è zero usandoMOVF VAR_A, F. Quanto vale Z dopo il test? - Sfida: c’è un modo per mettere il valore 0 in VAR_A senza usare CLRF e senza modificare W? Cercalo — c’è più di una soluzione con le istruzioni di questa lezione.
💡 Per l’esercizio 3: pensa a MOVF con destinazione F… oppure a un’altra combinazione di istruzioni che hai già visto.
❓ Quiz rapido
1. Dopo MOVLW 0x00, il flag Z vale 1 o 0?
Mostra risposta
Non cambia — MOVLW non tocca nessun flag. Z resta al valore che aveva prima. Se vuoi Z=1, devi usare CLRW.
2. Qual è la differenza tra MOVF f,W e MOVF f,F?
Mostra risposta
MOVF f,W copia il valore di f in W (e aggiorna Z). MOVF f,F non sposta niente (il valore rimane in f, W non cambia), ma aggiorna il flag Z — utile per testare se un registro è zero.
3. Ho bisogno di copiare il valore di CONTA (0x0C) in BUFFER (0x0D). Quante istruzioni servono?
Mostra risposta
Due: MOVF CONTA, W poi MOVWF BUFFER. Non esiste un’istruzione “registro→registro” diretta nel PIC16 — si passa sempre per W.
4. Voglio azzerare PORTB nel modo più efficiente possibile (meno istruzioni, W invariato). Quale istruzione uso?
Mostra risposta
CLRF PORTB — una sola istruzione, azzera PORTB, setta Z=1, e non tocca W. L’alternativa MOVLW 0x00 / MOVWF PORTB sono due istruzioni e modifica W.
Prossima lezione →
Lezione 04 — Aritmetica a 8 bitADDLW, ADDWF, SUBLW, SUBWF — somme, sottrazioni
e come i flag C, DC e Z riflettono il risultato.
© Prof. D. Bertolino · PIC16 From Zero to Hero · WebPicSimulator · Lezione 03