Architettura di Intel 80x86

Architettura di Von Neumann

Questo modello di base di un computer come unità di elaborazione che riceve input, comunica con una memoria e produce output è noto come architettura von Nuemann dal nome del primo scienziato informatico John von Neumann. In questa architettura, il processore stesso è costituito da più parti specializzate:

  • L’ unità logica aritmetica (ALU) - l’unità di elaborazione centrale in grado di eseguire operazioni matematiche e logiche.

  • L’unità di controllo che dirige il movimento delle istruzioni in entrata e in uscita dal processore e invia segnali di controllo all’ALU affinché esegua il corretto funzionamento in un dato momento.

  • I registri del processore : piccole aree di archiviazione per scopi speciali utilizzate per archiviare le informazioni con cui sta lavorando l’ALU.

  • L’unità di memoria, non parte del processore, contiene sia i dati che le istruzioni (programma). Per essere utilizzate, queste informazioni devono essere trasferite ai registri.

Arithmetic Logic Unit

L’acronimo ALU in italiano significa Unità Aritmetico-logica (Arithmetic logic unit) ed è ciò che permette ai computer di eseguire la valutazione degli operandi e le operazioni matematiche. Si trova all’interno della CPU insieme all’unità di controllo (che legge le istruzioni in linguaggio macchina, le fa eseguire e memorizza i risultati) e dei registri di cui parleremo in seguito.

Esistono infinite possibilità di creazione di ALU in grado di eseguire operazioni diverse. L’intera ALU viene scomposta in unità più piccole, ognuna in grado di elaborare un solo bit per una determinata operazione, le quali in cascata daranno il risultato finale. È normale che ci siano piccole differenze tra le singole ALU a più bit per poter gestire in modo ottimale le operazioni matematiche che non generano un risultato intero nei bit a disposizione e quindi essere al corrente in caso di Overflow del risultato. Al giorno d’oggi, quasi tutti i processori hanno più ALU che funzionano in parallelo e sono spesso specializzati per lavori specifici.

I registri

I processori della famiglia intel x86 possiedono almeno i seguenti registri: AX, BX, CX, DX, CS, DS, ES, SS, SP, BP, SI, DI, IP, FLAGS. Originariamente, fino alla nascita del processore 80386, i registri AX, BX, CX, DX, SP, BP, SI, DI, FLAGS ed IP avevano una dimensione pari a 16 bit. A partire dal 80386, la loro dimensione è stata portata a 32 bit e al loro nome è stata aggiunta la lettera E (per indicare extended) in prima posizione. Ad esempio, il registro AX è diventato EAX.

EAX, EBX, ECX, ed EDX sono registri generici (general purpose registers), pertanto è possibile assegnargli qualunque valore. Tuttavia, durante l’esecuzione di alcune istruzioni i registri generici vengono utilizzati per memorizzare valori ben determinati:

  • EAX (accumulator register) è usato come accumulatore per operazioni aritmetiche e contiene il risultato dell’operazione.
  • EBX (base register) è usato per operazioni di indirizzamento della memoria.
  • ECX (counter register) è usato per “contare”, ad esempio nelle operazioni di loop.
  • EDX (data register) è usato nelle operazioni di input/output, nelle divisioni e nelle moltiplicazioni.

CS, DS, ES e SS sono i registri di segmento (segment registers) e devono essere utilizzati con cautela:

  • CS (code segment) punta alla zona di memoria che contiene il codice. Durante l’esecuzione del programma. Usato assieme a IP (Instruction Pointer) serve per accedere alla prossima istruzione da eseguire (attenzione: non può essere modificato).
  • DS (data segment) punta alla zona di memoria che contiene i dati.
  • ES (extra segment) può essere usato come registro di segmento ausiliario.
  • SS (stuck segment) punta alla zona di memoria in cui risiede lo stack.

ESP, EBP, EIP sono i registri puntatore (pointer registers):

  • ESP (stack pointer) punta alla cima dello stack. Viene modificato dalle operazioni di PUSH (inserimento di un dato nello stack) e POP (estrazioni di un dato dallo stack). Si ricordi che lo stack è una struttura di tipo LIFO (Last In First Out – l’ultimo che entra è il primo che esce). E’ possibile modificarlo anche manualmente a proprio rischio e pericolo!
  • EBP (base pointer) punta alla base dello stack.
  • EIP (instruction pointer) punta alla prossima istruzione da eseguire. Non può essere modificato.

ESI e EDI sono i registri indice (index registers) e vengono utilizzati per operazioni con stringhe e vettori:

  • ESI (source index) punta alla stringa/vettore sorgente.
  • EDI (destination index) punta alla stringa/vettore destinazione.
  • EFLAGS è utilizzato per memorizzare lo stato corrente del processore. Ciascuna flag (bit) del registro fornisce una particolare informazione. Ad esempio, la flag in posizione 0 (carry flag) viene posta a 1 quando c’è stato un riporto o un prestito durante un operazione aritmetica; la flag in posizione 1 (parity flag) viene usata come bit di parità e viene posta a 1 quando il risultato dell’ultima operazione ha un numero pari di 1;

Composizione del registro EFLAGS

  • CF (carry flag): impostato a 1 se un’operazione aritmetica chiede un prestito dalla cifra più significativa o esegue un riporto oltre la cifra più significativa;

  • PF (parità flag): impostato a 1 se il numero di 1 presenti nel risultato di un’operazione è dispari, a 0 se è pari.

  • AF (auxiliary flag): utilizzato nell’aritmetica BCD (Binary Coded Decimal) per verificare se si è verificato un riporto o un prestito;

  • ZF (zero flag): impostato a 1 se il risultato dell’operazione è 0.

  • SF (sign flag): impostato a 1 se il risultato dell’operazione è un numero negativo, a 0 se è positivo (rappresentazione in complemento a 2).

  • OF (overflow flag): impostato a 1 nel caso di overflow di un’operazione.

Modalità di indirizzamento

Il termine modalità di indirizzamento si riferisce al modo in cui l’operando di un istruzione viene specificato. Esistono 7 modalità di indirizzamento principali:

  • Indirizzamento a registro: l’operando è contenuto in un registro. Il nome del registro è specificato nell’istruzione.
  • Indirizzamento assoluto: l’operando è contenuto in una locazione di memoria. L’indirizzo della locazione viene specificato nell’istruzione.
  • Indirizzamento immediato: l’operando è un valore costante ed è definito esplicitamente nella istruzione.
  • Indirizzamento indiretto: l’indirizzo di un operando è contenuto in un registro o in una locazione di memoria. L’indirizzo della locazione o il registro viene specificato nell’istruzione.
  • Indirizzamento indicizzato: l’indirizzo effettivo dell’operando è calcolato sommando un valore costante al contenuto di un registro.
  • Indirizzamento con autoincremento: l’indirizzo effettivo dell’operando è il contenuto di un registro specificato nell’istruzione. Dopo l’accesso all’operando, il contenuto del registro viene incrementato per puntare all’elemento successivo.
  • Indirizzamento con autodecremento: il contenuto di un registro specificato nell’istruzione viene decrementato. Il nuovo contenuto viene usato come indirizzo effettivo dell’operando.