Assembly Base con NASM
Capitolo 1: Strumenti necessari per la sezione Assembly Base
La sezione Assembly Base si rivolge, non solo a chi vuole apprendere la
programmazione in Assembly, ma anche a chi non ha la minima nozione sul
funzionamento di un computer; per seguire questo tutorial non è richiesta quindi
alcuna conoscenza di informatica o di hardware.
1.1 Il linguaggio Assembly
I computer si suddividono in una serie di categorie chiamate famiglie hardware;
questa definizione è legata all'architettura interna che caratterizza ogni elaboratore
elettronico. Tutti i computer appartenenti alla stessa famiglia hardware presentano
una importantissima caratteristica chiamata compatibilità; compatibilità
significa che tutti i computer appartenenti alla stessa famiglia hardware possono
dialogare tra loro (il che equivale a dire che tutti i computer compatibili parlano lo
stesso linguaggio).
Il linguaggio parlato da un computer prende il nome di machine code (codice
macchina o linguaggio macchina); come vedremo nei capitoli successivi, il codice
macchina espresso in forma umana è costituito da una sequenza di cifre ciascuna
delle quali può assumere il valore 0 o 1 (per questo motivo si parla
anche di codice binario). Dal punto di vista dei circuiti elettronici del
computer, questi due valori rappresentano due possibili livelli di tensione assunti
da un segnale elettrico; possiamo associare, ad esempio, la tensione elettrica di
0 volt alla cifra 0 e la tensione elettrica di +5 volt alla
cifra 1.
Come si può facilmente intuire, per un essere umano sarebbe una follia pensare di
interagire con un computer attraverso il codice binario; si tenga presente comunque
che all'inizio degli anni 50 il codice binario rappresentava l'unico mezzo per
dialogare con gli elaboratori elettronici.
Proprio per risolvere questi problemi, si pensò allora di creare un apposito codice
che risultasse più comprensibile agli esseri umani; nacque così un codice chiamato
Assembly. Il codice Assembly è formato da una serie di mnemonici
espressi da termini come ADD, SUB, MUL, DIV, MOV,
etc; ciascuno di questi mnemonici corrisponde ad una ben precisa sequenza di cifre
binarie e chiaramente risulta molto più comprensibile del codice macchina. Il
linguaggio macchina e il linguaggio Assembly vengono anche chiamati low
level languages (linguaggi di basso livello); tale definizione si riferisce al
fatto che questi linguaggi corrispondono a quello "grossolano" (o basso), parlato dal
computer, in contrapposizione al linguaggio "raffinato" (o alto) parlato dagli esseri
umani.
Ogni piattaforma hardware ha il proprio linguaggio Assembly; appare evidente
quindi che i codici Assembly destinati ai computer appartenenti ad una
determinata piattaforma hardware, risultano incomprensibili ai computer appartenenti
ad un'altra piattaforma hardware. Per risolvere questo problema sono stati creati i
cosiddetti high level languages (linguaggi di alto livello); i linguaggi di alto
livello utilizzano una serie di mnemonici espressi da termini molto vicini al linguaggio
umano (generalmente inglese) come, ad esempio, IF, THEN, ELSE,
WHILE, REPEAT, UNTIL, etc. Un programma scritto con un linguaggio
di alto livello viene prima tradotto nel codice macchina della piattaforma hardware in
uso e poi inviato alla fase di elaborazione; in questo modo è possibile ottenere
l'indipendenza di un programma dalla particolare piattaforma hardware che si sta utilizzando.
Da queste considerazioni si possono dedurre i vantaggi e gli svantaggi, sia dei linguaggi
di basso livello, sia dei linguaggi di alto livello. I linguaggi di basso livello
presentano un grandissimo vantaggio rappresentato dalla capacità di spremere al massimo
tutto l'hardware disponibile nel computer; lo svantaggio principale è rappresentato dal
fatto di dipendere fortemente dalla piattaforma hardware in uso. I linguaggi di alto
livello presentano il grandissimo vantaggio di risultare indipendenti dalle diverse
piattaforme hardware; lo svantaggio principale è dato dal fatto che, come vedremo nei
successivi capitoli, questa indipendenza dall'hardware si paga (spesso a carissimo prezzo)
in termini di prestazioni.
1.2 Ambiente operativo
Tutte le considerazioni esposte nella sezione Assembly Base e in tutte le altre
sezioni di questo sito, si riferiscono ai computer appartenenti alla piattaforma
hardware che viene indicata con il termine PC i80x86; questa sigla indica i
cosiddetti Personal Computer basati sui microprocessori Intel o
compatibili, della famiglia 80x86. Il microprocessore rappresenta il cervello
pensante del computer e viene anche chiamato CPU o Central Processing Unit
(unità centrale di elaborazione). In passato questi computer venivano anche chiamati
IBM compatibili; tale definizione è legata al fatto che questa piattaforma
hardware è fortemente basata su tecnologie sviluppate inizialmente dalla IBM.
Uno dei primi PC della storia (quello che più ci interessa per i nostri scopi) è
stato il famoso XT8086 realizzato dalla IBM nei primi anni 80;
tale nome deriva dal fatto che questo PC era basato sulla CPU Intel 8086.
Successivamente sono stati realizzati PC basati su CPU sempre più potenti
ed evolute; si possono citare, in ordine cronologico, le CPU 80286, 80386
e 80486. La generazione di CPU successiva all'80486 viene indicata
con le sigle 80586 e 80686; tale generazione comprende le CPU AMD
Athlon, Intel Pentium, etc.
Una caratteristica fondamentale delle CPU 80x86 è la cosiddetta compatibilità
verso il basso. Questa definizione indica il fatto che un programma scritto per
un 8086, funziona perfettamente su tutte le CPU di classe superiore;
viceversa, un programma scritto espressamente, ad esempio, per un 80586, non
funziona sulle CPU di classe inferiore.
Per ottenere la compatibilità verso il basso, tutte le CPU della famiglia
80x86 sono in grado di simulare la modalità di funzionamento dell'8086;
questa modalità viene chiamata modalità reale 8086. Tutti i programmi di
esempio
(che potete trovare anche nella sezione Codice sorgente di esempio per la sezione assembly base dell’
Area Downloads di questo sito)
e presentati nella sezione Assembly Base si riferiscono a questa
modalità operativa delle CPU 80x86.
Si tenga presente che appena si accende il PC, tutte le CPU della
famiglia 80x86 vengono inizializzate in modalità reale; questa modalità
viene sfruttata dalle CPU di classe superiore per attivare altre modalità
operative più evolute, come la modalità protetta, che viene illustrata
in una apposita sezione di questo sito.
Per permettere a qualunque utente di utilizzare un computer senza la necessità di
conoscerne il funzionamento interno, vengono realizzati appositi programmi chiamati
Sistemi Operativi o SO; il SO di un computer può essere paragonato
al cruscotto e ai comandi di un'automobile. Sarebbe piuttosto difficile guidare
un'automobile senza avere a disposizione il volante, il freno, l'acceleratore, la spia
dell'olio, etc; attraverso questi strumenti l'automobilista può gestire facilmente la
sua auto senza la necessità di avere una laurea in ingegneria meccanica. Allo stesso
modo, sarebbe praticamente impossibile utilizzare un computer senza avere a disposizione
un SO; attraverso il SO anche un utente privo di qualsiasi conoscenza di
informatica può ordinare al computer di suonare un CD audio, di immagazzinare dati in
un supporto di memorizzazione, di ricevere o inviare dati via Internet, etc.
Nell'ambiente operativo rappresentato dalla modalità reale delle CPU 80x86, il
SO più famoso è sicuramente il DOS (Disk Operating System); tale
SO, pur essendo ormai obsoleto, viene ancora supportato (o emulato) dai nuovi
SO della famiglia Windows. In sostanza, anche in presenza di
Windows 9x, Windows XP, Windows 7, 8, etc, è possibile creare
ed eseguire programmi destinati al DOS; inoltre, esistono ottimi emulatori
DOS che girano sotto Linux e MacOSX.
Il DOS, grazie alla sua struttura semplice e "trasparente", si presta molto
bene per l'apprendimento dei concetti basilari del linguaggio Assembly; del
resto, è necessario tenere presente che le istruzioni fornite dal linguaggio
Assembly dipendono esclusivamente dalla piattaforma hardware che si sta
utilizzando e non dal SO.
Bisogna anche aggiungere che, per un programmatore Assembly, è fondamentale
conoscere la modalità reale supportata dal DOS; infatti, solo
attraverso questa conoscenza è possibile capire il perché della particolare
evoluzione che ha interessato le CPU della famiglia 80x86.
Tutti i programmi di esempio presentati nella sezione Assembly Base sono
espressamente destinati al SO DOS; riassumendo, l'ambiente operativo di
riferimento per la sezione Assembly Base è quello rappresentato dalla
modalità reale 8086 supportata dal DOS.
Molte versioni di Windows forniscono uno strumento chiamato Prompt di
MS-DOS (o prompt dei comandi); come è stato spiegato in precedenza, attraverso
tale strumento si ha a disposizione un ambiente DOS che simula perfettamente
il SO presente sui vecchi PC e permette quindi di eseguire programmi
destinati alla modalità reale 80x86.
Il prompt dei comandi è più che valido per seguire questi tutorial ma, considerando
il fatto che le future versioni di Windows potrebbero anche abbandonare il
supporto al DOS, conviene decisamente ricorrere ad una differente soluzione
che consiste nell'utilizzare una cosiddetta virtual machine (macchina virtuale)
o VM. Una VM è un potente software in grado di simulare una o più
piattaforme hardware, anche differenti da quella del computer su cui è installato;
in tal modo, su un qualunque PC basato su Windows, Linux,
MacOSX, etc, compatibilmente con la disponibilità di memoria (e di potenza
di calcolo), è possibile installare ed eseguire altri SO!
Una delle migliori VM disponibili gratuitamente è VirtualBox, fornita
dall'azienda Oracle; tale VM supporta una impressionante quantità di
SO, dai più nuovi ai più vecchi.
In una VM, il SO "ospitante" si chiama host, mentre ciascuno
dei SO "ospitati" si chiama guest; il guest può usufruire di
tutti i dispositivi messi a disposizione dall'host, come hard disk, lettori
CD/DVD, schede audio, schede di rete, etc. In certi casi, è persino possibile
simulare via software periferiche non presenti; ad esempio, proprio nel caso in cui
il guest sia il DOS, è possibile simulare lettori di floppy disk e
vecchie schede audio come la celebre Sound Blaster 16!
In abbinamento a VirtualBox possiamo usare uno dei migliori emulatori
DOS in circolazione, appartenente al mondo open source; si tratta del
conosciutissimo FreeDOS. In realtà, FreeDOS è un vero SO che
tra le sue caratteristiche ha una piena compatibilità con il DOS; a riprova
della sua affidabilità, basti notare che non è raro trovarlo su quei PC che,
su richiesta del cliente, vengono venduti senza Windows preinstallato.
Per i nostri scopi, l'uso di un emulatore DOS su una VM comporta
numerosi vantaggi, a cominciare dal fatto che questi strumenti ci permettono di
studiare l'Assembly 80x86 in modo del tutto indipendente dall'host
presente sul nostro computer; inoltre, cosa ancora più importante, una macchina
virtuale ci isola in modo adeguato dallo stesso host evitando così interferenze
indesiderate e garantendo di conseguenza un certo grado di sicurezza.
La Figura 1.1 mostra FreeDOS eseguito in VirtualBox.
Naturalmente, sono disponibili anche altri validi emulatori DOS; uno di essi è
DOSEMU, destinato all'ambiente Linux e utilizzabile come applicazione
indipendente, senza cioè la necessità di una VM.
Un altro esempio è DOSBox, disponibile per Windows, Linux,
MacOSX e altri SO, ma orientato soprattutto al supporto dei vecchi
giochi per MS-DOS; anche in questo caso non è necessaria una VM.
In alternativa, è persino possibile scaricare gratuitamente il vecchio MS-DOS
6.22 (ultima versione prodotta da Microsoft); in questo caso però è
necessaria una VM come per FreeDOS.
Da questo momento in poi, il termine DOS verrà utilizzato per indicare,
indifferentemente, FreeDOS, MS-DOS, il Prompt di MS-DOS e
i vari emulatori DOS; eventualmente, in caso di programmi incompatibili
con uno o più di tali ambienti operativi, verranno date tutte le necessarie
informazioni.
Nella sezione Sistemi operativi dell’
Area Downloads di questo sito
sono presenti tutte le informazioni necessarie per installare e
utilizzare FreeDOS e MS-DOS in VirtualBox; se si ha intenzione
di usare altri strumenti, si faccia riferimento alle relative istruzioni presenti su
Internet.
1.3 Strumenti di sviluppo per l'Assembly
I moderni linguaggi di programmazione vengono spesso venduti insieme a potenti ambienti
di sviluppo integrati chiamati IDE (Integrated Development Environment), che
permettono di automatizzare tutto il lavoro che il programmatore deve svolgere (sono
persino in grado di generare un programma a partire da uno schema disegnato sullo
schermo); per imparare a sfruttare totalmente questi IDE, bisogna leggere
manuali d'uso che spesso arrivano a superare le 500 pagine!
All'estremo opposto troviamo i programmatori Assembly, noti per la loro
avversione nei confronti di queste (presunte) comodità; d'altra parte, si sa che chi
programma in Assembly vuole avere il controllo totale sul computer e questo è
in netto contrasto con l'uso degli IDE troppo sofisticati. Un IDE è a
tutti gli effetti un programma in esecuzione e quindi potrebbe entrare in conflitto
con il programma Assembly che stiamo testando; l'ideale quando si lavora in
Assembly sarebbe avere il computer a completa disposizione del nostro programma.
Con il passare del tempo, ci si abitua persino a lavorare con la linea di comando
(Prompt del DOS per chi usa Windows) che permette di eseguire svariate
operazioni ad altissima velocità e con esigenze di memoria irrisorie.
Nel rispetto di questa filosofia, gli strumenti necessari per sviluppare programmi in
Assembly sono pochissimi e semplici; la dotazione minima è rappresentata dal
seguente elenco:
- un editor di testo
- un assembler
- un linker
L'editor di testo permette di creare, salvare, modificare
o caricare da un supporto di memorizzazione, un testo in formato
ASCII;
questa sigla sta per American Standard Code for Information Interchange (Codice
Standard Americano per l'Interscambio dell'Informazione). Tale standard definisce un
insieme di 256 codici numerici riconosciuti dai PC di tutto il mondo;
questo significa che, ad esempio, la sequenza di codici:
65 115 115 101 109 98 108 121
verrà tradotta e visualizzata da un qualsiasi editor di testo sotto forma della seguente
stringa (sequenza di caratteri):
Assembly
Questo avverrà su qualunque PC e in qualunque nazione del mondo.
Un testo (o qualunque altro tipo di dato) immagazzinato in un supporto di memorizzazione,
viene chiamato file; un file è in formato
ASCII
quando aprendolo e visualizzandolo con un editor di testo, ci appare perfettamente
leggibile. In contrapposizione ai file di testo troviamo i cosiddetti file binari
che possono contenere programmi eseguibili, immagini, musica, etc. I file binari per
essere visualizzati richiedono appositi programmi; se proviamo ad aprire un file binario
con un editor di testo, ci troviamo davanti ad una sequenza incomprensibile di lettere
dell'alfabeto, cifre, segni di punteggiatura, etc.
Un programma scritto in Assembly o in un qualsiasi linguaggio di programmazione,
viene chiamato codice sorgente e deve essere rigorosamente in formato
ASCII;
questo significa che per leggere, scrivere, modificare e salvare un programma
Assembly è necessario usare un qualunque editor di testo. Utilizzando, ad esempio,
strumenti come OpenOffice, LibreOffice, MS Office o WordPad,
bisogna ricordarsi di salvare il file come documento di testo, mentre nel caso di
NotePad (Blocco Note), dell'editor del DOS (EDIT.COM) o di editor
Linux come kate, kwrite e gedit, il formato testo è quello
predefinito.
La scelta dell'editor è una questione di gusti personali; in ogni caso, per rendere più
semplice la scrittura del codice e per ridurre al minimo il rischio di commettere errori
sintattici, si raccomanda l'installazione di un editor con supporto per la syntax
highlighting (sintassi a colori), grazie alla quale si possono evidenziare con
colori differenti le varie parti del codice sorgente. Su Internet si possono
reperire facilmente ottimi editor di questo tipo per tutti i SO; chiaramente,
conviene assicurarsi che venga fornito anche il supporto alla sintassi del linguaggio
Assembly.
L'assembler o assemblatore, è un programma che traduce il
codice sorgente in codice oggetto, generando (se non ci sono errori) un file con
estensione .OBJ chiamato object file; questo file contiene il codice
macchina del programma appena tradotto, più una serie di importanti informazioni
destinate al linker.
Il linker o collegatore, ha il compito di generare il file
in formato eseguibile (estensione .EXE o .COM) a partire dal codice oggetto.
Un programma Assembly può essere costituito da un unico file o da più file; ad
esempio, se il codice sorgente si trova nei tre file chiamati MAIN.ASM,
LIB1.ASM e LIB2.ASM, attraverso l'assembler si ottengono i tre file
MAIN.OBJ, LIB1.OBJ e LIB2.OBJ. Il linker parte da questi tre
moduli e, dopo aver risolto eventuali riferimenti incrociati tra essi, li collega assieme
generando (se non vengono trovati errori) un file in formato eseguibile chiamato
MAIN.EXE.
1.4 Assembler disponibili
Con il termine assembler generalmente si indica l'insieme formato almeno
dall'assemblatore e dal linker; molti assembler forniscono spesso diversi altri
strumenti molto utili, come gli editor per i file binari e i debuggers per
la ricerca degli errori nei programmi.
Questo tutorial si basa sul noto assembler NASM (acronimo di Netwide
Assembler); si tratta di un potentissimo assembler open source le cui
caratteristiche non hanno niente da invidiare a prodotti commerciali più famosi
come il Microsoft Macro Assembler (MASM) e il Borland Turbo
Assembler (TASM).
L'assembler fornito con NASM è in grado di generare object file in
numerosi formati compatibili con i vari linker e SO (compreso, ovviamente,
il DOS); di conseguenza, per la creazione degli eseguibili è possibile
utilizzare i linker per DOS come quelli forniti da altri assemblatori
(MASM, TASM, etc) o compilatori (Borland C, Microsoft Quick
Basic, etc). Come vedremo nei successivi capitoli, sono inoltre disponibili
diversi linker open source o free; anche in questo caso, si tratta
di strumenti che non hanno nulla da invidiare ai prodotti professionali a pagamento.
Nella sezione Compilatori assembly, c++ e altri dell’
Area Downloads
di questo sito sono presenti tutte le informazioni necessarie per installare e
utilizzare NASM.