IA-32

Con IA-32 (Intel Architecture 32 bit), a volte i386, si definisce l'architettura o l'instruction set dei microprocessori prodotti da Intel, AMD e altre compagnie minori per il mercato desktop a partire dal 1985, e che è presente nella grandissima maggioranza dei personal computer esistenti al mondo. Spesso viene definita un'architettura CISC, ma queste distinzioni stanno sempre più perdendo significato con l'avanzare della tecnologia.

Storia 
Il termine fu coniato per distinguere il set di istruzioni per le CPU compatibili con il processore Intel 80386 da quelli per serie incompatibili come Itanium. Il set IA-32 viene implementato in tutte le CPU della grande famiglia x86 successive all'80386, ovvero quelle a 32 bit. I programmi che sono utilizzati con uno di questi processori possono girare in modalità protetta, usare memoria maggiore di 640K, disporre di memoria virtuale e ambiente multitasking. Inoltre essi possono accedere ad uno spazio di memoria lineare di circa 4 GB.

Modalità di operazione dei processori IA-32 
L'IA-32 supporta tre modalità di funzionamento: la modalità reale, la modalità protetta e la modalità 8086 virtuale. In modalità protetta i programmi possono sfruttare appieno il processore e tutta la memoria disponibile sulla macchina, mentre in modalità reale e in modalità 8086 virtuale il software ha a disposizione un solo megabyte di RAM e il processore si comporta come un semplice 8086.

Registri 
La CPU 80386 (e tutti i suoi successori) ha 4 registri ad uso generico a 32 bit e 6 registri di segmento, più il registro dei flag, due registri indice e due registri per la gestione dello stack. A questi registri di uso comune si aggiungono alcuni destinati a compiti particolari: ci sono 4 Control Register, 6 Debug Register e 4 Test Register, oltre naturalmente ai registri descrittori di segmento necessari per l'implementazione dei meccanismi di memoria virtuale. Il coprocessore matematico 80387 aggiungeva al sistema altri 8 registri in virgola mobile. I processori seguenti hanno incorporato il coprocessore matematico e introdotto altri registri per le istruzioni SIMD, come l'MMX, il 3DNow! e l'SSE, ma senza abbandonare mai il gruppo di registri originario del 386.

Registri ad uso generico 
I registri ad uso generico x86 non sono realmente destinati all'uso generico come indicherebbe la definizione, a causa di alcuni processi specifici che possono spesso essere eseguiti impiegando solo uno o due di questi registri. In altre architetture i registri ad uso generico sono impiegabili in modo assolutamente indistinto, mentre i registri x86 sono suddivisi tra specifici per i dati e specifici per gli indirizzi. 

Inoltre molte operazioni possono essere svolte o in un registro o direttamente nella RAM, senza necessità di caricare i dati in un registro. Questo comportamento dimostra i trent'anni di età di quest'architettura.

Nota: con l'arrivo dell'estensione AMD64 all'architettura x86 questa caratteristica è stata eliminata, almeno in modalità a 64 bit: ora i registri ad uso generico sono realmente ad uso generico, senza distinzioni. Questo non influenza comunque l'architettura IA-32.

Registri a 8 e 16 bit 
È inoltre possibile l'accesso ad ulteriori set di registri a 8 e 16 bit. Per esempio, si può accedere ai 16 bit inferiori del registro a 32 bit EAX chiamandoli AX. Alcuni registri a 16 bit possono essere divisi ulteriormente in registri a 8 bit: la metà superiore del registro a 16 bit AX visto sopra è chiamata AH e l'inferiore AL. Allo stesso modo, il registro a 32 bit EBX si divide in BX (16 bit), ulteriormente diviso in BH (8 bit) e BL (8 bit).

Registri generici dei dati 
Tutti i seguenti registri possono essere impiegati per uso generico, ma anche per processi specializzati; ognuno di essi può essere suddiviso in registri a 16 o 8 bit.

 EAX - accumulatore (specializzato per le istruzioni aritmetiche)
 EBX - base register (usato per indirizzare il dato nel segmento di memoria)
 ECX - contatore (specializzato per i cicli)
 EDX - data register

