Assembly 8086: Struttura Istruzione e Modi di Indirizzamento
Dal codice macchina ai mnemonici: come la CPU trova i dati — immediato, diretto e tutte le varianti indirette fino a base+indice+displacement. La formula EA che devi saper calcolare.
1. Assembly — il linguaggio mnemonico del processore
Assembly è la rappresentazione simbolica 1:1 del codice macchina: ogni mnemonico leggibile corrisponde esattamente a un opcode binario che la CPU esegue direttamente, senza livelli di astrazione.
Il codice macchina — le sequenze di bit che la CPU esegue direttamente — è incomprensibile all'uomo. L'Assembly è la sua rappresentazione simbolica: ogni istruzione binaria corrisponde esattamente a un mnemonico leggibile. Non c'è astrazione: Assembly e codice macchina sono equivalenti uno a uno.
Codice macchina
1011 0000 0100 1101
1000 1001 1100 0011
1010 0001 0110 1010
Sequenze binarie dirette.
Assembly
MOV AL, 4Dh
MOV BX, AX
MOV AX, [6Ah]
Mnemonici leggibili, stesso controllo.
Ogni riga Assembly viene tradotta dall'assemblatore (assembler) nel corrispondente opcode binario. Il vantaggio è fondamentale: si scrive in simboli mnemonici e si ottiene il controllo assoluto sull'hardware — senza rinunciare alla leggibilità.
Quando vedi MOV pensa sempre "copia, non sposta": la sorgente resta invariata. È la domanda trabocchetto classica in verifica. Se ti chiedono cosa succede a BX dopo MOV AX,BX, rispondi: BX resta uguale, AX diventa uguale a BX.
2. Struttura di un'istruzione Assembly x86
Un'istruzione Assembly x86 segue una sintassi precisa e può contenere fino a quattro elementi:
- LABEL (opzionale): nome simbolico dell'indirizzo di questa istruzione in memoria. Usata per salti (
JMP loop_start) e chiamate. - OPCODE (obbligatorio): il mnemonico dell'operazione — MOV, ADD, SUB, JMP, CALL... corrisponde direttamente al byte opcode binario.
- Operando destinazione: dove va il risultato.
- Operando sorgente: da dove viene il dato.
In loop_start: MOV AX, BX — loop_start è la label per saltarci, MOV è l'opcode obbligatorio, AX è la destinazione, BX la sorgente. Se inverti AX e BX inverti il flusso dei dati!
Confondere la sintassi Intel con AT&T: in Intel (8086) è MOV dest, sorg. In AT&T (usata da GAS/Linux) è invertita mov sorg, dest. In EMU8086 e in questa materia usiamo SEMPRE Intel.
3. Indirizzamento immediato
Indirizzamento immediato: il dato è scritto direttamente nell'istruzione stessa — nessun accesso a memoria o registro sorgente. 1 passo, massima velocità.
Nell'indirizzamento immediato il dato è parte dell'istruzione — subito dopo l'opcode. La CPU non deve cercarlo altrove.
Ideale per inizializzare registri con valori costanti noti a tempo di compilazione: contatori, maschere di bit, valori di configurazione. È la modalità più veloce perché la CPU non deve accedere alla RAM.
4. Indirizzamento diretto
Entrambi gli operandi sono registri oppure un operando è una locazione di memoria specificata direttamente dall'offset nell'istruzione, indicato tra parentesi quadre.
Da registro a registro
Diretto reg→reg è tutto interno alla CPU: nessuna attesa di RAM, 1 solo passo. Per la verifica ricorda: dopo MOV AX,BX — AX = valore vecchio di BX, BX resta identico.
Da registro a memoria e viceversa
Nell'8086 l'indirizzo fisico a 20 bit si calcola sempre come segmento × 16 + offset. Per gli accessi ai dati il registro di segmento è DS (Data Segment). Formula: EA = DS × 10h + offset. DS×10h significa DS shiftato di 4 bit a sinistra (×16 decimale).
5. Indirizzamento indiretto
Indirizzamento indiretto: l'istruzione non contiene il dato né il suo indirizzo diretto — contiene dove trovare l'indirizzo (un registro). Il dato finale è sempre in memoria.
Il meccanismo permette di cambiare dinamicamente a runtime l'indirizzo puntato, semplicemente modificando il registro indice — base di array, stringhe e strutture dati dinamiche.
Tramite registro (register indirect)
Modificando SI a runtime (INC SI), puoi scorrere un array in memoria senza modificare l'istruzione stessa — è la base di cicli e strutture dati dinamiche in Assembly. In C equivale a *ptr dove incrementi il puntatore.
Tramite registro e displacement
Al contenuto del registro indice si aggiunge un ulteriore displacement (spiazzamento fisso scritto nell'istruzione) per raggiungere una locazione specifica rispetto all'indirizzo base puntato dal registro.
6. Base + Indice e Base + Indice + Displacement
Base + Indice: EA = DS×10h + BX/BP + SI/DI. Base+Indice+Displacement aggiunge un offset fisso: massima flessibilità per array di strutture — base = inizio array, indice = elemento, displacement = campo.
L'indirizzo effettivo si calcola sommando il contenuto di un registro base (BX o BP) e di un registro indice (SI o DI). Permette di navigare strutture dati bidimensionali — il base punta alla struttura, l'indice al singolo elemento.
Quando usi BP come base, il segmento di default non è DS ma SS (Stack Segment): MOV AX, [BP][SI] usa SS:BP+SI. È pensato per accedere a parametri e variabili locali sullo stack — fondamentale per procedure e chiamate CALL.
Hai un array di 30 studenti, ogni studente occupa 10 byte (2 byte ID + 8 byte nome + 1 byte voto? semplifichiamo 10). BX punta all'inizio array, SI scorre di 10 in 10 per elemento, 06h è l'offset del campo voto. MOV AL, 06h[BX][SI] legge il voto corrente — poi ADD SI,10 per studente successivo. È esattamente studenti[i].voto in C!
7. Quadro comparativo — tutti i metodi
Tabella riassuntiva che devi saper riprodurre in verifica — metodi, formula EA, passi e uso tipico.
| Metodo | Sintassi esempio | Formula EA | Passi | Uso tipico |
|---|---|---|---|---|
| Immediato | MOV AL, 4Dh | — (dato nell'istruzione) | 1 | Costanti, inizializzazioni |
| Diretto reg→reg | MOV AX, BX | — (solo registri) | 1 | Copia rapida tra registri |
| Diretto reg↔mem | MOV AX, [6Ah] | DS×10h + offset | 2 | Variabili globali a indirizzo fisso |
| Indiretto via reg | MOV AX, [SI] | DS×10h + SI | 2 | Puntatori, scorrimento array |
| Indiretto + disp | MOV AX, 03h[SI] | DS×10h + SI + disp | 3 | Accesso a campi di strutture |
| Base + indice | MOV AX, [BX][DI] | DS×10h + BX + DI | 2 | Array bidimensionali, matrici |
| Base + ind + disp | MOV AX, 02h[BX][SI] | DS×10h + BX + SI + disp | 3 | Array di strutture — max flessibilità |
Conta le parentesi: immediato = nessun [] , diretto reg→reg = nessun [] , diretto mem = [numero fisso], indiretto = [registro]. Quando vedi due registri tra [] è base+indice, se c'è anche un numero è base+indice+displacement. EA sempre: segmento×16 + tutto quello che è dentro le quadre sommato.
8. Riepilogo e concetti chiave
📚 Prossimo passo — ISA: Instruction Set Architecture dell'8086
Ora che sai DOVE la CPU prende i dati, vedrai COSA può fare con quei dati: tutte le istruzioni dell'8086, i flag e gli interrupt. Fondamentale per scrivere i primi programmi in EMU8086.