Sistemi e Reti - EMU8086 Struttura Programma Assembly - Lezione 08
Sistemi e Reti · Anno 3 · Modulo 2 · Lezione 08
✍ Autore: profgiagnotti · Materia: Sistemi e Reti

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.

⏱ 55 min 📚 Anno 3 🧠 EMU8086 · Assembly 8086 💻 Segmenti · DB/DW · Sequenza/Selezione/Ciclo 📚 Esercizi Assembly 8086 →
// OBIETTIVI DI APPRENDIMENTO
✓Conoscere l'ambiente EMU8086 e le sue funzionalità di ispezione registri, memoria e opcode.
✓Distinguere i modelli .COM (tiny, ORG 100h, PSP) e .EXE (segmenti separati, DS da inizializzare).
✓Strutturare un programma con direttive standard (DATA/STACK/CODE/EXTRA) e semplificate (.model small).
✓Dichiarare variabili con DB/DW/DD/DQ, array e stringhe con $ e costanti con EQU senza occupare memoria.
✓Implementare sequenza, selezione con CMP/Jcc e cicli FOR (do-while) e WHILE (test in testa) in Assembly.

1. EMU8086 — l'ambiente di simulazione e debug

📌 Definizione da ricordare

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.

01 · ISPEZIONE

Registri live

AX, BX, CX, DX, SI, DI, SP, BP, IP, FLAGS aggiornati dopo ogni step.

02 · MEMORIA

Dump esadecimale

Vedi come le variabili del Data Segment vengono scritte e lette.

03 · CODICE MACCHINA

Opcode reali

Per ogni mnemonico, l'opcode binario/esa — il ponte tra Assembly e bit.

💬 Tip del docente

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.

🎯 Workflow in laboratorio

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.

EDITOR .asm Scrittura ASSEMBLER .com / .exe + errori EMU + DEBUG Single Step, Registri DOS WINDOW I/O interattivo

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)
SegmentiUnico da 64 KB per codice+dati+stackSeparati: DATA, STACK, CODE, EXTRA
Avvio IPORG 100h — primi 256 byte = PSPIP=0000h, CS punta al CODE
DSGià puntato al segmento unicoDeve essere inizializzato esplicitamente via AX
StackSP=FFFEh (fondo segmento) dichiarato: DB 100h DUP(?)
Dimensionemax ~64KB - 256Bpiù grande e strutturato
ASM · template .COM
; template minimo .COM ORG 100h start: ; codice qui MOV AH, 4Ch INT 21h
ASM · template .EXE semplificato
; template .EXE con direttive semplificate .model small .stack 100h .data ; variabili .code start: MOV AX, @data MOV DS, AX ; codice MOV AH, 4Ch INT 21h END start
⚠️ Errore comune — DS

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.

DATA SEGMENTvariabili — DSDB, DW, EQU STACK SEGMENTritorno — SS:SPDUP(?) 100h CODE SEGMENTistruzioni — CS:IPASSUME + INT 21h EXTRA SEGMENTarea extra — ES, facoltativostringhe, destinazioni
ASM · template completo .EXE direttive standard
data SEGMENT variabile DB 42d messaggio DB 'Ciao!', '$' ; $ terminatore per INT 21h 09h risultato DB ? COSTANTE EQU 10h ; costante simbolica, non occupa memoria data ENDS stack SEGMENT STACK DB 100h DUP(?) ; riserva 256 byte stack stack ENDS code SEGMENT ASSUME CS:code, DS:data, SS:stack start: MOV AX, data MOV DS, AX ; inizializza DS obbligatorio MOV AL, variabile ADD AL, COSTANTE MOV risultato, AL MOV AH, 4Ch ; termina programma INT 21h code ENDS END start

Direttive semplificate — .model

Le direttive semplificate usano macro: meno verbosità, l'assembler gestisce automaticamente i segmenti. Modello più usato nel corso: small.

ModelloSegm. codiceSegm. datiUso tipico
tiny1 condiviso1 condiviso.COM tutto in un segmento
small11Programmi piccoli — standard corso
compact1multipliDati grandi, codice piccolo
mediummultipli1Codice grande
largemultiplimultipliApp grandi
💬 Tip del docente

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).

01 · DB / DW

1-2 byte

DB=Byte 8 bit 0-255, DW=Word 16 bit. Più usate.

02 · DD / DQ

4-8 byte

DD=DWord 32 bit, DQ=QWord 64 bit per indirizzi lunghi.

03 · EQU

Costante simbolica

Non occupa memoria, sostituita a tempo di assemblaggio.

DirettivaSignificatoDimensioneEsempio
DBDefine Byte1 Bmsg DB 'Ciao','$'
DWDefine Word2 Bn1 DW 345o
DDDefine DWord4 Baddr DD 12345678h
DQDefine QWord8 Bbig DQ 1
DTDefine TByte10 BBCD
ASM · esempi dichiarazione variabili — dal sorgente originale
; variabili numeriche con basi diverse a DB 67d ; 1 byte - 67 decimale b DB 53o ; 1 byte - 53 ottale = 43 decimale n1 DW 345o ; 2 byte - 345o = 229 decimale (3*64+4*8+5) n2 DW 76h ; 2 byte - 76h = 118 decimale ; non inizializzate x DB ? y DB ? ris DB ? somma DW ? differenza DW ? ; costanti EQU - non occupano memoria C EQU 4h D EQU 1001b ; 1001b = 9 decimale ; array e stringhe voti DB 28d, 30d, 25d, 27d buffer DB 10 DUP(?) ; 10 byte buffer vuoto msg DB 'Risultato: ', '$' ; $ obbligatorio per INT 21h AH=09h carattere DB 'A'
🎯 Basi numeriche in EMU8086