Registri degli indirizzi 
Usati solo per l'indirizzamento. Possono essere divisi in registri a 16 bit ma non a 8 bit.

 EBP - base pointer (contiene l'indirizzo dello stack frame attualmente impiegato)
 ESI - source index (usato per le stringhe)
 EDI - destination index (usato per le stringhe)
 ESP - stack pointer (contiene il primo indirizzo di uno stack)
 EIP - instruction pointer (contiene l'indirizzo dell'istruzione successiva)

Registri stack per la virgola mobile 
Fin dall'introduzione dell'80486 sono presenti 8 registri x87 in virgola mobile, numerati da ST(0) a ST(7). Ogni registro contiene 80 bit e immagazzina numeri nel formato "precisione doppia estesa" dello standard IEEE 754. A questi registri non si può accedere direttamente, ma come uno stack LIFO. Il numero del registro non è fisso, ma si riferisce alla cima dello stack: ST(0) è il registro in cima allo stack, ST(1) è quello inferiore, ST(2) è ancora inferiore e così via. Questo significa che un dato è sempre spinto verso il basso, e che le operazioni vengono sempre effettuate con l'operando contenuto in cima allo stack: non è possibile accedere ad un dato registro in modo casuale, ma solo in ordine.

Registri di segmento 
I registri di segmento vengono utilizzati dall'80386 per generare un indirizzo lineare da un indirizzo logico. L'indirizzo logico è dato dalla coppia registro di segmento:offset (l'offset può essere una costante, un registro di base, di indice o la combinazione dei tre, con alcune regole/eccezioni). L'indirizzo lineare viene quindi trasformato in indirizzo fisico dal meccanismo di paging del processore. I registri di segmento sono 6:

 CS - code segment (viene implicitamente utilizzato dal processore, in coppia con il registro EIP, per prelevare la prossima istruzione)
 DS - data segment (viene utilizzato, implicitamente, nell'accesso alla memoria da parte di un'istruzione)
 SS - stack segment (utilizzato in coppia con ESP per gestire lo stack)
 ES - extra segment (utilizzato come ulteriore registro per dati, simile al data segment)
 FS - extra segment (segmento extra per i dati, ad uso generico)
 GS - extra segment (segmento extra per i dati, ad uso generico)

Nota: I registri FS e GS furono aggiunti nell'80386 (nei processori precedenti non erano presenti) e il loro nome è una semplice continuazione dell'alfabeto dalla E di ES.

Nota: Quando si vuole far riferimento ad un indirizzo di memoria nell'architettura IA-32, viene utilizzata la forma <SEGMENTO>:<OFFSET>. Il segmento è espresso mediante uno dei 6 registri di segmento (anche se in alcuni casi è possibile esprimerlo con un valore costante) mentre l'offset indica lo scostamento all'interno del segmento. Le istruzioni, ad esempio, vengono sempre prelevate nella memoria all'indirizzo puntato dalla coppia CS:EIP.

Registro dei flag 
L'80386 dispone di un registro dei flags, chiamato EFLAG. Sebbene non sia direttamente accedibile mediante un nome (come EAX, ad esempio) è possibile in qualche modo leggerlo e scriverlo. Sono necessarie solo un paio di istruzioni:

  /* Lettura dello stato del registro dei flags */
  PUSHFD       ;Salva lo stato dei flags nello stack
  POP EAX      ;Estrae dallo stack e salva in EAX (o qualunque altro registro generale)

Per modificare, invece, lo stato dei flags sono necessarie le seguenti due istruzioni:

  /* Modifica dello stato dei flags */
  PUSH EAX     ;Salva il registro EAX sullo stack (o qualunque altro registro generale)
  POPFD        ;Estrae dallo stack e memorizza nel registro dei flags

Le istruzioni precedenti salvano e ripristinano lo stato di EFLAG (versione a 32-bit dei flags dell'80386). È possibile salvare/ripristinare solo i 16 bit meno significativi utilizzando PUSHF/POP AX e PUSH AX/POPF rispettivamente. La dimensione (16 o 32 bit) utilizzata dipende dalla dimensione dell'operando. Il prefisso di forzatura operando (op-code 0x66) permette di variare la dimensione all'interno del contesto corrente: se utilizzato in modo 16-bit farà trattare al microprocessore l'istruzione come a 32-bit e viceversa.

Il registro dei flags è un registro a 16 bit dove ad alcuni bit (o raggruppamento di essi) è assegnato un significato preciso ed indica lo stato del processore. Se il bit è posto ad 1 il flag è impostato (set), se posto a 0 si dice che è resettato (reset o clear).

I numeri indicano la posizione in bit le sigle indicano il nome simbolico del flag.

Significato dei flags:

 V8 - Virtual 86 mode (se impostato indica che si è in modalità Virtual-8086)
 RF - Resume Flag (se impostato abilita le eccezioni in modo debug)
 NT - Nested Task Flag (se impostato indica che il codice in esecuzione non deve essere interrotto dal multi-tasking in quanto routine di un servizio di interrupt)
 PL - Priviledged Level Flag (2 bits) (se impostato permette di eseguire istruzioni di I/O, in caso è resettato, l'esecuzione di istruzioni di I/O genera un'eccezione di protezione).
 OF - Overflow Flag (se impostato indica che l'ultima operazione aritmetica ha generato un overflow)
 DF - Direction Flag (indica alla cpu quale direzione utilizzare negli incrementi automatici delle istruzioni che operano su stringhe.
 IF - Interrupt Flag (se impostato indica alla cpu di rispondere agli interrupt. L'NMI-Non Maskable Interrupt non viene influenzato da questo flag)
 TF - Trap Flag (se impostato indica alla cpu di generare una INT 0 dopo ogni istruzione)
 SF - Sign Flag (se impostato indica che l'ultima istruzione aritmetica ha generato un numero negativo).
 ZF - Zero Flag (se impostato indica che l'ultima operazione logico/aritmetica ha generato uno 0)
 AF - Auxiliary Carry Flag (se impostato indica che l'ultima operazione aritmetica ha generato un riporto sui 4 bit inferiori di AL, usato nell'aritmetica BCD)
 PF - Parity Flag (se impostato indica che l'ultima operazione aritmetica ha generato un risultato formato da un numero dispari di bit posti ad 1)
 CF - Carry Flag (se impostato indica che l'ultima operazione aritmetica ha generato un riporto)

I restanti bit non sono utilizzati e vengono riservati ad uso futuro; il loro valore non dovrebbe essere modificato e, se letto, non dovrebbe essere preso in considerazione.

Registri SIMD 

Gli instruction set MMX, 3DNow!, e SSE possiedono propri registri, in aggiunta a quelli standard IA-32.

Registri MMX 
L'MMX possiede 8 registri, chiamati da MM0 a MM7 (da qui in poi MMn), che però sono fisicamente gli stessi registri x87 per il calcolo in virgola mobile della FPU, per cui è impossibile usare contemporaneamente le istruzioni MMX e quelle in virgola mobile: prima di usare il set di istruzioni MMX deve essere disabilitata la FPU, con una istruzione apposita. 

Ognuno dei registri MMn contiene un intero a 64 bit, ma una delle caratteristiche fondamentali di questo instruction set è il concetto di vettore, formato da più dati simili tra loro: potevano quindi essere immagazzinate due parole di 32 bit l'una, quattro di 16 o otto di 8.

Sempre perché i registri MMn sono in "coabitazione fisica" con i registri x87, che contengono 80 bit l'uno, nell'esecuzione delle MMX i primi 16 bit del registro vanno sprecati: vengono quindi tutti impostati a 1, in modo che i dati presenti vengano riconosciuti come "NaN" o come infiniti da un'applicazione in virgola mobile, e rendendo facile riconoscere se vengano usati dati in virgola mobile o MMX.

Registri 3DNow! 
Il 3DNow! fu progettato come un'estensione naturale delle istruzioni MMX per il calcolo in virgola mobile; usa quindi le stesse denominazioni dei registri MMn, ma invece di immagazzinarvi parole di 64 bit, vi introduce numeri in virgola mobile a precisione singola.

Il vantaggio di usare i registri x87 anche in questo caso è che essi sono già dedicati al calcolo in virgola mobile, e quindi le istruzioni x87 possono essere usate per compiere le operazioni analoghe di salvataggio dei registri anche nel codice 3DNow!: ne consegue che non sono richieste modifiche al sistema operativo per usare questa tecnologia.

Registri SSE 
Con l'SSE le istruzioni SIMD furono rese completamente indipendenti dai registri x87. Ma questo significò anche allontanarsi definitivamente dagli altri instruction set SIMD, come MMX; sforzo giustificato dalla possibilità di usare registri più grandi, liberi dai limiti della virgola mobile. Furono creati otto registri a 128 bit, chiamati da XMM0 a XMM7 (nota: nell'architettura AMD64 i registri sono stati aumentati a 16).

Lo svantaggio consiste nel dover inserire nel sistema operativo il nuovo set di istruzioni. Intel creò quindi una nuova versione della modalità protetta, chiamata "Enhanced mode", che permette l'utilizzo delle istruzioni SSE, disabilitate nella normale modalità protetta: un sistema operativo che include le istruzioni SSE accede alla nuova modalità, mentre uno più vecchio o che comunque non le includa tenterà l'accesso solo alla normale modalità protetta.

L'SSE è un instruction set che opera solo su dati in virgola mobile, come 3DNow!, ma a differenza di questo non usa i registri stack della FPU ma un proprio set di registri separato, in grado di contenere il doppio di numeri a precisione singola. Mentre il primo SSE era limitato ai numeri a precisione singola, con l'SSE2 fu possibile trattare anche numeri a precisione doppia. Per il 3DNow! questo non era possibile, dato che un unico numero in questa precisione occuperebbe l'intero registro a 64 bit, mentre i registri XMMn sono a 128 bit: l'SSE2 è quindi molto più adatto ad applicazioni scientifiche rispetto ai due predecessori.

Set di istruzioni aggiuntivi SIMD 
 Le estensioni MMX furono il primo grande aggiornamento: erano istruzioni SIMD adatte solo per il calcolo intero. Esse furono introdotte insieme da Intel e AMD nei propri Pentium MMX e K6 nel 1997. Condivideva i registri con la FPU x87, così il sistema operativo non doveva essere modificato per adoperare queste istruzioni se supportava il salvataggio dello stato x87.
 L'MMX fu aggiornato con le estensioni 3DNow!, che supportavano la virgola mobile, da parte di AMD nel 1999 col K6-2. Anche queste sfruttavano i registri x87. Intel non considerò mai questa tecnologia.
 Intel introdusse le istruzioni SSE, con supporto per dati in virgola mobile a precisione singola, col processore Pentium III nel 1999. A differenza del 3DNow!, non erano un'estensione delle MMX e non sfruttavano i registri della FPU x87, e richiedevano modifiche al sistema operativo per essere sfruttate, ma erano libere dalle limitazioni imposte dai registri x87. Queste istruzioni e le sue successive estensioni furono adottate anche da AMD a partire dagli Athlon XP, e questa non sviluppò ulteriormente il 3DNow!.
 L'SSE2 fu introdotto col Pentium 4 all'inizio del 2001; costituiva un ulteriore miglioramento delle SSE, con l'aggiunta del supporto per i numeri a precisione doppia.
 L'SSE3, introdotto col Pentium 4 Prescott nel 2004, forniva aggiunte secondarie alle SSE2.

Formato delle istruzioni IA-32 
La struttura di una generica istruzione IA-32 è variabile a seconda dello specifico opcode, e può essere preceduta da dei prefissi (fino a quattro) che ne modificano il comportamento: una descrizione generale è data nella tabella qui sotto. 

Il byte Mode R/M specifica ulteriormente l'operando dell'istruzione e può contenere un supplemento di opcode, mentre il byte SIB (Scale Index Base) specifica sempre un registro a 32 bit (EAX, EBX ecc.) ed è caratteristico dei processori IA-32.

Nella tabella seguente sono elencate le istruzioni IA-32, organizzate per ordine alfabetico in base al loro codice mnemonico assembly. Vengono riportati anche gli opcodes esadecimali e, in cicli di clock, i tempi di esecuzione per un 80386. Se al posto dell'opcode c'è un asterisco è perché l'istruzione ha molti opcode diversi a seconda delle varie forme; anche i tempi di esecuzione sono variabili a seconda dello stato in cui si trova il processore: in modo protetto molti accessi alla memoria "costano" cicli di clock in più, e un eventuale context switch può alzare di molto i tempi. I flag impostati a valori predefiniti sono contrassegnati con il valore 0 o 1 che assumono; se vengono modificati in accordo con il risultato dell'operazione sono contrassegnati con un asterisco; se vengono modificati, ma in modo non definito sono contrassegnati con un punto interrogativo.

Questo è il set completo di istruzioni del processore 80386. La nuova architettura Intel IA-64 non è direttamente compatibile con le istruzioni IA-32.

Voci correlate 

 x86 - Famiglia di processori Intel
 AMD64 - Architettura a 64 bit di AMD
 IA-64 - Architettura a 64 bit di Intel per processori Itanium
 EM64T - Architettura a 64 bit di Intel per processori x86

Architettura dei calcolatori
Intel