3.1 Nozioni base del Linguaggio Assembly

      

Spesso i virus sono scritti in un linguaggio molto vicino a quello "naturale" del computer, l'Assembly appunto. I listati scritti in questo linguaggio sono caratterizzati dall'estensione ASM (a volte A86). Il programmatore Assembly deve conoscere necessariamente l'aritmetica binaria e quella esadecimale. Se il nostro sistema di numerazione decimale prevede l'uso di dieci simboli, quello binario ne prevede due e quello esadecimale (abbreviato con "hex") ne usa 16 (0-1-2-3-4-5-6-7-8-9-A-B-C-D-E-F). Il fattore di conversione è un puro calcolo matematico. Ovviamente il sistema esadecimale offre il vantaggio di occupare meno spazio. In Assembly è possibile gestire tutti e tre i sistemi di numerazione. Quello di 'default' è il sistema decimale, ma è possibile scrivere numeri negli altri formati aggiungendo "B" oppure "H" alla fine del numero.

Esempio: 10011010010B       4D2H

E' bene precisare che i numeri esadecimali non possono iniziare con una lettera, cioè A55H non è ammesso, 0A55H si.


3.2 I Registri

Gli elementi chiave dell'Assembly sono i registri, cioè le celle di memoria che possono memorizzare determinati valori. La dimensione dei registri dipende dal processore e dalla compilazione usata. Iniziamo con i registri a 16 bit (2 byte equivalgono a 1 word).        

Registri a 16 bit                                                            

AX

BX

CX DX
SI DI    
CS DS ES SS
BP SP IP  

I primi 4 registri sono ulteriormente suddivisi in registri a 8 bit, che indicano rispettivamente la parte alta e la parte bassa del registro. Vediamo come i registri sono classificati:

Ci sono poi i registri di segmento, che indicano delle porzioni di memoria RAM di 64K:

I registri che possono indirizzare la memoria, cioè riferirsi a dei dati contenuti in un certo punto di questa, sono solo BX, SI e DI. Nei processori 386 e superiori esistono i registri a 32 bit che richiedono debugger particolari per il loro controllo.

Registri a 32 bit

EAX EBX ECX EDX    
ESI EDI        
CS DS ES SS FS GS
EBP ESP EIP      

Per visualizzare il contenuto dei registri sotto MS-DOS si può usare il comando "DEBUG" che restituisce inoltre l'istruzione da eseguire, con il relativo codice esadecimale.

Esistono poi alcuni "tester" chiamati Flag. Essi sono degli switch che possono valere 0 o 1 e scattano in particolari condizioni:


3.3 Istruzioni di base                                    

                                            

Segue ora una descrizione delle più comuni e usate istruzioni del linguaggio.

ADD

Addizione tra due registri, tra un numero e un registro, tra un'area di memoria e un registro, tra un'area di memoria e un numero. Esempi:

E' possibile operare solo con registri della stessa dimensione o con registri e valori dello stesso formato. Ad esempio un'addizione del numero 1234 (16 bit) al registro AL (8 bit) risulta errata. Inoltre in caso di ambiguità bisogna specificare se il dato da manipolare è di tipo WORD (16 bit) o di tipo BYTE (8 bit), usando l'istruzione "PTR":

Se il risultato eccede per il registro, il flag di riporto verrà settato su ON.

SUB

Funzione inversa di ADD, effettua la sottrazione tra numeri, registri o valori. Stesso funzionamento di ADD.

INC / DEC

Nel caso di addizione o sottrazione di 1 (incremento e decremento), si possono usare queste due istruzioni, molto più veloci e ridotte in termini di spazio:

Non si possono usare direttamente sui registri di segmento.

MOV

Muove un valore dentro a un registro, o un registro dentro un altro registro, un valore dentro un'area di memoria o un registro dentro un'area di memoria.

Usando questa istruzione è possibile accedere ai registri di segmento e modificarli:

Non sono ammesse manipolazioni sui registri CS e IP.

PUSH / POP

Permettono di salvare un registro o il valore puntato da un registro nello stack per poi ripristinarlo:

E' anche possibile manipolare i registri di segmento, come abbiamo visto prima con l'istruzione "MOV":

NOP

E' un'istruzione progettata per non eseguire nessuna operazione. E' usata per le ottimizzazioni di codice, cioè per sincronizzare le esecuzioni e i trasferimenti dei dati. Il suo codice esadecimale è 90H.

CMP

Istruzione di confronto, serve per confrontare tra di loro due registri, delle posizioni di memoria:

Non si possono confrontare tra di loro due valori diretti o due valori puntati contemporaneamente. Occorre caricare uno di essi prima in un registro e poi eseguire il confronto su quel registro.

JMP

Salta a un indirizzo. Si può usare in diversi formati:

JNZ / JZ

Salti condizionati. Eseguono il salto se una data condizione è vera. In questo caso la condizione è data dallo zero flag; esistono però altri tipi di salti:

Di solito i salti condizionati seguono un'istruzione "CMP" o una "OR". I salti condizionati hanno un limite (range) per cui non si possono fare salti dall'indirizzo corrente ad uno che superi i 181H (385D) byte.