EMU8086 e struttura di un programma Assembly 8086
Dal simulatore EMU8086 ai modelli .COM/.EXE, dalle direttive di segmento alle tre strutture di Böhm-Jacopini: come si scrive, si organizza e si debugga un programma in Assembly 8086.
1. EMU8086 — l'ambiente di simulazione e debug
EMU8086 è un assemblatore + simulatore che emula l'8086 reale: non solo compila, ma ti fa vedere registri, flag, memoria e opcode dopo ogni singola istruzione.
EMU8086 emula il microprocessore Intel 8086 (compatibile x86/AMD). A differenza di un editor generico, è un ambiente completo di sviluppo e debug che consente di osservare l'esecuzione istruzione per istruzione, aprendo automaticamente la finestra DOS per I/O interattivo.
Registri live
AX, BX, CX, DX, SI, DI, SP, BP, IP, FLAGS aggiornati dopo ogni step.
Dump esadecimale
Vedi come le variabili del Data Segment vengono scritte e lette.
Opcode reali
Per ogni mnemonico, l'opcode binario/esa — il ponte tra Assembly e bit.
Usa sempre Single Step all'inizio: metti un breakpoint prima di MUL o CMP e controlla come cambiano AX e i flag. In verifica ti chiedo di descrivere proprio quel passaggio.
1) Scrivi .asm → 2) Assemble (segnala errori) → 3) Emulate con Single Step per debug → 4) Run fino a MOV AH,4Ch / INT 21h. Se hai input da tastiera, EMU8086 apre DOS automaticamente.
2. Modelli di memoria — .COM e .EXE
L'8086 lavora a segmenti da 64 KB. Il formato dell'eseguibile decide come vengono organizzati prima dell'esecuzione.
| Caratteristica | .COM — tiny | .EXE — small (preferito) |
|---|---|---|
| Segmenti | Unico da 64 KB per codice+dati+stack | Separati: DATA, STACK, CODE, EXTRA |
| Avvio IP | ORG 100h — primi 256 byte = PSP | IP=0000h, CS punta al CODE |
| DS | Già puntato al segmento unico | Deve essere inizializzato esplicitamente via AX |
| Stack | SP=FFFEh (fondo segmento) | dichiarato: DB 100h DUP(?) |
| Dimensione | max ~64KB - 256B | più grande e strutturato |
Non esiste MOV DS, data né MOV DS, 1000h. I registri di segmento accettano solo un registro generale. La sequenza obbligatoria è sempre:MOV AX, data → MOV DS, AX. Se dimentichi questa inizializzazione, leggi dati casuali!
3. Struttura di un programma — 4 segmenti e direttive semplificate
Con le direttive standard descrivi esplicitamente i 4 segmenti. È il modello più vicino all'hardware.
Direttive semplificate — .model
Le direttive semplificate usano macro: meno verbosità, l'assembler gestisce automaticamente i segmenti. Modello più usato nel corso: small.
| Modello | Segm. codice | Segm. dati | Uso tipico |
|---|---|---|---|
| tiny | 1 condiviso | 1 condiviso | .COM tutto in un segmento |
| small | 1 | 1 | Programmi piccoli — standard corso |
| compact | 1 | multipli | Dati grandi, codice piccolo |
| medium | multipli | 1 | Codice grande |
| large | multipli | multipli | App grandi |
All'interrogazione: chiedetemi sempre ASSUME a cosa serve — è solo informativa per l'assembler (dice quali registri puntano a quali segmenti), non genera opcode. Invece MOV AX,data / MOV DS,AX genera codice vero!
4. Data Segment — variabili e costanti
Ogni variabile va dichiarata nel Data Segment con nome, dimensione e valore iniziale (? se non inizializzata).
1-2 byte
DB=Byte 8 bit 0-255, DW=Word 16 bit. Più usate.
4-8 byte
DD=DWord 32 bit, DQ=QWord 64 bit per indirizzi lunghi.
Costante simbolica
Non occupa memoria, sostituita a tempo di assemblaggio.
| Direttiva | Significato | Dimensione | Esempio |
|---|---|---|---|
| DB | Define Byte | 1 B | msg DB 'Ciao','$' |
| DW | Define Word | 2 B | n1 DW 345o |
| DD | Define DWord | 4 B | addr DD 12345678h |
| DQ | Define QWord | 8 B | big DQ 1 |
| DT | Define TByte | 10 B | BCD |
67d o 67 → decimale43h → esadecimale53o → ottale1001b → binario. Fondamentale saper convertire a mano: in verifica vi chiedo 345o → 229d.
EQU = costante simbolica, zero byte in memoria. DB/DW = variabile, occupa locazioni reali nel Data Segment. Le stringhe per INT 21h devono finire con $ altrimenti stampa spazzatura.
5. Teorema di Böhm-Jacopini — le tre strutture
Qualsiasi algoritmo computabile si può esprimere con solo tre strutture: sequenza, selezione, ciclo. In Assembly le implementiamo con CMP + salti.
Istruzioni lineari
Esecuzione una dopo l'altra — ADD, MOV, SUB in ordine.
if / if-else
CMP + JG/JL/JE + JMP per saltare il ramo alternativo.
while / for
Condizione + corpo + DEC + salto condizionato.
6. Esercizio 1 — Sequenza (a, b, C, D)
Date a=67d, b=53o, C=4h, D=1001b:
1) x = a + D
2) y = b + C
3) ris = x - y
Calcolo manuale: D=9d, quindi x=76d; b=43d, C=4d → y=47d; ris=29d=1Dh.
Per la sequenza, annota sempre il valore atteso di AL dopo ogni operazione. In EMU8086 puoi confrontare AL reale con il tuo calcolo — è il debug più didattico.
7. Esercizio 2 — Selezione if-else (n1=345o, n2=76h)
Se n1 > n2 → somma, altrimenti differenza. Conversioni: n1=345o=3×64+4×8+5=229d, n2=76h=7×16+6=118d → n1>n2 → somma = 347d.
Dopo il ramo else devi sempre JMP fine altrimenti esegui anche il ramo if! E usa JG/JL per signed, JA/JB per unsigned — qui con 229 e 118 sono positivi, entrambi funzionano, ma in verifica distingui.
8. Esercizio 3 — Ciclo FOR (fattoriale di 5)
5! = 5×4×3×2×1 =120. Contatore CL da 5 a 1, MUL CL ad ogni iterazione. Struttura do-while: corpo → DEC → CMP → JGE.
| Iter | CL prima | AX = AX × CL | CL dopo DEC |
|---|---|---|---|
| 1 | 5 | 1×5=5 | 4 |
| 2 | 4 | 5×4=20 | 3 |
| 3 | 3 | 20×3=60 | 2 |
| 4 | 2 | 60×2=120 | 1 |
| Fine | 1 | CL=1 → JGE non salta → esci | — |
9. Esercizio 4 — Ciclo WHILE (fattoriale di 5)
Condizione verificata PRIMA del corpo: se CL=1 all'avvio, il corpo non parte mai. Schema: controllo → CMP/JLE → corpo → DEC → JMP controllo.
Condizione in fondo
Corpo almeno 1 volta. DEC → CMP → JGE inizio.
Condizione in testa
Può non eseguire mai. CMP → JLE fine → JMP indietro.
Disegna sempre le due strutture a confronto. Se ti chiedo "che differenza tra FOR e WHILE in Assembly?" rispondi: posizione del test. Nel FOR il JGE/JG è dopo il corpo; nel WHILE il JLE è prima. Ricorda che MUL CL usa AL/AX implicitamente: risultato in AX (8 bit) o DX:AX (16 bit).
10. Riepilogo e concetti chiave
MOV AX,data / MOV DS,AX — mai MOV DS,valore..model small più usato, gestisce segmenti automaticamente.DB 28,30,25,27, buffer 10 DUP(?), stringhe con $, costanti EQU senza memoria.CMP + JG/JL/JE + JMP fine. Ciclo FOR (do-while) corpo→DEC→CMP→JGE, WHILE test in testa CMP→JLE→corpo→JMP.MOV AH,4Ch / INT 21h; basi: d dec, h hex, o oct, b bin — saper convertire 345o=229d, 76h=118d.📚 Fine modulo —
Ora sai strutturare un programma semplice in Assembly 8086