Lezione 5 di 43

Lezione 04

πŸŽ“ PIC16 β€” From Zero to Hero Β· Lezione 04

Aritmetica a 8 bit βž•βž–

ADDLW  ADDWF  SUBLW  SUBWF
Somme, sottrazioni e i tre flag C, DC, Z.

🎯 Cosa impari in questa lezione

  • ADDLW k β€” somma una costante a W
  • ADDWF f,d β€” somma W con un registro RAM
  • SUBLW k β€” sottrae W da una costante (k - W)
  • SUBWF f,d β€” sottrae W da un registro RAM (f - W)
  • Come funziona il flag C in addizione e sottrazione
  • Cos’Γ¨ il flag DC (Digit Carry) e quando serve
  • L’overflow a 8 bit e come gestirlo

πŸ“‹ Scheda lezione

Modulo1 β€” Assembly Base
Lezione04 di 42
Livello⭐⭐ Principiante+
Tempo~30 minuti
Istruzioni4 nuove
Flag STATUSC, DC, Z

πŸ”’ Aritmetica a 8 bit β€” il confine Γ¨ 255

Il registro W e tutti i registri RAM del PIC16 sono a 8 bit: possono contenere valori da 0x00 (0) a 0xFF (255). Cosa succede se il risultato di una somma supera 255? Il risultato si tronca a 8 bit e il carry viene registrato nel flag C.

Overflow a 8 bit β€” cosa succede ai flag C, DC, Z Somma normale 0x30 + 0x20 = 0x50 (80) C = 0 DC = 0 Z = 0 nessun riporto, risultato normale Overflow β€” Carry 0xF0 + 0x20 = 0x10 (+256 perso) C = 1 DC = 0 Z = 0 il nono bit Γ¨ andato nel flag C Digit Carry 0x08 + 0x09 = 0x11 (17) C = 0 DC = 1 Z = 0 riporto dal nibble basso (bit 3β†’4)
Figura 1 β€” I tre casi: normale, overflow carry, digit carry

πŸ”΄ Flag C β€” Carry

In addizione: vale 1 se il risultato supera 255 (il bit 8 “trabocca”).
In sottrazione: vale 1 se non c’Γ¨ borrow (risultato β‰₯ 0), 0 se c’Γ¨ borrow (risultato negativo). Attenzione β€” Γ¨ il contrario dell’intuizione!

🟠 Flag DC β€” Digit Carry

Riporto dal nibble basso (bit 3) al nibble alto (bit 4). Usato nell’aritmetica BCD (Binary Coded Decimal) per correggere il risultato. Nel codice normale lo ignorerai quasi sempre β€” ma il simulatore lo mostra comunque.

🟣 Flag Z β€” Zero

Vale 1 se il risultato (dopo la troncatura a 8 bit) è esattamente 0. Utile per rilevare quando due valori sono uguali: A - B = 0 significa A = B. È la base dei confronti.


β‘  ADDLW k β€” somma costante a W

Sintassi
ADDLW k
Operazione
W + k β†’ W
Flag
C Β· DC Β· Z
Cicli
1

Somma la costante k (0–255) al registro W e mette il risultato in W. I tre flag C, DC e Z vengono aggiornati in base al risultato.

MOVLW 0x30 ; W = 0x30
ADDLW 0x20 ; W = 0x50, C=0, DC=0, Z=0

MOVLW 0xF0 ; W = 0xF0
ADDLW 0x20 ; W = 0x10, C=1 (overflow!)

MOVLW 0xFE ; W = 0xFE = 254
ADDLW 0x02 ; W = 0x00, C=1, Z=1 (254+2=256, troncato a 0)

πŸ’‘ L’ultimo esempio Γ¨ interessante: 0xFE + 0x02 = 256, che a 8 bit diventa 0x00. Il risultato Γ¨ zero (Z=1) e c’Γ¨ stato carry (C=1) contemporaneamente. Nel simulatore puoi vedere entrambi i flag settati.

β‘‘ ADDWF f,d β€” somma W con un registro RAM

Sintassi
ADDWF f,d
Operazione
W + f β†’ dest
Flag
C Β· DC Β· Z
Cicli
1

Somma W con il registro f. La destinazione d decide dove va il risultato: W (d=0) oppure F (d=1, rimane in f). È la versione “registro con registro” dell’addizione.

CONTA EQU 0x0C
TOTALE EQU 0x0D

; ADDWF con d=W: risultato in W, f invariato
MOVLW 0x0A ; W = 10
MOVWF CONTA ; CONTA = 10
MOVLW 0x05 ; W = 5
ADDWF CONTA, W ; W = 5+10 = 15, CONTA = 10 (invariato)

; ADDWF con d=F: risultato in f, W invariato
MOVLW 0x05 ; W = 5
ADDWF CONTA, F ; CONTA = 10+5 = 15, W = 5 (invariato)

