IA-32
# 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:

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

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.

| 31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 09 | 08 | 07 | 06 | 05 | 04 | 03 | 02 | 01 | 00 |
| - | - | - | - | - | - | - | - | - | - | - | - | - | - | - | - | - | - | - | - | - | - | - | - | - | - | - | - | - | - | - | - |
| | | | | | | | | | | | | | | V8 | RF | | NT | PL | PL | OF | DF | IF | TF | SF | ZF | | AF | | PF | | CF |

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.

| Prefissi | Prefissi | Prefissi | Prefissi | Istruzione | Istruzione | Istruzione | Istruzione | Istruzione |
| - | - | - | - | - | - | - | - | - |
| Istruzione | Dimensione operando | Dimensione indirizzo | sostituzione segmento | Opcode | Mode R/M | SIB | Spostamento | Immediato |
| 1 byte | 1 byte | 1 byte | 1 byte | 1 o 2 byte | 1 byte | 1 byte | 1, 2 o 4 byte | 1, 2 o 4 byte |
| Opz. | Opz. | Opz. | Opz. | OBBLIGATORIO | Opz. | Opz. | Opz. | Opz. |

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.

Byte Mode R/M :

| Mode | Reg/Opcode | R/M |
| - | - | - |
| 2 bit | 3 bit | 3 bit |

Byte SIB :

| Scale | Index | Base |
| - | - | - |
| 2 bit | 3 bit | 3 bit |

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.

