Win32 Assembly

Capitolo 1: Strumenti necessari per la sezione Win32 Assembly

Nella sezione Win32 Assembly vengono illustrate le tecniche generali che si utilizzano per lo sviluppo dei programmi Assembly destinati a "girare" in ambiente Windows; il termine Win32 indica tutte le versioni a 32 bit del sistema operativo Windows, come Windows 95, Windows 98, Windows ME, Windows NT, Windows 2000, Windows XP (che esiste anche in versione a 64 bit).
Naturalmente si da' per scontato il fatto che chi legge questa sezione abbia una buona conoscenza generale della programmazione in Assembly; in particolare, e' importante avere una certa dimestichezza con il set di istruzioni a 32 bit e soprattutto con gli indirizzamenti a 32 bit. Bisogna osservare inoltre che il sistema operativo Win32 sfrutta la modalita' protetta delle CPU 80386 e superiori; e' importante quindi avere anche una conoscenza generale dei concetti che stanno alla base di questa modalita' operativa delle CPU. Ricordiamo le principali novita' che caratterizzano la modalita' operativa protetta a 32 bit:

* I segmenti di programma possono avere l'attributo SIZE di tipo USE32.
* Gli indirizzamenti predefiniti sono di tipo NEAR a 32 bit.
* E' possibile utilizzare qualsiasi registro generale a 32 bit come registro puntatore.
* Lo stack viene gestito dalla CPU attraverso ESP, e dal programmatore attraverso EBP.
* La dimensione predefinita per gli operandi immediati e' di 32 bit.

Ulteriori dettagli vengono esposti nel capitolo successivo.
In ogni caso, per scrivere programmi Assembly in ambiente Win32 non e' necessario destreggiarsi tra descrittori di segmento, selettori, task switching, etc; tutti questi aspetti vengono infatti gestiti dal sistema operativo e non dal programmatore. E' chiaro pero' che se si e' interessati agli aspetti piu' nascosti di Windows e' necessaria una conoscenza piuttosto approfondita della programmazione in modalita' protetta e dei concetti che stanno alla base della progettazione dei sistemi operativi (da ora in poi chiamati SO); le sezioni Assembly Base, Assembly Avanzato e Modalita' Protetta rappresentano una buona base di partenza per chi fosse interessato a questi argomenti.

1.1 Strumenti di sviluppo

Per poter sviluppare programmi Windows in Assembly e' necessario dotarsi di una serie di adeguati strumenti; la dotazione minima comprende:

* un editor di testo
* un assembler a 32 bit
* un linker a 32 bit
* un compilatore di risorse
* un editor di icone
* il Windows SDK


L'editor di testo ci serve per creare, modificare, salvare su disco o leggere dal disco i files contenenti il codice sorgente dei nostri programmi Assembly; come al solito, questi files devono essere rigorosamente in formato ASCII perche questo e' cio' che viene richiesto dall'assembler. Per motivi di chiarezza e di stile, si consiglia di rispettare tutte le convenzioni per le estensioni dei files contenenti programmi Assembly; i files contenenti il codice sorgente dovrebbero utilizzare l'estensione ASM, i files contenenti direttive, dichiarazioni, prototipi di procedure, etc, dovrebbero utilizzare l'estensione INC, i files contenenti macro dovrebbero utilizzare l'estensione MAC, e cosi' via.

L'assembler ha il compito di convertire il codice sorgente del nostro programma in codice oggetto; come al solito, se il codice sorgente e' distribuito su piu' files, verranno generati altrettanti files con estensione OBJ contenenti il codice macchina del nostro programma. E' chiaro che per poter sviluppare programmi per Win32 e' necessario un assembler in grado di supportare il set di istruzioni a 32 bit; se poi si vogliono utilizzare istruzioni disponibili solo in modalita' protetta (come LLDT), e' necessario un assembler che accetti direttive del tipo .386p (set di istruzioni a 32 bit in modalita' protetta).

Il linker ha il compito di collegare tra loro i vari moduli oggetto e di generare il programma finale in formato eseguibile (estensione EXE); il linker deve essere capace di generare eseguibili a 32 bit compatibili con Windows. Infatti, il formato EXE utilizzato da Windows e' differente dall'analogo formato utilizzato in ambiente DOS; la struttura degli eseguibili per Windows viene analizzata in un apposito capitolo della sezione Win32 Assembly.