; Incremento diretto di una variabile (CONTA += 1)
MOVLW 0x01
ADDWF CONTA, F ; CONTA = CONTA + 1


β‘’ SUBLW k β€” sottrai W da una costante

Sintassi
SUBLW k
Operazione
k βˆ’ W β†’ W
Flag
C Β· DC Β· Z
Cicli
1

Attenzione alla direzione: Γ¨ k meno W, non W meno k. Il risultato va in W. È usata meno frequentemente di SUBWF, ma utile quando si vuole calcolare il “complemento” rispetto a una costante.

⚠️ Il flag C in sottrazione β€” logica invertita

Nel PIC16 (come nella maggior parte delle CPU a 8 bit), il flag C in sottrazione Γ¨ il complemento del borrow:

  • C = 1 se il risultato Γ¨ β‰₯ 0 (nessun borrow, sottrazione “va bene”)
  • C = 0 se il risultato Γ¨ < 0 (c’Γ¨ borrow, il sottraendo era piΓΉ grande)

Sembra controintuitivo, ma ha senso implementativo: la sottrazione viene eseguita come addizione del complemento a 2, e il carry di quell’addizione diventa il flag C.

; k=10, W=3 β†’ risultato = 10-3 = 7 β‰₯ 0 β†’ C=1
MOVLW 0x03 ; W = 3
SUBLW 0x0A ; W = 10-3 = 7, C=1, Z=0

; k=5, W=5 β†’ risultato = 0 β†’ C=1, Z=1
MOVLW 0x05 ; W = 5
SUBLW 0x05 ; W = 5-5 = 0, C=1, Z=1

; k=3, W=10 β†’ risultato = 3-10 = -7 (borrow!) β†’ C=0
MOVLW 0x0A ; W = 10
SUBLW 0x03 ; W = 3-10 β†’ 0xF9 (249), C=0 (borrow!)

β‘£ SUBWF f,d β€” sottrai W da un registro RAM

Sintassi
SUBWF f,d
Operazione
f βˆ’ W β†’ dest
Flag
C Β· DC Β· Z
Cicli
1

La piΓΉ usata tra le sottrazioni: f meno W. Stessa logica del flag C: vale 1 se il risultato Γ¨ β‰₯ 0. Il pattern tipico Γ¨ caricare il sottraendo in W con MOVLW, poi usare SUBWF.

VALORE EQU 0x0C
DIFF EQU 0x0D

; VALORE = 20, calcolo VALORE – 7
MOVLW 0x14 ; W = 20
MOVWF VALORE ; VALORE = 20
MOVLW 0x07 ; W = 7 (il sottraendo va in W)
SUBWF VALORE, W ; W = 20-7 = 13, C=1, VALORE invariato
MOVWF DIFF ; DIFF = 13

; Decremento diretto (VALORE -= 1)
MOVLW 0x01
SUBWF VALORE, F ; VALORE = VALORE – 1

; Confronto: VALORE == 10?
MOVLW 0x0A ; W = 10
SUBWF VALORE, W ; W = VALORE – 10
; Z=1 se VALORE==10, Z=0 altrimenti

πŸ’‘ Pattern confronto: MOVLW valore / SUBWF variabile, W Γ¨ il modo standard per confrontare una variabile con una costante. Se Z=1 i valori sono uguali. Nelle prossime lezioni lo combineremo con BTFSC/BTFSS per fare branch condizionali.


πŸ“Š Riepilogo β€” le 4 istruzioni a confronto

IstruzioneOperazioneDestinazioneCDCZ
ADDLW kW + kWβœ…βœ…βœ…
ADDWF f,WW + fWβœ…βœ…βœ…
ADDWF f,FW + ffβœ…βœ…βœ…
SUBLW kk βˆ’ WWβœ… (inv.)βœ…βœ…
SUBWF f,Wf βˆ’ WWβœ… (inv.)βœ…βœ…
SUBWF f,Ff βˆ’ Wfβœ… (inv.)βœ…βœ…

βœ… (inv.) = C Γ¨ invertito rispetto all’intuizione: vale 1 se il risultato Γ¨ β‰₯ 0, vale 0 se c’Γ¨ borrow.


πŸ” Visualizzare i flag nel simulatore

Il registro STATUS Γ¨ all’indirizzo 0x03. Nel pannello registri del simulatore lo vedi aggiornato in tempo reale dopo ogni istruzione. I bit che ci interessano ora sono i tre bassi:

STATUS (0x03) dopo: MOVLW 0x05 / ADDLW 0x05 bit 7 0 bit 6 0 bit 5 RP0 0 bit 4 TO 1 bit 3 PD 1 bit 2 β€” Z 0 bit 1 β€” DC 1 bit 0 β€” C 0
Figura 2 β€” Registro STATUS dopo MOVLW 0x05 / ADDLW 0x05: risultato 0x0A, DC=1 (riporto nibble), C=0, Z=0