67d o 67 → decimale
43h → esadecimale
53o → ottale
1001b → binario. Fondamentale saper convertire a mano: in verifica vi chiedo 345o → 229d.

⚠️ EQU vs DB

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

📌 Teorema

Qualsiasi algoritmo computabile si può esprimere con solo tre strutture: sequenza, selezione, ciclo. In Assembly le implementiamo con CMP + salti.

→ SEQUENZA

Istruzioni lineari

Esecuzione una dopo l'altra — ADD, MOV, SUB in ordine.

◇ SELEZIONE

if / if-else

CMP + JG/JL/JE + JMP per saltare il ramo alternativo.

↺ CICLO

while / for

Condizione + corpo + DEC + salto condizionato.

SEQUENZA MOV AL,a ADD AL,D MOV x,AL SELEZIONE CMP AX, n2 JG ramo_maggiore JMP fine CICLO CMP / JLE / MUL DEC + JMP/JGE

6. Esercizio 1 — Sequenza (a, b, C, D)

🎯 Traccia originale — mantieni tutti i concetti

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.

ASM · esercizio 1 sequenza — codice originale completo
data SEGMENT a DB 67d b DB 53o ; 53 ottale = 43 decimale C EQU 4h D EQU 1001b ; 9 decimale x DB ? y DB ? ris DB ? data ENDS stack SEGMENT STACK DB 100h DUP(?) stack ENDS code SEGMENT ASSUME CS:code, DS:data, SS:stack start: MOV AX, data MOV DS, AX ; x = a + D MOV AL, a ADD AL, D ; 67+9=76d MOV x, AL ; y = b + C MOV AL, b ADD AL, C ; 43+4=47d MOV y, AL ; ris = x - y MOV AL, x SUB AL, y ; 76-47=29d=1Dh MOV ris, AL MOV AH, 4Ch INT 21h code ENDS END start
💬 Tip del docente

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)

🎯 Traccia originale

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.

ASM · esercizio 2 selezione — codice originale
data SEGMENT n1 DW 345o ; 229d - DW perché >255 n2 DW 76h ; 118d somma DW ? differenza DW ? data ENDS stack SEGMENT STACK DB 100h DUP(?) stack ENDS code SEGMENT ASSUME CS:code, DS:data, SS:stack start: MOV AX, data MOV DS, AX MOV AX, n1 CMP AX, n2 ; imposta i flag JG ramo_maggiore ; se n1>n2 salta ; else: n1 <= n2 SUB AX, n2 MOV differenza, AX JMP fine ; salta il ramo if ramo_maggiore: ADD AX, n2 ; 229+118=347d MOV somma, AX fine: MOV AH, 4Ch INT 21h code ENDS END start
⚠️ Errore comune — salti

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)

🎯 Traccia — simulare FOR

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.

ASM · fattoriale FOR — codice originale
data SEGMENT numero DB 5d risultato DW 1d ; accumulatore =1 data ENDS stack SEGMENT STACK DB 100h DUP(?) stack ENDS code SEGMENT ASSUME CS:code, DS:data, SS:stack start: MOV AX, data MOV DS, AX MOV AX, risultato ; AX=1 MOV CL, numero ; CL=5 ciclo_for: ; inizio corpo MUL CL ; AX = AX * CL DEC CL CMP CL, 1d JGE ciclo_for ; se CL>=1 continua (condizione in fondo) MOV risultato, AX ; 120d = 78h MOV AH, 4Ch INT 21h code ENDS END start
IterCL primaAX = AX × CLCL dopo DEC
151×5=54
245×4=203
3320×3=602
4260×2=1201
Fine1CL=1 → JGE non salta → esci—

9. Esercizio 4 — Ciclo WHILE (fattoriale di 5)

🎯 Traccia — stessa funzione, logica WHILE

Condizione verificata PRIMA del corpo: se CL=1 all'avvio, il corpo non parte mai. Schema: controllo → CMP/JLE → corpo → DEC → JMP controllo.

ASM · fattoriale WHILE — codice originale
data SEGMENT numero DB 5d risultato DW 1d data ENDS stack SEGMENT STACK DB 100h DUP(?) stack ENDS code SEGMENT ASSUME CS:code, DS:data, SS:stack start: MOV AX, data MOV DS, AX MOV AX, risultato MOV CL, numero controllo_while: ; test condizione PRIMA CMP CL, 1d JLE fine_while ; se CL<=1 esci MUL CL DEC CL JMP controllo_while ; torna al controllo fine_while: MOV risultato, AX MOV AH, 4Ch INT 21h code ENDS END start
FOR · do-while

Condizione in fondo

Corpo almeno 1 volta. DEC → CMP → JGE inizio.

WHILE · test in testa

Condizione in testa

Può non eseguire mai. CMP → JLE fine → JMP indietro.

💬 Tip del docente per verifica

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).

✓EMU8086 emula 8086 con ispezione registri, dump memoria e opcode — workflow Edit → Assemble → Single Step → Run con DOS window per I/O.
✓.COM = un segmento 64KB da ORG 100h (PSP), .EXE = segmenti separati, DS inizializzato con MOV AX,data / MOV DS,AX — mai MOV DS,valore.
✓Direttive standard: DATA/STACK/CODE/EXTRA + ASSUME. Semplificate: .model small più usato, gestisce segmenti automaticamente.
✓Data: DB 1B, DW 2B, DD 4B, DQ 8B; array DB 28,30,25,27, buffer 10 DUP(?), stringhe con $, costanti EQU senza memoria.
✓Selezione: CMP + JG/JL/JE + JMP fine. Ciclo FOR (do-while) corpo→DEC→CMP→JGE, WHILE test in testa CMP→JLE→corpo→JMP.
✓Terminazione sempre 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