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