πŸ’» Programma β€” esplora tutti i casi

Carica questo programma e usa Step per eseguirlo istruzione per istruzione. Per ogni operazione annota i valori di W, C, DC e Z β€” poi confronta con la tabella soluzione.

; ============================================
; Lezione 04 β€” Aritmetica e flag
; Prof. D.Bertolino Β· WebPicSimulator
; ============================================
LIST p=16F84A
#include <p16f84a.inc>
A EQU 0x0C
B EQU 0x0D
ORG 0x00

; — Addizioni —
MOVLW 0x30 ; W=0x30
ADDLW 0x20 ; [1] W=? C=? Z=?

MOVLW 0xF0 ; W=0xF0
ADDLW 0x20 ; [2] W=? C=? Z=? (overflow!)

MOVLW 0xFE ; W=0xFE
ADDLW 0x02 ; [3] W=? C=? Z=? (overflow+zero!)

MOVLW 0x14 ; W=20
MOVWF A ; A=20
MOVLW 0x06 ; W=6
ADDWF A, F ; [4] A=? W=? C=?

; — Sottrazioni —
MOVLW 0x0A ; W=10
SUBLW 0x1E ; [5] W=? C=? (30-10)

MOVLW 0x1E ; W=30
SUBLW 0x0A ; [6] W=? C=? (10-30, borrow!)

MOVLW 0x14 ; W=20
MOVWF B ; B=20
MOVLW 0x14 ; W=20
SUBWF B, W ; [7] W=? C=? Z=? (B-W, 20-20)

FINE GOTO FINE
END

Mostra soluzione β€” risultati attesi
#IstruzioneWCDCZNote
1ADDLW 0x200x500000x30+0x20=0x50, nessun overflow
2ADDLW 0x200x101000xF0+0x20=0x110, troncato a 0x10
3ADDLW 0x020x001010xFE+0x02=0x100 β†’ 0, C=1 e Z=1 insieme
4ADDWF A,F6000A=20+6=26=0x1A, W invariato a 6
5SUBLW 0x1E0x1411030-10=20=0x14, C=1 (no borrow)
6SUBLW 0x0A0xEC00010-30=-20 β†’ 0xEC (complemento a 2), C=0 (borrow!)
7SUBWF B,W0x00111B-W=20-20=0, C=1 (no borrow), Z=1

πŸ‹οΈ Prova tu!

  1. Scrivi una sequenza che calcola 100 - 37 e salva il risultato in una variabile RIS. Verifica nel simulatore che RIS = 63 = 0x3F e C=1.
  2. Aggiungi al programma precedente una seconda operazione: RIS + 200. Il risultato supera 255? Cosa vale C?
  3. Sfida: come fai a calcolare A - B (entrambe variabili in RAM) e mettere il risultato in una terza variabile DIFF? Scrivi la sequenza completa.

πŸ’‘ Per l’esercizio 3: ricorda che SUBWF calcola f - W. Prima devi caricare B in W, poi eseguire SUBWF A, W β€” oppure trovare un altro percorso.

❓ Quiz rapido

1. MOVLW 0xFF / ADDLW 0x01: quanto vale W? E il flag C?

Mostra risposta

W = 0x00 (255+1=256, troncato a 0). C = 1 (overflow). Z = 1 (risultato zero). Tre flag settati in una sola addizione.


2. Dopo MOVLW 0x05 / SUBLW 0x03 (cioΓ¨ 3βˆ’5), quanto vale C?

Mostra risposta

C = 0. Il risultato Γ¨ 3βˆ’5 = βˆ’2 (borrow): nel PIC16 C=0 indica che c’Γ¨ stato borrow, cioΓ¨ che il risultato Γ¨ negativo. W conterrΓ  0xFE (complemento a 2 di βˆ’2).


3. Qual Γ¨ la differenza tra ADDLW k e ADDWF f,W?

Mostra risposta

ADDLW k somma W con una costante scritta nel codice. ADDWF f,W somma W con il contenuto attuale del registro f in RAM β€” un valore che puΓ² cambiare durante l’esecuzione.


4. Voglio verificare se la variabile CONTA Γ¨ uguale a 50. Come scrivo il test senza modificare CONTA?

Mostra risposta

MOVLW 0x32 (50 in esadecimale) poi SUBWF CONTA, W. Il risultato va in W (CONTA rimane intatta). Se Z=1, CONTA era uguale a 50.

Prossima lezione β†’

Lezione 05 β€” Operazioni logiche
ANDLW, ANDWF, IORLW, IORWF, XORLW, XORWF
Mascherare bit, settare flag, confrontare nibble.

Β© Prof. D. Bertolino Β· PIC16 From Zero to Hero Β· WebPicSimulator Β· Lezione 04