Lezione 4 di 43

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 W
  • MOVWF f — copiare W in un registro RAM
  • MOVF f,d — leggere un registro RAM (verso W o verso sé stesso)
  • CLRW — azzerare W
  • CLRF f — azzerare un registro RAM
  • Come il simulatore mostra ogni movimento in tempo reale

📋 Scheda lezione

Modulo1 — Assembly Base
Lezione03 di 42
Livello⭐ Principiante
Tempo~25 minuti
Istruzioni5 nuove
Flag STATUSZ (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.

Flusso dati — le 5 istruzioni di questa lezione Costante k 0x00 – 0xFF (nel codice sorgente) W Working Register 8 bit · interno CPU RAM f SFR o GPR RAM f destinazione F MOVLW k MOVWF f MOVF f,W MOVF f,F (solo Z) CLRW → W = 0, Z=1 CLRF f → f = 0, Z=1
Figura 1 — Flusso dati delle 5 istruzioni: costante → W → RAM e viceversa

① MOVLW k — carica una costante in W

Sintassi
MOVLW k
Operazione
k → W
Flag modificati
nessuno
Cicli
1

MOVe 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

Sintassi
MOVWF f
Operazione
W → f
Flag modificati
nessuno
Cicli
1

MOVe 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

Sintassi
MOVF f,d
Operazione
f → dest
Flag modificati
Z
Cicli
1

MOVe 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

Sintassi
CLRW
Operazione
0 → W
Flag modificati
Z = 1 (sempre)
Cicli
1

CLeaR 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

Sintassi
CLRF f
Operazione
0 → f
Flag modificati
Z = 1 (sempre)
Cicli
1

CLeaR 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

IstruzioneOperazioneW dopoRAM f dopoFlag ZCicli
MOVLW kk → W= kinvariata—1
MOVWF fW → finvariato= W—1
MOVF f,Wf → W= finvariataaggiornato1
MOVF f,Ff → f (test)invariatoinvariataaggiornato1
CLRW0 → W= 0invariata1 (sempre)1
CLRF f0 → finvariato= 01 (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:

StepIstruzioneWVAR_A (0x0C)VAR_B (0x0D)VAR_C (0x0E)Z
inizio—0x000x000x000x000
1MOVLW 0x42?————
2MOVWF VAR_A—?———
3MOVLW 0xFF?————
4MOVF VAR_A,W?———?
5MOVWF VAR_B——?——
6CLRW?———?
7CLRF VAR_C———??
8MOVF VAR_B,F————?
Mostra soluzione completa
StepWVAR_AVAR_BVAR_CZ
10x420x000x000x000 (non toccato)
20x420x420x000x000
30xFF0x420x000x000
40x420x420x000x000 (0x42 ≠ 0)
50x420x420x420x000
60x000x420x420x001
70x000x420x420x001
80x000x420x420x000 (0x42 ≠ 0)

🏋️ Prova tu!

  1. Scrivi un programma che mette il valore 0xA5 in VAR_A, poi lo copia in VAR_B e VAR_C. Verifica nel simulatore che tutti e tre abbiano lo stesso valore.
  2. Aggiungi al programma una sequenza che azzera VAR_B con CLRF e poi testa se VAR_A è zero usando MOVF VAR_A, F. Quanto vale Z dopo il test?
  3. 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 bit
ADDLW, 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