Appunti di Assembler 8086 – Prima Parte
Indice dei contenuti
- Cosa occorre
- Dove prelevare l’ambiente di lavoro
- Struttura della#cpu CPU 8086
- Prime istruzioni del linguaggio Assembler
- Interrupt di uso comune
La CPU intel 8086 è ormai largamente superata, anche se i moderni processori della serie x86, hanno ereditato con i necessari ampliamenti ed evoluzioni alcune sue caratteristiche.
Questi appunti anno lo scopo di sintetizzare alcuni concetti sull’uso del linguaggio Assmbler per questo processore.
Cosa occorre per scrivere un programma Assembler
Esistono vari software assemblatori e,io ho scelto il Turbi Assembler della Borland, in quanto evita problemi nel calcolo degli indirizzi di memoria (almeno una volta occorrerebbe vedere con il Debug come si scrivono gli indirizzi di memoria), e perché ance se un ambiente assemblativo comodo per la scrittura e la modifica di file sorgenti.
I File sorgenti in Assembler hanno l’estensione ASM, quindi ogni programma sorgente dell’Assembler avrà la sintassi nomefile.asm.
Una volta generato il file sorgente che si potrà scrivere con il comando Edit del dos (ad esempio edit primo.asm), occorre generare il file oggetto con il programma Assemblatore con la sintassi: tasm nomefile.asm, in caso di compilazione corretta, il programma crea un nuovo file che avrà lo stesso nome del sorgente ma estensione obj (file oggetto).
Se come sicuramente succederà vi sono degli errori nel programma il programma segnala la presenza di tali errori nelle righe indicate, e quindi occorre tornare alla fase di editing per correggere gli errori.
La fase successiva alla compilazione consiste nel linkaggio ovvero la creazione del file eseguibile vero e proprio con eventuali moduli esterni e ce genera un file di estensione “exe” o “com” secondo le impostazioni che il programmatore impone al comando tlink.
Per creare il file eseguibile occorre dare il comando tlink nomefile.obj, dove il nome file è il file generato precedentemente con il commando tasm. Una volta linkato il file sarà possibile eseguirlo semplicemnte digitando il nome del file dal prompt del DOS:
Dove prelevare l’ambiente di lavoro
Scaricare il TASM è abbastanza semplice anche se con le versioni di Windows a 64bit occorre utilizzare la suite Dosbox per emulare una piattaforma compatibile a 16bit con i programmi assemblatori.
Alla fine del documento sarà esposta una procedura semplice per aggirare tale problema nei sistemi operativi a 64 bit.
Struttura della CPU Intel 8086
Questa breve introduzione alla CPU 8086 non ha la pretesa di svelare tutti i dettagli ma di agevolare i nuovi programmatori ad un approccio più semplificato a tale ambiente che di per se molto ostico.
La CPU 8086 è stata la prima a 16 bit, prodotta da Intel, hce utilizzava un Bus dati a 16bit, un Bus Indirizzi a 20 bit condiviso con quello dati, e con una frequenza di circa 5 Mhz.
La CPU, era dotata di una serie di registri di uso generale a 16 bit AX; BX,CX, DX scomponibili all’occorrenza in 8 registri a 8 bit AL, AH, BL ,BH, CL, CH, DL, DH.
Tali registri sono utilizzati per le operazioni di Input e Output, le Istruzioni di Assegnazione e Calcolo, e per il trasferimento dati dalla Memoria RAM alla CPU, e dai dispositivi di I/O alla CPU.
Esistono poi altri registri denominati CS ,ES, DS, SS, IP, BP, SP, IP, FLAG, CS contiene l’indirizzo di memoria di partenza delle istruzioni del programma Assembler, il registro DS contiene l’indirizzo base di partenza dove sono memorizzati i dati ( eventuali dati definiti dall’utente nel programma), il registro ES contiene l’indirizzo base di partenza per un ulteriore spazio di memoria. I registri SS contiene l’indirizzo base di partenza per l’area di Stack un’area di memoria utilizzata come Pila.
Una Pila è una struttura dati LIFO ovvero l’ultimo dato a entrare è il primo ad uscire. I registri BP e SP contengono l’indirizzo della base dello stack e della testa dello stack. Ovviamente se nello stack sono presenti dati.
Il registro IP sta per puntatore istruzioni e contiene l’indirizzo della prossima istruzione da eseguire, mentre il registro Flag eaminato in dettaglio più avanti contiene dei bit che danno informazioni sulle ultima operazione eseguita ad esempio se il risultato di un’operazione è zero, negativa o in overflow o se è presente un riporto (Carry Flag).
Esistono ulteriori registri SI e DI ce sono i registri indice sorgente e destinazione.
Prime nozione sulle istruzioni Assembler
Un’istruzione Assembler in architettura CISC (Complex Istruction Set Architetture) è strutturata nella forma:
Codice Operando [Operando 1],[Operando 2]
ove Codice Operando è la tipologia di istruzione ad eseguire che viene prelevata dall’indirizzo di Memoria RAM indicato dal registro Contatore Programma durante la fase di Fetch. Gli Operandi sono gli argomenti delle istruzioni che possono essere anche facoltativi.
A titolo di esempio vediamo tre tipologie di istruzioni:
NOP
INT 21H
ADD AX,BX
L’istruzione (a) non prevede nessun operando in quanto è un’istruzione che non fa svolgere nessuna operazione alla CPU. Essa sta per No Operation, l’istruzione (b) invece prevede un operando e attiva un’interruzione sulla linea 21H. Per finire l’istruzione (c) somma due valori a 16 bit contenuti nei registri AX e BX ed è un’istruzione a 2 operandi.
La lunghezza diversa delle istruzioni genera il collo di bottiglia nell’architettura di Von Neumann, in quanto la CPU dopo aver prelevato l’istruzione dalla Memoria con la fase di Fetch deve riconoscerne la tipologia e tale operazione avviene con la fase di Decode.
In questo intervallo di tempo fra la fase di fetch e decode che consuma alcuni cicli di clock in quanto la memoria RAM ha tempi di accesso maggiori la CPU non compie nessuna operazione sprecando del tempo, che potrebbe essere utilizzato per l’esecuzione di altre operazioni. Fin dalla produzione del processore Intel 8086 era chiara la limitazione, ma nel corso degli anni con l’avanzare del progresso tecnologico i nuovi processori introdussero delle migliorie per aumentare le prestazioni. Tali migliorie saranno discusse più avanti.
La scrittura di un programma Assembler avviene mediante un editor solo testo come per altro già scritto prima, la struttura di un programma Assembler in Turbo Assembler ha delle direttive ben precise per definire alcune informazioni essenziali all’assemblatore e al collegatore (linker).
Primo programma Assembler
.MODEL SMALL
.STACK 100H
.DATA
.CODE
Inizio:
NOP
MOV AH,00H
MOV AL,4CH
INT 21H
END Inizio
Questo programma viene assemblato e linkato con la seguente sequenza di comandi:
tasm no.asm il file è stato chiamato no.asm
tlink no.obj il file con estensione obj è stato generato dal programma assemblatore TASM
L’esecuzione del programma avviene mediante la riga di comando:
no il file essendo un eseguibile EXE viene caricato e eseguito solo con il suo nome.
Per quanto riguarda il programma, il programma non fa nulla, fa aspettare alla CPU un ciclo di clock e poi esce al sistema operativo DOS.
In dettaglio le righe:
.MODEL SMALL
.STACK 100
.DATA
.CODE
definiscono la struttura del programma utilizzando un segmento di memoria comune per i dati, il codice, e l’area di stack che ha la dimensione di 256 byte infatti 100h è pari a 256.
Ogni programma deve essere racchiuso in un costrutto:
Etichetta:
…… istruzioni
End Etichetta
che indica l’inizio e la fine del codice del programma ovvero le istruzioni vere e proprie. All’interno del costrutto precedente il programma è costituito dalle seguenti linee di codice:
NOP
MOV AL,00H
MOV AH,4CH
INT 21H
La prima non fa nessuna operazione, la seconda , la terza e la quarta attivano un’interruzione sulla linea 21H, per l’uscita al DOS. Ogni Interruzione per essere attivata deve avere un indirizzo di memoria composto da due byte ove sarà reperito l’indirizzo di memoria della funzione (come se fosse un programma esterno) per l’uscita al sistema operativo. Il programma esterno si definisce ISR Interrupt Service Routine, mentre l’indirizzo di memoria viene definito anche Interrupt Handler.
Interrupt di uso comune
Nei programmi Assembler è molto importante imparare e implementare la gestione delle Interruzioni per la gestione dell’Input/Output.
Le prime interruzioni da gestire sono quelle per la gestione della tastiera e del monitor del calcolatore. Tali interruzioni sono gestite con lo schermo in modalità 25 righe per 80 colonne in modo testo. Esiste la possibilità di gestire anche lo schermo in modalità grafica, tale argomento sarà trattato più avanti perché introduce un livello di complessità maggiore.
La sequenza di istruzioni Assembler per l’attivazione di un’interruzione varia a seconda della tipologia di dispositivo di Input o Output si intende gestire.
Per la gestione della tastiera, l’interruzione che permette di inserire un carattere da tastiera, e memorizzarlo nel registro AL in formato Esadecimale, è:
MOV AH,00
INT 16H
Analizziamo meglio le due istruzioni; la prima dichiara quale sarà il servizio da gestire 00H, la tastiera, la seconda istruzione attiva l’interruzione numero 16H, il digitato da tastiera verrà memorizzato nel registro AL. Ad esempio il programma sotto riportato chiedere la digitazione di un tasto da tastiera.
.MODEL SMALL
.STACK 100H
.DATA
.CODE
INIZIO:
MOV AH,00H
INT 16h
MOV AL,00H
MOV AH,4C
INT 21H
END INIZIO
Nel momento in cui l’utente digita un carattere, ad esempio la “A”, nel registro AL verrà caricato il codice ASCII della lettera che vale 41H, basta consultare la tabella ASCII per verificare.
La seconda Interruzione provoca l’uscita al sistema operativo mediante le tre istruzioni
MOV AL,00H
MOV AH,4CH
INT 21H
che in modo compatto si possono anche sintetizzare in:
MOV AX,004CH
INT 21H.
Fine Prima Parte