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 WADDWF f,dβ somma W con un registro RAMSUBLW 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
| Modulo | 1 β Assembly Base |
| Lezione | 04 di 42 |
| Livello | ββ Principiante+ |
| Tempo | ~30 minuti |
| Istruzioni | 4 nuove |
| Flag STATUS | C, 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.
π΄ 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
ADDLW kSomma 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
ADDWF f,dSomma 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
SUBLW kAttenzione 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
SUBWF f,dLa 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
| Istruzione | Operazione | Destinazione | C | DC | Z |
|---|---|---|---|---|---|
ADDLW k | W + k | W | β | β | β |
ADDWF f,W | W + f | W | β | β | β |
ADDWF f,F | W + f | f | β | β | β |
SUBLW k | k β W | W | β (inv.) | β | β |
SUBWF f,W | f β W | W | β (inv.) | β | β |
SUBWF f,F | f β W | f | β (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:
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
| # | Istruzione | W | C | DC | Z | Note |
|---|---|---|---|---|---|---|
| 1 | ADDLW 0x20 | 0x50 | 0 | 0 | 0 | 0x30+0x20=0x50, nessun overflow |
| 2 | ADDLW 0x20 | 0x10 | 1 | 0 | 0 | 0xF0+0x20=0x110, troncato a 0x10 |
| 3 | ADDLW 0x02 | 0x00 | 1 | 0 | 1 | 0xFE+0x02=0x100 β 0, C=1 e Z=1 insieme |
| 4 | ADDWF A,F | 6 | 0 | 0 | 0 | A=20+6=26=0x1A, W invariato a 6 |
| 5 | SUBLW 0x1E | 0x14 | 1 | 1 | 0 | 30-10=20=0x14, C=1 (no borrow) |
| 6 | SUBLW 0x0A | 0xEC | 0 | 0 | 0 | 10-30=-20 β 0xEC (complemento a 2), C=0 (borrow!) |
| 7 | SUBWF B,W | 0x00 | 1 | 1 | 1 | B-W=20-20=0, C=1 (no borrow), Z=1 |
ποΈ Prova tu!
- Scrivi una sequenza che calcola
100 - 37e salva il risultato in una variabileRIS. Verifica nel simulatore cheRIS = 63 = 0x3Fe C=1. - Aggiungi al programma precedente una seconda operazione:
RIS + 200. Il risultato supera 255? Cosa vale C? - Sfida: come fai a calcolare
A - B(entrambe variabili in RAM) e mettere il risultato in una terza variabileDIFF? 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 logicheANDLW, ANDWF, IORLW, IORWF, XORLW, XORWF
Mascherare bit, settare flag, confrontare nibble.
Β© Prof. D. Bertolino Β· PIC16 From Zero to Hero Β· WebPicSimulator Β· Lezione 04