- Utilizzare il linguaggio specifico della micro-programmazione e dell'assembly per modellare il funzionamento dell'hardware.
- Comprendere l'interazione tra software applicativo e sistema operativo tramite le chiamate di sistema (Interrupt).
- Analizzare e implementare procedure di input/output a basso livello.
- Utilizzare ambienti di simulazione per il collaudo di programmi di controllo.
L'Output e l'Interrupt 21h
Per poter comunicare con l'utente, un programma Assembly deve inviare dati alla periferica di output (il monitor). In un ambiente a basso livello come quello dei file .com (standard MS-DOS), non abbiamo a disposizione funzioni come printf o cout. Dobbiamo invece invocare i servizi del Sistema Operativo tramite gli Interrupt.
Il Meccanismo degli Interrupt
Un interrupt (INT) è una chiamata a una routine predefinita che il sistema operativo (o DOS, in EMU8086) esegue per te. Serve a comunicare con l’hardware o il sistema senza dover conoscere tutti i dettagli delle porte, buffer e registri.
Ti permette di fare cose come:
- stampare a video (AH = 09h)
- leggere un tasto (AH = 01h)
- emettere un beep (AH = 02h)
- uscire dal programma (AH = 4Ch)
L'istruzione INT 21h è la porta d'accesso ai servizi del DOS. Prima di chiamare l'interrupt, dobbiamo istruire la CPU su quale specifica operazione vogliamo compiere caricando un codice identificativo nel registro AH.
| AH (Codice Funzione) | Descrizione | Parametri richiesti |
|---|---|---|
| 02h | Visualizza un singolo carattere ASCII | Il carattere deve essere in DL |
| 09h | Visualizza una stringa di testo | L'indirizzo della stringa deve essere in DX |
| 4Ch | Termina l'esecuzione del programma | AL può contenere il return code (solitamente 0) |
La Stringa in Assembly: Il Terminatore "$"
A differenza dei linguaggi di alto livello che usano il terminatore null (\0), la funzione 09h del DOS richiede che la stringa termini obbligatoriamente con il carattere $. Se questo manca, il sistema continuerà a stampare i dati presenti nelle celle di memoria successive fino a trovare un simbolo di dollaro casuale, causando errori visivi o blocchi del sistema.
| Istruzione | Descrizione | Esempio |
|---|---|---|
| MOV | Copia un valore in un registro o memoria | MOV AH, 09h |
| LEA | Load Effective Address: carica l'indirizzo della variabile in un registro | LEA DX, msg |
| CMP | Confronta due valori (non modifica registri, ma imposta i flags) | CMP AL, 1 |
| JE | Jump if Equal: salta se i flag indicano uguaglianza (ZF=1) | JE pezzo_ok |
| JMP | Salta incondizionatamente a una label | JMP fine |
| INT | Interruzione software: chiama i servizi DOS (INT 21h, etc.) | INT 21h |
LABORATORIO
I/O Video su EMU8086
In questo laboratorio imparerai a stampare caratteri singoli e intere frasi utilizzando le funzioni di sistema.
- Emulatore EMU8086
- Mappa dei caratteri ASCII
1 Stampa di un carattere singolo
Scriviamo un piccolo programma che visualizzi la lettera 'Z' sullo schermo.
ORG 100h MOV AH, 02h ; Prepariamo la funzione per la stampa di un carattere MOV DL, 'Z' ; Carichiamo il carattere nel registro DL INT 21h ; Eseguiamo la chiamata di sistema MOV AH, 4Ch ; Funzione per chiudere il programma correttamente INT 21h END
2 Stampa di una stringa
Per stampare una frase, dobbiamo usare la funzione 09h e definire una variabile in memoria tramite la direttiva DB (Define Byte).
ORG 100h
; CODICE
MOV AH, 09h ; Funzione stampa stringa
LEA DX, messaggio ; LEA carica l'indirizzo (offset) della variabile in DX
INT 21h ; Visualizza il testo
MOV AH, 4Ch
INT 21h
; DATI
messaggio DB "Benvenuti nel Laboratorio ITP$"
END
3 Esercizio: Sistema di Selezione Scarti (Controllo Qualità)
Scenario: State programmando il software di una stazione di controllo qualità. Un sensore rileva se un pezzo è conforme o difettoso.
Logica del programma:
Il programma deve simulare la lettura di un valore (nel nostro caso lo caricheremo manualmente nel registro AL).
- Se AL = 1: Il pezzo è OK. Stampa "PEZZO CONFORME$".
- Se AL = 0: Il pezzo è difettoso. Stampa "SCARTO!$" e attiva il segnale acustico (Beep).
ORG 100h
; SIMULAZIONE INPUT SENSORE (Cambia questo valore per testare i due casi)
MOV AL, 1 ; 1 = OK, 0 = Errore
; LOGICA DI SELEZIONE (IF)
CMP AL, 1 ; Confronta il valore in AL con 1
JE pezzo_ok ; Se sono uguali (Jump If Equal), vai alla label pezzo_ok
; PARTE ELSE (Se AL non è 1)
MOV AH, 09h
LEA DX, msg_err ; Carica "SCARTO!$"
INT 21h
MOV AH, 02h ; Funzione segnale acustico
MOV DL, 07h ; Codice ASCII Beep
INT 21h
JMP fine ; Salta alla fine per non eseguire il blocco OK
pezzo_ok: ; PARTE THEN
MOV AH, 09h
LEA DX, msg_ok ; Carica "PEZZO CONFORME$"
INT 21h
fine:
MOV AH, 4Ch ; Chiusura programma
INT 21h
; AREA DATI
msg_ok DB "ESITO: PEZZO CONFORME$"
msg_err DB "ATTENZIONE: SCARTO!$"
END
- Copiate il codice in EMU8086.
- Eseguite l'emulazione con MOV AL, 1 e osservate il monitor.
- Cambiate la riga in MOV AL, 0, ricompilate e verificate che il messaggio cambi e che l'altoparlante (virtuale) emetta il suono.
4 Perché abbiamo usato JMP fine?
Notate che dopo la stampa del messaggio di errore abbiamo inserito un JMP fine.
Senza quel salto, la CPU continuerebbe a leggere le istruzioni riga dopo riga, finendo per stampare anche il messaggio "PEZZO CONFORME" subito dopo lo scarto. In Assembly, dobbiamo gestire manualmente l'uscita dai rami decisionali.
Confronto tra RET e END in EMU8086
| Caratteristica | RET | END |
|---|---|---|
| Tipo | Istruzione eseguibile dalla CPU | Direttiva dell'assemblatore |
| Genera codice | Sì, diventa codice macchina | No, non genera codice |
| Scopo | Ritorna all’indirizzo in cima allo stack (usato dopo una CALL) | Indica la fine del sorgente all’assemblatore |
| Quando la legge la CPU | Runtime, durante l’esecuzione | Mai, è ignorata dalla CPU |
| Quando la legge l’assemblatore | Il compilatore lo converte in codice macchina | Compile-time, serve solo per sapere dove finisce il sorgente |
| Uso corretto | Solo per terminare procedure dopo una CALL | Alla fine del file sorgente |
| Effetto in .COM senza CALL | “Funziona” perché lo stack iniziale punta al DOS, ma non è sicuro | Nessun effetto sul programma |
| Alternativa moderna per uscire | INT 21h, AH=4Ch | — |