Il compilatore di risorse e' uno strumento di sviluppo tipico dell'ambiente Windows; questo particolare compilatore opera sui cosiddetti Resource Files (files di risorse) di Windows. Come si intuisce dal nome, un file di risorse e' destinato a contenere una serie di risorse che verranno utilizzate da una applicazione Windows; tra le risorse piu' conosciute possiamo citare i menu, le icone, le immagini in formato bitmap, etc. I files di risorse utilizzano l'estensione predefinita RC e anche in questo caso devono essere in formato ASCII; il compilatore di risorse compila il FILE.RC e lo converte in un FILE.RES che e' compatibile con il formato oggetto (OBJ). A questo punto il FILE.RES viene passato al linker che provvede a collegarlo ai vari moduli OBJ per poter ottenere il programma finale in versione EXE.

L'editor di icone e' un'altro strumento di sviluppo tipico dei SO o ambienti operativi che utilizzano interfacce grafiche; uno degli oggetti piu' caratteristici delle interfacce grafiche e' rappresentato proprio dall'icona che e' una sorta di bitmap formata in genere da 16 x 16 o 32 x 32 pixel. Nell'interfaccia grafica di Windows, di Linux, di OS/2, etc, ad ogni programma viene associata un'icona chiamata icona del programma; l'editor di icone ci permette proprio di creare o modificare icone, e di salvarle su disco nel tipico formato di immagine ICO utilizzato da Windows. A rigore bisogna dire che l'editor di icone non e' uno strumento indispensabile; infatti, se il programmatore non specifica una icona personalizzata, Windows provvedera' ad assegnare al programma una icona predefinita. Su Internet sono reperibili numerosi editor di icone, dai piu' semplici ai piu' sofisticati; per trovarli ci si puo' servire di un motore di ricerca e utilizzare un criterio di ricerca del tipo windows AND iconedit.

Il Windows SDK rappresenta uno strumento senza il quale non sarebbe possibile sviluppare programmi per Windows; la sigla SDK sta per Software Development Kit e cioe' kit software per lo sviluppo dei programmi Windows. L'SDK rappresenta una collezione di librerie contenenti tutti gli strumenti che Windows mette a disposizione dei programmatori per la gestione dei files, gestione della memoria, gestione della grafica, multimedia, telecomunicazioni, etc; l'SDK occupa su disco diversi Mb, ed e' importante procurarsi la versione piu' aggiornata possibile per poter usufruire di tutte le nuove funzionalita' messe a disposizione dalle versioni piu' recenti di Windows. L'SDK di Windows e' scritto principalmente in linguaggio C standard (ANSI C), mentre le parti piu' critiche, strettamente legate alla piattaforma hardware utilizzata, sono state scritte guarda caso in Assembly; queste considerazioni ci fanno capire che i programmi Windows scritti in C o Assembly risultano piu' semplici, compatti e veloci degli analoghi programmi scritti con qualunque altro linguaggio di programmazione.

1.2 Assembler disponibili

L'assembler che offre il supporto piu' completo per lo sviluppo di applicazioni Windows e' sicuramente il Microsoft Macro Assembler (MASM); l'aspetto piu' interessante e' dato dal fatto che la Microsoft da un po' di tempo ha deciso di distribuirlo "gratis" via Internet (con la solita chilometrica licenza d'uso che tutti evitano di leggere premendo direttamente il pulsante [Accept]). Grazie ad un rapporto di collaborazione tra la Microsoft e un gruppo di programmatori, e' nato il progetto MASM32 che ha lo scopo di promuovere l'uso dell'Assembly per lo sviluppo di applicazioni Win32; MASM32 fornisce ai programmatori interessati un vasto insieme di strumenti di sviluppo che comprende tra l'altro: l'assembler, il linker, il compilatore di risorse, l'SDK, un ottimo editor di testo (Quick Editor), etc. Nella sezione Links Utili e' presente un link al sito ufficiale del progetto MASM32; accedendo a questo sito e' possibile scaricare MASM32 (circa 4 Mb) insieme a diversi esempi di applicazioni Windows scritte in Assembly. Tra l'altro, lo stesso MASM32 contiene una notevole quantita' di eccezionali esempi pratici scritti dagli stessi programmatori della Microsoft; nella sezione Downloads, premendo il pulsante [Info] si ottengono le informazioni necessarie per installare MASM32.