| Assembly | Opcode (esadecimale) | Cicli di clock | Flag modificati | Descrizione |
| - | - | - | - | - |
| AAA | 37 | 4 | oditszapc ? ??*?* | Regolazione ASCII dopo l'addizione (per aritmetica BCD) |
| AAD | D5 0A | 19 | oditszapc ? ??*?* | Regolazione ASCII prima della divisione (per aritmetica BCD) |
| AAM | D4 0A | 17 | oditszapc ? ??*?* | Regolazione ASCII dopo la moltiplicazione (per aritmetica BCD) |
| AAS | 3F | 4 | oditszapc ? ??*?* | Regolazione ASCII dopo la sottrazione (per aritmetica BCD) |
| ADC | * | 2-7 | oditszapc * ***** | Somma con carry. |
| ADD | * | 2-7 | oditszapc * ***** | Somma. |
| AND | * | 2-7 | oditszapc 0 **?*0 | Esegue l'AND logico bit a bit fra i due operandi, di cui uno può essere implicitamente il registro AL/AX/EAX. |
| ARPL | 63 | 21 | oditszapc * | Regolazione del campo RPL del selettore di segmento. Si usa nei sistemi operativi, per assicurarsi che un programma non chiami una subroutine che abbia un privilegio superiore a quello del programma stesso. |
| BOUND | 62 | 10 | oditszapc | Controlla che l'operando sia entro determinati limiti. Serve ad evitare di indirizzare per errore zone al di fuori di un array: di solito, per motivi di efficienza, si usa soltanto nelle versioni di debug di un programma. |
| BSF | 0F BC | * | oditszapc * | Scansione in avanti dei bit dell'operando. |
| BSR | 0F BD | * | oditszapc * | Scansione all'indietro dei bit dell'operando. |
| BT | * | 3-12 | oditszapc * | Test del bit specificato dell'operando |
| BTC | * | 6-13 | oditszapc * | Test del bit specificato dell'operando e sua negazione |
| BTR | * | 6-13 | oditszapc * | Test del bit specificato dell'operando e sua impostazione a 0 |
| BTS | * | 6-13 | oditszapc * | Test del bit specificato dell'operando e sua impostazione a 1 |
| CALL | * | 7-98+ | oditszapc tutti | Chiamata di procedura o subroutine |
| CBW | 98 | 3 | oditszapc | Conversione da byte a word |
| CDQ | 99 | 2 | oditszapc | Conversione da doubleword a quadword |
| CLC | F8 | 2 | oditszapc 0 | Azzeramento del flag di Carry |
| CLD | FC | 2 | oditszapc 0 | Azzeramento del flag di Direzione |
| CLI | FA | 3 | oditszapc 0 | Azzeramento del flag di Interrupt |
| CLTS | 0F 06 | 5 | oditszapc (nota 1) | Azzeramento del flag di cambio task (TS) nel registro speciale CR0 |
| CMC | F5 | 2 | oditszapc * | Negazione del flag di Carry |
| CMP | * | 2-6 | oditszapc * ***** | Confronto fra due operandi |
| CMPS* | * | 10 | oditszapc * ***** | Confronto fra due stringhe di memoria i cui indirizzi relativi sono memorizzati nei registri indice SI (o ESI) e DI (o EDI): entrambi i registri vengono decrementati di uno. A seconda se si devono considerare byte, word o doubleword sono disponibili le varianti CMPS, CMPSB, CMPSW e CMPSD. Molto spesso questa istruzione viene usata con prefissi REP* in modo da confrontare automaticamente intere zone di memoria. |
| CWD | 99 | 2 | oditszapc | Conversione da word a doubleword |
| CWDE | 98 | 2 | oditszapc | Conversione da word a doubleword |
| DAA | 27 | 4 | oditszapc ? ***** | Regolazione decimale dopo l'addizione (per aritmetica BCD) |
| DAS | 2F | 4 | oditszapc ? ***** | Regolazione decimale dopo la sottrazione (per aritmetica BCD) |
| DEC | * | 2-6 | oditszapc * **** | Decrementa di uno l'operando specificato |
| DIV | * | 38-41 | oditszapc ? ????? | Divisione senza segno. |
| ENTER | * | 10- | oditszapc | Creazione dello stack frame necessario per le chiamate di procedura dei linguaggi ad alto livello. |
| HLT | F4 | 5 | oditszapc | Ferma il processore. Dopo un HLT non vengono eseguite nuove istruzioni finché non si verifica un interrupt o un reset: in caso di interrupt, dopo la routine di servizio il processore riprende l'esecuzione dall'istruzione successiva alla HLT. Di solito si usa questa istruzione a fini di sincronizzazione o di risparmio energetico. |
| IDIV | * | 19-43 | oditszapc ? ????? | Divisione con segno. |
| IMUL | * | 9-41 | oditszapc * ????* | Moltiplicazione con segno |
| IN | * | 12+ | oditszapc | Lettura di un byte o di una word dalla porta di I/O specificata nell'operando. |
| INC | * | 2-6 | oditszapc * **** | Incrementa l'operando di uno. |
| INS* | * | 15-29 | oditszapc | Lettura di un byte o di una word dalla porta di I/O specificata nella stringa specificata dal registro indice DI (o EDI). Si usa spesso con prefissi REP* per leggere automaticamente interi vettori di dati. |
| INT | * | 33-119 | oditszapc 00 | Interrompe l'esecuzione corrente ed esegue la subroutine di interrupt specificata dall'operando. |
| INTO | CE | 59-119 | oditszapc | Interrompe l'esecuzione corrente ed esegue la subroutine di interrupt dedicata agli overflow. È sinonimo di INT 4. |
| IRET/IRETD | CF | 22-82 | oditszapc TUTTI | Ritorno da una subroutine di interrupt. |
| Jcc | * | 7+ | oditszapc | Salto condizionato. Il salto all'indirizzo specificato viene eseguito solo se determinati flag hanno un determinato valore: altrimenti l'esecuzione continua normalmente con l'istruzione successiva. Esistono numerosi tipi di salti condizionati. |
| JMP | * | 7-49+ | oditszapc | Salto ad altra locazione. L'esecuzione del programma continua a partire dalla locazione indicata dall'argomento del salto: se l'argomento non dovesse puntare ad una istruzione valida, viene generata una eccezione e il programma si ferma. |
| LAHF | 9F | 2 | oditszapc | Copia il registro dei flag nel registro AH |
| LAR | 0F 02 | 16 | oditszapc * | Carica il byte dei diritti di accesso nel descrittore di segmento. Questa istruzione serve ad impostare i privilegi di un determinato segmento: è una istruzione privilegiata e viene usata solo dal sistema operativo. |
| LEA | 8D | 2 | oditszapc | Caricamento dell'offset dell'indirizzo effettivo. |
| LEAVE | C9 | 4 | oditszapc | Uscita da una procedura di un linguaggio ad alto livello: è l'istruzione simmetrica di ENTER e provvede a distruggere lo stack frame della procedura terminata. |
| LGDT | 0F 01 /2 | 11 | oditszapc | Caricamento del registro della tabella dei descrittori globali dei segmenti: questa istruzione è usata soltanto dai sistemi operativi, un programma utente non ha nessun motivo di usarla. |
| LIDT | 0F 01 /3 | 11 | oditszapc | Caricamento del registro della tabella degli interrupt. Questa operazione viene fatta una volta per tutte all'avvio dal sistema operativo. |
| L*S | * | 7-25 | oditszapc | Caricamento di un puntatore completo segmento: offset. Le varie forme dell'istruzione (LGS, LFS, LDS, LES, LSS) specificano quale registro di segmento conterrà la parte segmento del puntatore. |
| LLDT | 0F 00 /2 | 20 | oditszapc | Caricamento del registro della tabella del descrittore locale. Come tutte le istruzioni sui descrittori di segmento, anche questa è usata solo dai sistemi operativi. |
| LMSW | 0F 01 /6 | 10-13 | oditszapc | Caricamento della parola di stato della macchina (Machine Status Word) |
| LODS* | * | 5 | oditszapc | Caricamento di un operando stringa. L'operando puntato dal registro SI (o ESI) viene caricato in AL/AX/EAX, a seconda di quale versione dell'istruzione viene usata (LODS, LODSB, LODSW, LODSD) |
| LOOP* | * | 11+ | oditszapc | Salto condizionato in base al valore del registro CX/ECX. Dopo il salto, CX/ECX viene decrementato di uno: quando il registro è zero, il salto non viene più eseguito. |
| LSL | 0F 03 | 20-26 | oditszapc * | Carica il limite del segmento nel relativo descrittore, specificato nell'operando. È di esclusivo uso del sistema operativo. |
| LTR | 0F 00 /3 | | oditszapc | Carica il registro del task con il registro o locazione di memoria specificata dall'operando. Anche questa istruzione è privilegiata e usata soltanto dai sistemi operativi. |
| MOV | * | 2-4 | oditszapc | Copia il secondo operando nel primo. |
| MOVS* | * | 7 | oditszapc | Copia il valore corrente in una certa posizione di una stringa nella corrispondente posizione della seconda. Si usa spesso con prefissi REP*. |
| MOVSX | 0F BE | 3-6 | oditszapc | Copia il secondo operando nel primo e ne estende il segno. |
| MOVZX | * | 3-6 | oditszapc | Copia il secondo operando nel primo e azzera il resto del primo operando. |
| MUL | * | 9-41 | oditszapc * ????* | Moltiplicazione senza segno di AL o AX |
| NEG | * | 2-6 | oditszapc * ***** | Negazione dell'operando in complemento a due |
| NOP | 90 | 3 | oditszapc | Nessuna operazione. Sinonimo di XCHG AX, AX (vedi). |
| NOT | * | 2-6 | oditszapc | Negazione logica dell'operando |
| OR | * | 2-7 | oditszapc 0 **?*0 | Or logico inclusivo di due operandi. |
| OUT | * | 10-25 | oditszapc | Scrittura di un byte o di una word nella porta di I/O specificata dall'operando. |
| OUTS* | * | 8-28 | oditszapc | Scrittura di un byte o di una word di una stringa nella porta di I/O specificata dall'operando. |
| POP* | * | 5-24 | oditszapc ********* | Caricamento dallo stack di alcuni registri. Il valore del puntatore alla cima dello stack, lo Stack Pointer SP, viene decrementato di tante unità quanti byte sono stati letti. |
| PUSH* | * | 2-18 | oditszapc | Scrittura nello stack di alcuni registri. Il valore del puntatore alla cima dello stack, lo Stack Pointer SP, viene decrementato di tante unità quanti byte sono stati scritti. |
| RCL | * | 9-10 | oditszapc * * | Rotazione a sinistra dell'operando con carry: tutti i bit dell'operando vengono spostati di una posizione a sinistra e in quella rimasta libera viene copiato il valore del flag di carry, che assume il valore del bit uscito da destra. |
| RCR | * | 9-10 | oditszapc * * | Rotazione a destra dell'operando con carry: tutti i bit dell'operando vengono spostati di una posizione a destra e in quella rimasta libera viene copiato il valore del flag di carry, che assume il valore del bit uscito da sinistra. |
| RET | * | 10-68 | oditszapc | Ritorno da una subroutine o da una procedura a basso livello. |
| ROL | * | 3-7 | oditszapc * * | Rotazione a sinistra dell'operando: tutti i bit dell'operando vengono spostati di una posizione a sinistra e quello uscito all'estrema sinistra viene copiato nella posizione liberatasi a destra. |
| ROR | * | 3-7 | oditszapc * * | Rotazione a destra dell'operando: tutti i bit dell'operando vengono spostati di una posizione a destra e quello uscito all'estrema destra viene copiato nella posizione liberatasi a sinistra. |
| SAHF | 9E | 3 | oditszapc ********* | Scrittura del contenuto di AH nel registro dei flag. |
| SAL | * | 3-7 | oditszapc * **?** | Spostamento dei bit dell'operando N volte a sinistra: i bit fuoriusciti da sinistra vengono persi. Se nessun bit viene perso, questa operazione equivale ad una moltiplicazione per $2^N.$ |
| SAR | * | 3-7 | oditszapc * **?** | Spostamento dei bit dell'operando N volte a destra: i bit fuoriusciti da destra vengono persi. Questa operazione equivale ad una divisione per $2^N$ senza resto. |
| SBB | * | 2-7 | oditszapc * ***** | Sottrazione intera con riporto. |
| SCAS* | * | 7 | oditszapc * ***** | Confronto di stringhe. Le posizioni di memoria puntate dai registri SI e DI (o ESI ed EDI) vengono confrontate e i due registri incrementati/decrementati di uno a seconda del valore del flag D. Questa istruzione si usa spesso con prefissi REP*. |
| SETcc | * | 4-5 | oditszapc | Impostazione del byte in base alla condizione specificata. In modo analogo alle istruzioni Jcc, se i valori dei flag sono quelli imposti dalla particolare versione di SETcc usata, nel byte operando viene scritto il valore 1. |
| SGDT | 0F 01 /0 | 9 | oditszapc | Memorizzazione della tabella del descrittore globale. Ad esclusivo uso e consumo dei sistemi operativi. |
| SHL | * | 3-7 | oditszapc * **?** | Spostamento a sinistra dei bit dell'operando: il bit fuoriuscito da sinistra è perso. Se era zero, l'operazione equivale ad una moltiplicazione per 2. |
| SHLD | * | 3-7 | oditszapc ? **?** | Spostamento a sinistra dei bit dell'operando in doppia precisione. Come SHL, ma coinvolge anche un secondo registro, concatenato al primo. |
| SHR | * | 3-7 | oditszapc * **?** | Spostamento a destra dei bit dell'operando: il bit fuoriuscito da destra è perso. L'operazione equivale ad una divisione per 2 senza resto. |
| SIDT | 0F 01 /1 | 9 | oditszapc | Memorizzazione della tabella degli interrupt in modalità protetta. Ad esclusivo uso e consumo dei sistemi operativi. |
| SHRD | * | 3-7 | oditszapc ? **?** | Spostamento a destra dei bit dell'operando in doppia precisione. Come SHR, ma coinvolge anche un secondo registro, concatenato al primo. |
| SLDT | 0F 00 /0 | 2 | oditszapc | Carica il registro della tabella del descrittore locale. Usata soltanto nei sistemi operativi. |
| SMSW | 0F 01 /4 | 2-3 | oditszapc | Memorizzazione della parola di stato della macchina (Machine Status Word) |
| STC | F9 | 2 | oditszapc 1 | Imposta a uno il flag di Carry |
| STD | FD | 2 | oditszapc 1 | Imposta a uno il flag di Direzione |
| STI | FB | 3 | oditszapc 1 | Imposta a uno il flag di Interrupt |
| STOS* | * | 4 | oditszapc | Memorizza il valore di AL/AX/EAX nella posizione di una stringa puntata da DI (o EDI). Dopodiché il valore di (E)DI viene incrementato/decrementato a seconda del valore del flag D. |
| STR | 0F 00 /1 | 23-27 | oditszapc | Memorizza il registro dei task. Utile solo ai sistemi operativi. |
| SUB | * | 2-7 | oditszapc * ***** | Sottrazione intera. |
| TEST | * | 2-5 | oditszapc 0 **?*0 | Confronto logico non distruttivo di due operandi. Viene eseguito l'AND logico fra i due, ma il risultato non viene memorizzato: vengono modificati soltanto i flag. |
| VERR | 0F 00 /4 | 10-11 | oditszapc * | Verifica di accesso in lettura di un segmento: se sì, il flag Zero viene posto a 1, altrimenti viene azzerato. |
| VERW | 0F 00 /5 | 15-16 | oditszapc * | Verifica di accesso in scrittura di un segmento: se sì, il flag Zero viene posto a 1, altrimenti viene azzerato. |
| WAIT | 9B | 6 | oditszapc | Il processore si ferma finché il segnale esterno BUSY# (proveniente dal coprocessore matematico) non si disattiva: si usa per sincronizzare i calcoli del coprocessore con quelli della CPU principale. |
| XCHG | * | 3-5 | oditszapc | Scambia i valori dei due operandi. |
| XLAT/XLATB | D7 | 5 | oditszapc | Trasformazione con tabella di consultazione. Il valore corrente di AL viene sostituito con quello nella cella di memoria della tabella puntata da DS:BX + AL stesso. |
| XOR | * | 2-7 | oditszapc 0 **?*0 | OR logico esclusivo fra due operandi. |

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

