Assembly x86
# Assembly x86

Assembly x86 è una famiglia di linguaggi assembly retrocompatibili usata per produrre codice macchina per i processori con architettura x86. Come tutti i linguaggi assembly utilizza corte mnemoniche, ovvero abbreviazioni facili da ricordare (per esempio cmp sta per compare ovvero "confronta") che rappresentano le operazioni fondamentali che il processore può eseguire.

I processori Intel 8086 e 8088 sono stati i primi ad avere il set di istruzioni che viene comunemente chiamato x86. Questi processori a 16 bit ereditarono molte caratteristiche dai precedenti processori a 8 bit, ma vennero aggiornati ricevendo un numero molto maggiore di istruzioni e funzionalità. Assembly x86 permette di scrivere codice macchina per l'8086, per tutti i processori Intel seguenti e per i processori di altri produttori (come per esempio AMD) che utilizzano l'architettura x86.

## Registri

Complessivamente i registri utilizzati nell'assembly x86 sono 14. Quattro sono registri di uso generale, utilizzati per la memorizzazione temporanea:

* AX, registro accumulatore, è il registro usato per le istruzioni matematiche quali somme, sottrazioni, moltiplicazioni e divisioni.
* BX, registro base, è il registro che può specificare un indirizzo di memoria.
* CX, registro contatore, è il registro usato nelle istruzioni di conteggio dei cicli o di operazioni matematiche.
* DX, registro di I/O, è il registro che indirizza le porte di Input/Output; può essere usato anche in istruzioni matematiche come moltiplicazioni e divisioni.

Due sono registri indice, usati sia per la memorizzazione temporanea (solo a 16 bit) sia nelle istruzioni in cui si manipolano stringhe:

* SI, registro indice sorgente, è il registro in cui viene specificato l'indirizzo da cui leggere l'array.
* DI, registro indice destinazione, è il registro in cui viene specificato l'indirizzo in cui scrivere l'array.

Due registri vengono usati per la gestione dello stack e per l'indirizzamento in memoria:

* BP, registro base pointer, è il registro che contiene il primo indirizzo di memoria della pila di stack.
* SP, registro stack pointer, è il registro che contiene l'ultimo indirizzo di memoria della pila di stack.

Due registri vengono aggiornati dal processore e per questo non possono essere modificati dal programmatore:

* IP, registro instruction pointer, è il registro che contiene la parte meno significativa dell'istruzione successiva da eseguire.
* Flag, registro dei flag, è il registro dove ogni bit ha un significato diverso dopo l'esecuzione di un'istruzione; descrive lo stato del processore.

Gli ultimi quattro registri sono di segmento vengono usati per contenere i 16 bit più significativi di un qualsiasi indirizzo di memoria.

* CS, registro code segment, è il registro che contiene la parte più significativa del program counter ed è associato al registro IP.
* DS, registro data segment, è il registro che contiene la parte più significativa di una memoria dati ed è associato ai registri BX, SI e DI.
* ES, registro extra segment, è uguale al registro DS ma associato ad una seconda memoria dati.
* SS, registro stack segment, è il registro che contiene la parte più significativa della memoria in cui è assegnato lo stack ed è associato ai registri BP e SP

## Istruzioni

### MOV

L'istruzione mov copia il contenuto di a (che può essere un valore costante, un contenuto del registro o della memoria) in b.

### PUSH

L'istruzione push inserisce all'inizio dello stack a l'indirizzo inserito nel registro SP il quale a sua volta viene decrementato di due unità.

### POP

L'istruzione pop preleva un elemento dallo stack, dall'indirizzo inserito nel registro SP, e lo sposta in b. Il registro SP viene incrementato di due unità.

### NOP

L'istruzione nop non fa niente, ma viene usata per esempio se si vuole rallentare l'esecuzione del programma oppure se si vuole aumentare l'indirizzo del codice di una unità.

### CMP

L'istruzione cmp confronta i valori contenuti in a e b effettuando una sottrazione. Successivamente vengono impostati i flag in base al risultato dell'istruzione.

### JMP

L'istruzione jmp (salto incondizionato) trasferisce nell'indirizzo a il flusso del programma eseguito.

### LOOP

L'istruzione loop, quando viene eseguita, controlla il registro CX. Se è diverso da zero viene decrementato di una unità il suo valore, altrimenti il programma riprende normalmente l'esecuzione.

### Operazioni matematiche

L'istruzione add esegue la somma tra a e b; il risultato viene inserito in a.

L'istruzione sub esegue la sottrazione tra a e b; il risultato viene inserito in a.

L'istruzione mul esegue la moltiplicazione tra il valore del registro AX e a; il risultato viene inserito in AX.

L'istruzione div esegue la divisione tra il valore del registro AX e a; il risultato viene inserito in AX.

## Interruzioni

Nell'assembly x86 le interruzioni (o interrupt) vengono gestite attraverso delle istruzioni molto importanti se si vuole scrivere un programma, poiché servono per poter accedere allo schermo e alla tastiera.

### Gestione dell'output

Le istruzioni int 10 e int 21 sono le istruzioni necessarie per stampare sullo schermo un carattere; quest'ultimo dovrà essere sempre indicato in codifica ASCII anche se è formato da una cifra decimale.

Nell'esempio sotto viene mostrato come si stampa il carattere "A".

### Gestione dell'input

Le istruzioni int 16 e int 21 sono le istruzioni necessarie per inserire un carattere da tastiera. Quando viene invocata l'interruzione, l'esecuzione del programma viene bloccata in attesa che l'utente digiti un carattere da tastiera. Alla fine dell'esecuzione viene visualizzato in ASCII il carattere premuto dall'utente.

### Chiusura di un programma

L'istruzione int 20 chiude un programma COM; il DOS non viene informato sullo stato della chiusura. L'istruzione int 21 chiude un programma EXE; il DOS viene informato sullo stato della chiusura.

### Ora corrente

L'istruzione int 21h restituisce l'ora corrente, inclusi i minuti, i secondi e i centesimi di secondo.

## Debug

Per scrivere e compilare programmi in assembly x86 viene utilizzato il programma debug.exe (eseguibile tramite il comando debug nel prompt di Windows e di MS-DOS), presente in MS-DOS e nelle versioni a 16 bit e 32 bit di Windows. Nelle versioni a 64 bit il programma non è presente, tuttavia per questi sistemi è possibile utilizzare emulatori gratuiti scaricabili in rete come DOSBox. La notazione utilizzata è quella esadecimale. Nel debug.exe i comandi sono molto comprensibili dall'utente, e sono anche case sensitive. Sotto vengono riassunti i comandi principali:

| Comando | Che cosa fa |
| - | - |
| A | Inizia la scrittura del programma. |
| D | Permette di visualizzare la memoria. |
| L | Carica il programma. |
| N | Rinomina il programma. |
| Q | Esce da debug.exe. |
| R | Permette di visualizzare e/o impostare i registri. |
| U | Permette di modificare il programma. |
| W | Salva il programma. |