Un'altro assembler professionale che permette di sviluppare applicazioni Windows e' il Borland Turbo Assembler (TASM) che a differenza del MASM e' pero' a pagamento; si tratta comunque di un assembler nettamente piu' affidabile del MASM, tanto che la stragrande maggioranza dei programmatori Assembly lo considera il miglior assembler disponibile nel mondo dei PC. Del resto la Borland e' una software house resa celebre da mitici compilatori e interpreti come il Turbo Basic, il Turbo Pascal, il C/C++, Delphi, etc, che si differenziano dagli analoghi prodotti Microsoft per la quasi totale assenza di bugs; si puo' dire che grazie alla Borland, milioni di programmatori in tutto il mondo hanno appreso l'arte della programmazione.
La versione piu' aggiornata del TASM e' la 5.0 che mette a disposizione l'assembler a 32 bit (TASM32.EXE), il linker a 32 bit (TLINK32.EXE) in grado di generare eseguibili per Windows, il compilatore di risorse e numerosi altri strumenti. Per i fortunati possessori del TASM, si presenta un problema legato al fatto che l'SDK fornito con la versione 5.0 dell'assembler risale all'era paleozoica di Windows 95; si tratta quindi di un SDK molto vecchio e pressoche' inutilizzabile. Un vero programmatore Assembly pero' non puo' certo fermarsi davanti a questi ostacoli; vediamo allora come puo' essere risolto il problema in modo da poter utilizzare non solo TASM 5.0 ma persino le versioni precedenti. La prima idea che viene in mente puo' essere quella di installare MASM32 per utilizzare poi il relativo SDK con TASM; questa idea pero' non funziona in quanto le librerie usate dal MASM contengono codice oggetto in formato COFF, mentre il TASM e tutti i vari compilatori Borland, accettano solo codice oggetto in formato standard OMF (vedere la sezione Downloads per la documentazione ufficiale su questi due formati). La strada che dobbiamo seguire consiste allora nel procurarci la versione piu' recente possibile dell'SDK che la Borland distribuisce insieme ai suoi compilatori; questa opportunita' ci viene offerta dal fatto che da tempo la Borland distribuisce gratuitamente le versioni a linea di comando dei suoi potentissimi compilatori C/C++ come il Borland C/C++ compiler 5.x e il Borland C++ Builder 5.x (o versioni superiori). Si possono seguire due strade in quanto questi prodotti sono disponibili sia sui CD allegati alle varie riviste di programmazione, sia via Internet nel sito della Borland (vedere la sezione Links Utili); in entrambi i casi, bisogna registrarsi gratuitamente on-line. Una volta installato il compilatore C/C++ abbiamo finalmente a disposizione l'SDK, che generalmente viene sistemato in una sottocartella chiamata Lib; se lo si desidera si puo' anche copiare l'SDK nella cartella dove abbiamo installato il TASM (creando un'analoga sottocartella Lib). Osserviamo che il compilatore C/C++ ci mette a disposizione anche il linker e il compilatore di risorse; tutti questi strumenti possono essere utilizzati al posto degli analoghi strumenti forniti con il Turbo Assembler. A questo punto siamo "quasi" pronti per utilizzare TASM nello sviluppo di applicazioni Win32; l'ultimo passo da compiere viene descritto nel seguito del capitolo.

Tra i vari assembler che si possono utilizzare per lo sviluppo di applicazioni Windows, una menzione speciale spetta al prodotto freeware NASM; la versione a 32 bit di NASM supporta il formato oggetto COFF e puo' essere quindi usata in combinazione con l'SDK fornito con MASM32. Chi volesse usare NASM per sviluppare applicazioni Windows, puo' reperire tutta la documentazione necessaria via Internet; tutti gli esempi proposti nella sezione Win32 Assembly si riferiscono esclusivamente a MASM e TASM.

1.3 Gli include files

Dopo aver installato MASM32 sul disco fisso (generalmente nella cartella masm32), si nota la presenza di due sottocartelle chiamate Lib e Include; la sottocartella Lib contiene ovviamente la collezione di librerie dell'SDK, mentre la sottocartella Include contiene gli include files. Come gia' sappiamo, gli include files dell'Assembly equivalgono agli header files del C/C++ e sono destinati a contenere prototipi di procedure, dichiarazioni di strutture, di union, di costanti simboliche, etc; in questo caso tutti questi prototipi e dichiarazioni servono per poter interfacciare i nostri programmi Assembly con l'SDK di Windows.
Nel caso del TASM, dobbiamo tener presente che stiamo utilizzando l'SDK fornito in dotazione ai compilatori C/C++ della Borland; nella sottocartella Include del compilatore troveremo quindi non gli include files ma gli header files necessari per interfacciare i programmi C/C++ con l'SDK. Fortunatamente, le versioni piu' recenti del TASM, supportano la sintassi avanzata imposta dalla Microsoft per le dichiarazioni presenti negli include files del MASM32 (vedere il Capitolo 28 della sezione Assembly Base); questo significa che nella gran parte dei casi, gli include files di MASM32 possono essere utilizzati con il TASM. Possiamo allora copiare gli include files di MASM32 in una apposita sottocartella Include di TASM. Purtroppo, come abbiamo visto nella sezione Assembly Base, esistono delle differenze tra MASM e TASM per quanto riguarda in particolare la visibilita' dei membri di strutture e union; tanto per citare un esempio, in MASM il nome di un membro di una struttura e' locale alla struttura stessa e puo' essere quindi riutilizzato per identificare un membro di un'altra struttura, un parametro di una procedura, una variabile locale, etc. In TASM invece il nome di un membro di una struttura e' visibile anche all'esterno della struttura stessa e non puo' quindi essere ridefinito; in caso contrario TASM genera un errore. Nei vari esempi che vengono presentati nella sezione Win32 Assembly, vengono illustrati i rimedi che bisogna adottare per eliminare queste situazioni di errore.

1.4 L'include file Windows.inc

Tra tutti gli include files, il piu' importante di tutti e' sicuramente Windows.inc che equivale all'header file Windows.h usato dai programmi C/C++ per Windows e viene chiamato include file principale; il file Windows.inc contiene al suo interno una autentica marea di dichiarazioni di procedure, di strutture, di union, di costanti, di tipi di dati (typedef), etc. Queste dichiarazioni sono indispensabili per poter sviluppare qualunque applicazione per Windows; se si osserva il codice sorgente del modulo principale di un programma per Windows, si nota che all'inizio e' sempre presente una direttiva del tipo:
INCLUDE ..\Include\Windows.inc
All'interno di Windows.inc si possono trovare ad esempio dichiarazioni del tipo:
UINT TYPEDEF DWORD
Questa dichiarazione crea un nuovo tipo di dato UINT che rappresenta il tipo intero senza segno a 32 bit. E' importantissimo che il programmatore dia un'occhiata a questo include file per farsi un'idea precisa del suo contenuto; si tenga presente infatti che in fase di sviluppo dei programmi Assembly per Windows, la consultazione di Windows.inc diventa una pratica frequentissima.
Il file Windows.inc relativo a MASM32 viene tenuto costantemente aggiornato da diversi programmatori; nella sezione Downloads e' possibile scaricare l'aggiornamento piu' recente curato da Iczelion. Purtroppo questo file e' inutilizzabile con TASM a causa delle incompatibilita' descritte in precedenza; per questo motivo, chi utilizza TASM e' tenuto a scaricare un apposito include file Windows.inc. Nella sezione Downloads e' presente oltre ad un generico file Windows.inc per TASM, anche un analogo file Win32.inc; il file Win32.inc viene costantemente aggiornato da Ra.M. Software.

1.5 Documentazione

Per poter utilizzare l'SDK il programmatore deve conoscere i nomi con i quali vengono chiamate le funzioni, procedure, macro, strutture, union, costanti simboliche, etc, presenti nell'SDK stesso; tutte queste dichiarazioni utilizzano la classica sintassi del linguaggio C, e nel loro insieme formano la cosiddetta Windows API. La sigla API sta per Application Programming Interface (interfaccia per la programmazione delle applicazioni) e indica appunto l'interfaccia che bisogna utilizzare per accedere agli strumenti dell'SDK; si tratta di centinaia e centinaia di nomi che un programmatore non puo' certo ricordare a memoria. E' molto importante quindi procurarsi un manuale di riferimento sull'API di Windows, che deve essere il piu' possibile aggiornato; fortunatamente grazie a Internet e' possibile scaricare un file generalmente chiamato win32.zip e contenente un documento chiamato Win32 Programmer's Reference in formato HLP (Help File di Windows). Questo file, una volta decompresso occupa su disco oltre 24 Mb, ma nonostante le dimensioni consistenti, contiene una versione dell'API aggiornata al 1996; in ogni caso si tratta di un documento che si rivela di estrema utilita' per il programmatore. La documentazione completa dell'API di Windows occupa diversi CD-ROM ed e' ottenibile a pagamento dalla Microsoft; in alternativa, la versione completa ed aggiornata dell'API e' consultabile gratuitamente via Internet nel sito della stessa Microsoft. Nella sezione Links Utili e' presente un link al sito web di MrCrimson che oltre al file win32.zip contiene anche una eccezionale collezione di ducumenti sull'API di Windows sempre in formato HLP.

Nota importante
Si tenga presente che diversi siti web citati nella sezione Links Utili vengono gestiti da programmatori e appassionati; la sopravvivenza di tali siti (e quindi anche di questo) e' legata spesso alle decisioni di chi li ospita o di chi li gestisce. E' del tutto normale quindi che questi siti possano scomparire improvvisamente per poi riapparire magari ad un altro indirizzo Internet; nei limiti del possibile la sezione Links Utili viene costantemente aggiornata in modo da garantire il corretto funzionamento dei vari links.