Ciao a
tutti! E così avete deciso di imparare l'assembly…bravi ragazzi! Non sarà
facile, vi avverto…ma con un po' di buona volontà potrete diventare tutti degli
ottimi asm-coders. In queste lezioni cercherò di partire da zero, e di non
tralasciare niente.
Beh, direi di
iniziare subito, elencando i tools che verranno usati in questa prima lezione:
un assemblatore. Io userò l'A86, un buon assembler shareware e semplice da
usare. Lo trovate a qui.
un qualsiasi editor di testo, ad esempio il notepad oppure l'"edit.com"
del Dos.
una lista di interrupt, ad esempio quella di Ralph Brown, che trovate qui.
Questa lista non è strettamente necessaria…tuttavia è meglio averla, perché
poi la userete spesso come "technical reference". A proposito: non
preoccupatevi se non sapete cos'è un interrupt, dopo vedremo tutto con calma.
E’ necessario utilizzare un editor di testo: praticamente tutti
gli assemblatori, infatti, non hanno un ambiente integrato (cioè non hanno un
loro editor) ma funzionano a riga di comando.
Per prima cosa, quindi,
creiamo un file in cui verrà salvato il codice del nostro primo programma in
assembly…chiamatelo come volete, ma è meglio se gli assegnate l’estensione
“.asm”. Io l’ho chiamato “lezione1.asm”. E’ meglio crearlo nella directory in
cui è stato copiato l’A86. Apriamo il file con l’editor, ed iniziamo a scrivere
il programma!
Uhm, il programma più semplice che possiamo scrivere è
quello che non fa nulla…l’unica operazione che deve fare è il ritorno al Dos. Il
ritorno al sistema operativo è indispensabile; sotto Dos bisogna fare così:
mov ah,4ch
mov al,00h
int 21h
Scriviamo queste tre linee nel file “.asm”, e salviamo il file. A questo
punto, dobbiamo compilare il codice che abbiamo appena scritto. Con l’A86 è
semplice: basta prendere il file “.asm” e trascinarlo sul programma “a86.com”
(oppure, una volta aperto il Prompt del Dos, basta posizionarsi nella directory
in cui è stato copiato l’A86 e digitare “a86 lezione1.asm”). Se non ci sono
stati problemi, vediamo comparire nella directory il file “lezione1.com”.
Proviamo a lanciarlo, e vediamo che non fa assolutamente niente…gran cosa, eh?
Prima di capire il significato di quelle tre righe di codice,
aggiungiamo qualche altra operazione in modo da visualizzare qualcosa sullo
schermo (mi sembra il minimo…). Allora, apriamo di nuovo il nostro
“lezione1.asm” e aggiungiamo:
mov ah,02
mov dl,65 ;codice ascii della lettera ‘A’
int 21h
Attenzione: è necessario aggiungere queste due linee prima di “mov
ah,4ch / mov al,00h / int 21h”. Ricompiliamo con l’A86 e proviamo a lanciare
“lezione.com”. Wow, qualcosa è successo! Viene visualizzata la lettera “A”.
Ma ora, alt un attimo! Vediamo di capire bene cosa succede in queste
poche linee di codice. Uhm, ci sono alcune parole che si ripetono… “mov” e
“int”: sono due istruzioni del processore. Le istruzioni del processore sono
tutto ciò di cui si compone la programmazione in assembly, sono i comandi di
questo linguaggio; attraverso queste istruzioni, noi diciamo al processore di
svolgere un determinato compito. In realtà, questi “compiti”, svolti dal
processore, sono piuttosto limitati…cioè ogni istruzione, presa da sola, fa
pochissimo: può eseguire un’operazione matematica, oppure memorizzare un dato in
memoria…ma, per esempio, non ci sono istruzioni che, da sole, permettono di
scrivere stringhe di caratteri. Per questa ragione, spesso, sono necessarie
parecchie istruzioni anche solo per eseguire un singolo compito…ma non
scoraggiatevi! Queste piccole istruzioni sono, in realtà, il potere del
linguaggio assembly: è proprio grazie a loro che, con l’asm, si possono
realizzare cose che con gli altri linguaggi di programmazione non si possono
fare.
Ok, ora che vi ho spiegato cos’è un’istruzione, analizziamo il
significato delle due istruzioni “mov” e “int”.
“Mov” muove…e non è un
gioco di parole: l’istruzione “mov” serve proprio per muovere dei valori
numerici da un posto ad un altro, per esempio dalla memoria del computer ad un
registro del processore o viceversa, oppure tra due registri (un registro è una
parte del processore che contiene dei valori numerici; ogni registro può
contenere un valore numerico, con un limite fissato). Allora, riprendendo il
nostro codice: mov ah,02 muove il numero 02 in un registro del processore
chiamato “AH”; mov dl,65 muove 65 nel registro “DL”, e così via.
“Int” serve a richiamare una procedura (interrupt), ovvero un pezzo di
codice che sta da qualche altra parte, nella memoria del computer. Nel nostro
programmino, noi richiamiamo una procedura contrassegnata dal numero 21h (la “h”
sta ad indicare un numero in base 16; spesso, lavorando con l’assembly, dovremo
usare numeri esadecimali, quindi è meglio abituarsi ad usare la calcolatrice di
Windows, che ha la conversione da decimale ad esadecimale). Allora, quando il
processore trova la nostra istruzione “int 21h”, salta alla porzione di
codice voluta; poi, quando ha finito l’esecuzione della procedura chiamata,
ritorna al nostro programmino, pronto per eseguire l’istruzione
successiva.
Beh, ora sappiamo cosa fanno queste due istruzioni…il punto,
ora, è capire come metterle insieme per fare qualcosa di semplice, come ad
esempio scrivere una lettera “A” sullo schermo. Il ruolo maggiore è svolto dalla
procedura che chiamiamo con l’interrupt 21h. Allora, già che ci siamo, andiamo a
vedere cosa dice la lista di Ralph Brown sull’int 21h…uhm, c’è scritto “INT 21 –
DOS 1+ - FUNCTION CALLS”, e c’è una lista di funzioni, ognuna contrassegnata da
un numero. Allora, questo vuol dire che, attraverso l’istruzione “int 21h”, noi
possiamo chiamare delle funzioni Dos (un po’ come accade in Windows, quando
chiamiamo una API). Dobbiamo semplicemente specificare la funzione che
desideriamo, tra le tante che l’interrupt 21h ci mette a disposizione: dobbiamo
muovere nel registro “AH” il numero corrispondente alla funzione voluta. E’ per
questo, infatti, che nel nostro codice abbiamo inserito l’istruzione mov
ah,02 : in questo modo, abbiamo scelto la funzione 02h dell’interrupt 21h.
Vediamo cosa dice la solita lista a proposito di questa funzione:
INT 21 02-- - DOS 1+ - WRITE CHARACTER TO STANDARD OUTPUT
Category: D - DOS kernel
Inp.:
AH = 02h
DL = character to write
Return: AL = last character output (despite the official docs which state
nothing is returned) (at least DOS 2.1-5.0)
Notes: ^C/^Break are checked, and INT 23 executed if pressed
standard output is always the screen under DOS 1.x, but may be
redirected under DOS 2+
the last character output will be the character in DL unless DL=09h
on entry, in which case AL=20h as tabs are expanded to blanks
if standard output is redirected to a file, no error checks (write-
protected, full media, etc.) are performed
SeeAlso: AH=06h,AH=09h
INT 21
La lista di Ralph Brown è veramente utile, ci fornisce tante informazioni…
per esempio, ci dice come facciamo a specificare il carattere da scrivere sullo
schermo: basta muovere nel registro “DL” il valore ASCII corrispondente al
carattere. Se vogliamo visualizzare una “A”, il cui codice ASCII è 65, dovremo
scrivere l’istruzione mov dl,65.
A questo punto, dovrebbe essere
abbastanza intuitivo il significato delle istruzioni
mov ah,4ch
mov al,00h
int 21h
Anche qui, come prima, chiamiamo l’interrupt 21h; questa volta, però,
specifichiamo la funzione 4ch. Vediamo cosa ci dice Mr. Brown su questa
funzione:
INT 21 4C-- - DOS 2+ - "EXIT" - TERMINATE WITH RETURN CODE
Category: D - DOS kernel
Inp.:
AH = 4Ch
AL = return code
Return: never returns
Notes: unless the process is its own parent (see #0691 at AH=26h, offset 16h
in PSP), all open files are closed and all memory belonging to the
process is freed
all network file locks should be removed before calling this function
SeeAlso: AH=00h,AH=26h,AH=4Bh,AH=4Dh,INT 15/AH=12h/BH=02h,INT 20,INT 22
SeeAlso: INT 60/DI=0601h
Come abbiamo visto prima, la funzione 4ch termina un programma,
restituendo il controllo del processore al sistema operativo. Nel registro “AL”
dobbiamo specificare il codice di ritorno; se non ci sono stati errori, questo
codice corrisponde ad uno zero: allora muoviamo zero in “AL”, attraverso un “mov
AL,00h”.
Beh, questa prima lezione termina qui; vi suggerisco di
guardarvi un po’ la interrupt list di Ralph Brown, e soprattutto le funzioni
dell’interrupt 21h. Mmh, potreste anche provare a scrivere un programmino che
legga un carattere da tastiera e lo visualizzi sullo schermo! Cercate la
funzione dell’int 21h per leggere il carattere da tastiera, e il gioco è fatto.
Spero di essere stato chiaro; lo so che non abbiamo visto molto, in
questa prima puntata, ma gli esami incombono…e bisogna studiaaaare! La prossima
volta vedremo tutti i registri del processore, e, magari, l’organizzazione della
memoria del PC.