ISA 8086 — Set di Istruzioni e Interrupt
Il vocabolario della CPU: dal MOV ai flag, dalle maschere di bit ai salti condizionati, fino a INT 21h per gestire input/output in Assembly 8086.
1. L'ISA — Instruction Set Architecture
L'ISA è il contratto tra software e hardware: definisce istruzioni, formati, modi di indirizzamento e comportamento dei flag. L'8086 è il vocabolario base di tutti gli x86.
L'ISA (Instruction Set Architecture) è l'insieme completo di istruzioni che un processore è in grado di eseguire — è il "vocabolario" della CPU. L'ISA dell'8086 definisce le istruzioni, i formati, i modi di indirizzamento e il comportamento dei flag: è il contratto tra il software e l'hardware.
MOV PUSH POP
Movimentazione dati tra registri, memoria e stack. XCHG, LEA per indirizzi.
ADD SUB MUL DIV
Calcoli interi, complemento a 2, prodotto doppio, divisione con resto.
AND OR SHL SHR
Maschere di bit, ottimizzazione ×/÷ potenze di 2, rotazioni.
2. I flag — il registro di stato FLAGS
Molte istruzioni non restituiscono il risultato solo in un registro — modificano anche i flag nel registro FLAGS. I flag sono bit singoli che memorizzano informazioni sul risultato dell'ultima operazione e guidano i salti condizionati.
| Flag | Nome | Si attiva quando... | Usato da |
|---|---|---|---|
| ZF | Zero Flag | Il risultato è zero (o i due operandi di CMP sono uguali) | JE, JNE, LOOPE, LOOPNE |
| SF | Sign Flag | Bit più significativo =1 (risultato negativo in complemento a 2) | JG, JL, JGE, JLE |
| CF | Carry Flag | Riporto/prestito fuori dal MSB (overflow senza segno) | JA, JB, ADC, SBB |
| OF | Overflow Flag | Risultato non entra nel tipo con segno | JO, JNO |
| PF | Parity Flag | N° bit a 1 pari nel risultato | Controllo parità seriale |
Per l'interrogazione ricorda: MOV non tocca mai i flag. ADD/SUB/CMP sì, INC/DEC no sul CF. Se vedi ZF=1 dopo CMP sai già che i due valori sono uguali.
3. Istruzioni di trasferimento dati
MOV — copia di dati
MOV è l'istruzione più usata dell'ISA — copia il valore del secondo operando nel primo. Non è uno spostamento: la sorgente rimane invariata. Non modifica i flag.
Non è mai possibile avere entrambi gli operandi in memoria nella stessa MOV. Per copiare da memoria a memoria servono due istruzioni: prima carica in un registro, poi scrivi.
PUSH e POP — gestione dello stack
PUSH inserisce un valore a 16 bit in cima allo stack decrementando SP di 2, POP preleva il valore incrementando SP di 2. Lo stack cresce verso il basso.
XCHG e LEA
MOV SI, [array] carica il dato contenuto in array. LEA SI, [array] carica l'indirizzo di array — equivale a &array in C. Indispensabile per passare puntatori a stringhe o buffer alle routine INT 21h.
4. Istruzioni aritmetiche
ADD e SUB — con complemento a 2
Se il risultato di SUB è negativo, la CPU lo rappresenta in complemento a 2. Su 8 bit: -21d → 21d=00010101 → NOT=11101010 → +1 = 11101011 = EBh, SF=1.
ADC e SBB — con riporto e prestito
Per somme su operandi più grandi del registro (es. 32 bit su CPU a 16 bit), si usano ADC e SBB che includono CF dell'operazione precedente.
MUL — moltiplicazione
MUL moltiplica sempre usando AL o AX come operando implicito. Il risultato è sempre il doppio della dimensione — per evitare overflow.
AL × op8 → AX
MOV AL,50 · MOV BL,10 · MUL BL → AX=500d=01F4h
AX × op16 → DX:AX
MOV AX,1000 · MOV BX,500 · MUL BX → DX:AX=500000d=0x7A120 → DX=0007h AX=A120h
DIV — divisione
AX ÷ op8 → AL quoziente · AH resto
AX=100, BL=30 → AL=3, AH=10
DX:AX ÷ op16 → AX quoziente · DX resto
DX:AX=100000, BX=100 → AX=1000, DX=0
INC, DEC, NEG, CMP
CMP op1,op2 esegue internamente op1-op2 ma scarta il risultato — aggiorna solo ZF, SF, CF, OF. Se op1=op2 ZF=1. Se op1<op2 CF=1,SF=1. Se op1>op2 tutti 0. Sempre seguita da Jcc.
5. Istruzioni logiche e di shift
Operazioni bitwise — AND, OR, XOR, NOT
Operano bit per bit. Fondamentali per flag di stato, maschere, azzeramento veloce.
Azzerare bit (masking)
MOV AL,11001010b · AND AL,00001111b → 00001010b. Tronca nibble alto.
Impostare bit
MOV AL,10110000b · OR AL,00000111b → 10110111b.
In Sistemi e Reti usiamo AND per estrarre la rete da IP: 192.168.1.10 AND 255.255.255.0 → 192.168.1.0. Stesso meccanismo in Assembly per isolare bit di stato.
SHL, SHR, ROL, ROR
Shift sposta e perde bit (o in CF). Rotazione fa rientrare il bit uscente dall'altro lato.
SHL di N = ×2ⁿ in 1 ciclo vs molti cicli di MUL. Nei loop ad alte prestazioni usa shift per potenze di 2. SHR per ÷2ⁿ intera.
6. Controllo del flusso — salti e cicli
JMP — salto incondizionato
CMP + salti condizionati — if/else
Coppia CMP + Jcc è il mattone di ogni if/else in Assembly.
| Istruzione | Condizione | Flag | Interpretazione |
|---|---|---|---|
| JE / JZ | op1 = op2 | ZF=1 | Uguale / Zero |
| JNE / JNZ | op1 ≠ op2 | ZF=0 | Diverso / Non zero |
| JG | op1 > op2 | ZF=0 e SF=OF | Maggiore con segno |
| JA | op1 > op2 | CF=0 e ZF=0 | Maggiore senza segno |
| JL | op1 < op2 | SF≠OF | Minore con segno |
| JB | op1 < op2 | CF=1 | Minore senza segno |
| JGE / JAE | op1 ≥ op2 | SF=OF / CF=0 | Maggiore o uguale |
| JLE / JBE | op1 ≤ op2 | ZF=1 o SF≠OF | Minore o uguale |
Stessi bit, significato diverso: AL=10 (0x0A), BL=-30 (0xE2 =226 senza segno). CMP AL,BL → con segno (JG) AL>BL → salta. Senza segno (JA) AL
LOOP — cicli con contatore
LOOP usa CX come contatore implicito: decrementa CX e salta se CX≠0. Equivale a for con CX iterazioni.
Salta se CX≠0
Dopo decremento automatico di CX.
CX≠0 e ZF=1
Preceduta da CMP, utile per ricerca.
CX≠0 e ZF=0
Continua fino a trovare o esaurire CX.
CALL e RET — subroutine
7. Interrupt e I/O
Un interrupt è un evento che sospende il ciclo fetch-decode-execute: la CPU salva IP e FLAGS nello stack ed esegue l'Interrupt Handler (ISR). IRET ripristina il contesto.
I programmi Assembly devono interagire con tastiera, schermo e altri dispositivi. In x86 questo avviene attraverso gli interrupt software.
INT N (0–255)
Numero interrupt identifica servizio.
Salvataggio FLAGS e IP
Disabilita interrupt, salva stato su stack SS:SP.
INT 21h — i servizi DOS
Interrupt più usato in DOS: INT 21h. Servizio selezionato caricando codice in AH.
| AH | Servizio | Input | Output |
|---|---|---|---|
| 01h | Leggi carattere da tastiera con echo | — | AL = ASCII tasto |
| 02h | Scrivi carattere a video | DL = ASCII | — |
| 09h | Stampa stringa a video | DS:DX = indirizzo stringa terminata da $ | — |
| 0Ah | Leggi stringa con buffer | DS:DX = indirizzo buffer | Buffer riempito |
| 4Ch | Termina programma | AL = codice uscita | — |
In Emu8086 usa LEA DX,msg prima di INT 21h/09h. Ricorda il '$' finale altrimenti stampa spazzatura. Per input sicuro usa AH=0Ah con buffer predefinito.
8. Riepilogo — quadro delle istruzioni ISA 8086
| Categoria | Istruzioni principali | Nota chiave |
|---|---|---|
| Trasferimento | MOV PUSH POP XCHG LEA | MOV non modifica flag · LEA carica indirizzi non valori |
| Aritmetica | ADD ADC SUB SBB MUL DIV INC DEC NEG CMP | MUL: AL×op→AX · AX×op→DX:AX · CMP scarta risultato |
| Logica | AND OR XOR NOT | XOR reg,reg azzera · AND per maschere |
| Shift/Rotazione | SHL SHR ROL ROR | SHL/SHR: ×/÷ per potenze di 2 in 1 ciclo |
| Salto incond. | JMP CALL RET | CALL salva IP su stack · RET lo recupera |
| Salto condiz. | JE JNE JG JA JL JB JGE JLE… | J* con segno (JG/JL) · J* senza segno (JA/JB) |
| Cicli | LOOP LOOPE LOOPNE | Usano CX come contatore implicito — CX-- poi controlla |
| Interrupt | INT N IRET | INT 21h + AH = servizio DOS per I/O |
9. Verifica e attività in Emu8086
🔬 Attività pratica
Apri Emu8086 e realizza i seguenti mini-programmi. Usa la cheatsheet Assembly 8086 come riferimento.
- Scrivi un programma che legge un carattere con INT 21h/01h e, se è una lettera minuscola, la converte in maiuscola usando AND 11011111b e la stampa.
- Implementa somma 1..10 con LOOP: verifica che AX =55d (0x37). Cosa succede se dimentichi MOV CX,10?
- Usa SHL per moltiplicare AL=7 per 8 senza MUL. Confronta i cicli con emulatore: quanti cicli risparmi?
- Gestisci l'errore DIV per zero: cosa mostra Emu8086? Come proteggeresti il codice con CMP e JE prima di DIV?
- Esercizio INT 21h/09h: stampa due stringhe diverse a seconda che il carattere letto sia 's' o 'n' (simula conferma).
La differenza ASCII tra 'a' (0x61=01100001) e 'A' (0x41=01000001) è il bit 5. AND con 11011111b (0xDF) azzera quel bit → minuscola→maiuscola. Per controllo intervallo: CMP AL,'a' / JB non_minuscola / CMP AL,'z' / JA non_minuscola. Questo mostra AND come maschera.
📚 Prossimo passo — Ambiente di simulazione Emu8086
Ora che conosci l'ISA, vedremo come strutturare un programma completo in Emu8086, usare segmenti, direttive e debugger per testare i tuoi primi programmi. Tieni aperta la cheatsheet Assembly.