# Intel 8086

L'Intel 8086 (également appelé iAPX 86) est un microprocesseur CISC 16 bits fabriqué par Intel à partir de 1978. C'est le premier processeur de la famille x86, qui est devenue l'architecture de processeur la plus répandue dans le monde des ordinateurs personnels, stations de travail et serveurs informatiques en raison du choix d'IBM de l'utiliser comme base de l'IBM PC sorti quelques années après. Son principal concurrent était le Motorola 68000 sorti en 1979 et notamment utilisé dans les Apple Macintosh.
Il fut lancé en mai 1978 au prix de 360 dollars.
Successeur du 8080, un processeur 8 bits, il adopte une architecture totalement 16 bits : les registres, le bus de données et les calculs sont réalisés en 16 bits. Son bus d'adresse est quant à lui de 20 bits, ce qui lui permet d'adresser 1 Mo d'espace mémoire. Par comparaison, le 68000 sera un an plus tard une solution hybride 16/32 bits, utilisant des registres en 32 bits, un bus d'adresse de 24 bits, et une ALU et bus de données de 16 bits.
Il contient 29 000 transistors gravés en 3 µm. Sa puissance de calcul varie de 0,33 MIPS (lorsqu'il est cadencé à 4,77 MHz comme dans l'IBM PC) jusqu'à 0,75 MIPS pour la version 10 MHz.
Capable de réaliser les 4 opérations fondamentales sur les nombres entiers (ADD, SUB, MUL, DIV), il peut aussi être étendu par l'interconnexion avec un coprocesseur Intel 8087 qui lui ajoute des capacités de traitement des nombres en virgule flottante.

## Histoire

Le projet 8086 a débuté en mai 1976. Il était initialement conçu comme un substitut temporaire pour le iAPX 432, projet très ambitieux et qui n’était pas encore abouti et qui sera, quelques années plus tard, un échec commercial. Intel espérait ainsi évincer les processeurs de la concurrence (notamment Motorola, Zilog et MOS Technology) tout en contrant la menace du Z80, conçu par un ex-employé d'Intel ayant travaillé sur le 8080.
L'architecture de la puce a été développée rapidement par un petit groupe de personnes, en utilisant les mêmes techniques de fabrication que pour l'Intel 8085 pour en assurer la compatibilité.
Permettant l'utilisation du même langage assembleur que pour les 8008, 8080 et 8085, le 8086 a été ainsi présenté comme parfaitement compatible, nécessitant peu ou pas de modification du code source des programmes. Il offre toutefois un support complet du 16 bits, au contraire des 8080 et 8085 qui n’avaient que des capacités 16 bits très basiques.
Toujours dans le but de faciliter son adoption, le fabricant déclinera en 1979 une version nommée 8088 dont les bus externes sont réduits à 8 bits (données) et 16 bits (adresse) pour le rendre plus compatible avec les cartes mères 8 bits conçues pour l'Intel 8080. Cette démarche existera également pour ses successeurs tels que le 80186 (80188).

## Anecdote

En 2002, du fait de l'obsolescence de ses systèmes de validation, la NASA s'est vu obligée d'acheter des processeurs 8086 sur eBay car ils n'étaient plus fabriqués par Intel depuis les années 90.
En 2018, Intel lance un processeur en édition limitée, l'Intel Core i7-8086K, pour commémorer les 40 ans de l'Intel 8086.

## Packaging

Plusieurs versions du 8086 existent, avec différents types de boitier et plusieurs fréquences maximales supportées.
Les boitiers peuvent être en céramique ou en plastique. Le suffixe du 8086 indique la fréquence maximale : 5 MHz pour le 8086, 8 MHz pour le 8086-2, et 10 MHz pour le 8086-1.
* Une version plastique P8086.

## Variantes

En 1979, Intel lance une variante de ce processeur, mais avec un bus externe de données de seulement 8 bits, c'est l'Intel 8088. C'est cette version moins chère qui a été choisie par IBM pour créer le premier IBM PC.

## Architecture
### Caractéristiques générales

* Architecture CISC : les instructions sont de taille variable et nécessitent un décodage interne pour leur exécution.
* Unité Arithmétique et Logique fonctionnant en 16 bits, réalisant les 4 opérations fondamentales sur les entiers.
* Extension possible au traitement des nombres à virgule flottante par adjonction d'un coprocesseur dédié.
* Registres généraux de 16 bits utilisables par paires en 8 bits.
* Bus mémoire et de données de 16 bits
* Bus d'adresse de 20 bits, capable d'adresser 1 Mo
* Pas de mode de fonctionnement spécifique (d'autres processeurs tels que le 68000 proposent déjà à l'époque une distinction entre mode utilisateur et mode système d'exploitation)
* Gestion de 256 interruptions dont une partie purement software
* Ports d'entrée / sortie disposant d'un espace d'adressage (et donc d'un jeu d'instructions) spécifique, pouvant également être mappé en mémoire

### Adressage mémoire

Le processeur dispose d'un bus d'adresse de 20 bits alors que son architecture repose sur une ALU 16 bits. Afin de s'affranchir de cette contrainte, le processeur utilise un mécanisme de segmentation de la mémoire : l'adresse d'un octet est obtenue par la combinaison de deux registres de 16 bits via une opération d'addition produisant un résultat sur 20 bits.
Concrètement, un registre dit de segment délimite un bloc de 64 Ko de mémoire dont l'adresse de début est égale à valeur_du_registre x 0x10 (donc un décalage à gauche de 4 bits : la valeur 0x1234 spécifie donc l'adresse réelle 0x12340). A cette valeur issue du registre de segment on ajoute une valeur dite offset qui provient soit d'un autre registre plus général, soit d'une valeur directe du programme.
L'adresse d'un octet est donc déterminée ainsi : adresse_physique = valeur_registre_segment x 0x10 + offset.
Le segment est toujours identifié par l'un des 4 registres de segment de l'ALU : CS, DS, SS ou ES.
Par convention, les adresses segmentées sont notées ainsi : XX:YY où XX est le nom du registre de segment utilisé (ou parfois une valeur directe) et YY le nom du registre contenant l'offset (ou à nouveau une valeur directe).
Par exemple CS:IP est une adresse formée par combinaison du registre de Code Segment (CS) et du registre d'Instruction Pointer (IP).

### Registres

Contrairement au 68000, dont l'architecture très orthogonale permet de considérer la plupart des registres comme équivalents, les registres du 8086 ont soit une fonction dédiée, soit des caractéristiques spécifiques se traduisant par des opérations ne s'appliquant qu'à eux. Il est donc important de bien connaître les capacités de chacun des registres et, pour construire un code efficace, de favoriser l'utilisation optimale de ces derniers.
* Le couple CS:IP (Code Segment : Instruction Pointer) indique en permanence l'instruction en cours d'exécution. Les opérations de saut (jumps, call...) aboutissent à des modifications soit de IP (saut court ou NEAR) soit de l'ensemble CS:IP (saut long ou FAR) ;
* Le couple SS:SP (Stack Segment : Stack Pointer) indique en permanence l'adresse du début de la pile. Un autre registre nommé BP (Base Pointer) se combine également avec le segment de pile sous la forme SS:BP. Le registre BP n'est pas utilisé par l'ALU directement, contrairement à SP qui est modifié par les opérations telles que CALL, RET, PUSH ou POP. De ce fait, BP est généralement utilisé pour marquer un emplacement spécifique de la pile et s'y référer ensuite (variables locales d'une fonction ou passage de paramètres par exemple) ;
* Le registre de segment DS (Data Segment) indique en permanence le segment de données vers lequel d'autres registres sont susceptibles de pointer. Les registres généraux (voir plus bas) s'y réfèrent souvent, mais 2 autres registres lui sont dédiés : SI (Source Index) et DI (Destination Index). Ces registres sont dédiés aux opérations répétitives sur des blocs de données indexés, DS:SI pointant sur l'adresse source et DS:DI pointant sur l'adresse destination, quand elle est nécessaire (exemple : opération de copie d'un bloc mémoire) ;
* Le registre de segment ES (Extra Segment) est libre d'usage et permet, pour certaines opérations, de pointer un segment de données différent de celui pointé par DS ;
* Les registres généraux permettent la manipulation courante des données (calculs). Il s'agit des registres AX, BX, CX et DX, chacun de ces registres pouvant être utilisé dans des variantes de 8 bits par paire. Ainsi le registre AX est la combinaison de AH et AL, AH contenant les 8 bits de poids fort (H = High) de AX, AL (L = Low) contenant quant à lui les 8 bits de poids faible ;
* Le registre des drapeaux (flags) qui indique en permanence l'état de l'ALU et en particulier de la dernière instruction exécutée.

### Interruptions

Le processeur dispose d'un total de 256 interruptions, certaines liées au matériel, d'autres utilisables par les logiciels. La table d'interruption est un bloc mémoire de 1024 octets débutant à l'adresse physique 0x00000 et comportant 256 pointeurs sous la forme Segment:Offset (donc 4 octets chacun, pour une adresse de 20 bits). La table des vecteurs d'interruption s'étend donc jusqu'à l'adresse 0x003FF. Chaque pointeur indique l'adresse du gestionnaire d'interruption associé. Ainsi le premier pointeur correspond à l'interruption 0, etc.
Lorsqu'une interruption de numéro X est levée, le processeur charge le pointeur présent à l'adresse mémoire X * 4 dans les registres CS:IP, après avoir sauvegardé leur contenu sur la pile.
Le numéro de l'interruption dépend de sa provenance :
* Le numéro d'une interruption matérielle, levée par la sollicitation de la broche INTR du processus, est obtenu par interrogation du contrôleur externe d'interruption réalisée par le CPU durant la phase d'acquittement de l'interruption. Un octet est lu, qui fournit la valeur de X ;
* Lorsque c'est la broche NMI (interruption non masquable) qui est sollicitée, le numéro d'interruption levé est automatiquement 2 ;
* Lorsque l'interruption est d'origine logicielle (instruction INT X), la valeur de X est portée par le paramètre de l'instruction.
La même logique de calcul de l'adresse du gestionnaire étant utilisée pour chaque type d'interruption, il n'existe pas de distinction réelle entre interruptions matérielles, non masquables ou logicielles. Il convient donc d'éviter les recouvrement dans l'affectation des numéros.
Les 5 premières interruptions sont réservées et produites par le processeur lui-même, soit directement, soit en liaison avec les composants périphériques :
* L'interruption 0 est produite lorsqu'une division par ZERO intervient dans l'ALU ;
* L'interruption 1 est produite l après chaque instruction lorsque le processeur est placé en mode pas à pas par le drapeau correspondant du registre de drapeaux ;
* L'interruption 2 est produite lorsque la broche NMI (Non Maskable Interrupt) du processeur reçoit un signal ;
* L'interruption 3 est produite lorsque le processeur atteint une instruction INT, également appelée instruction BREAK. Elle est utilisée pour l'exécution pas à pas d'un programme, par exemple par un déboggeur ;
* L'interruption 4 est produite lorsqu'une opération arithmétique provoque un dépassement de capacité (overflow), sous réserve que ce fonctionnement soit activé par le registre de drapeaux ;
Pour cette raison, les interruptions matérielles ou logicielles de 0 à 4 ne sont pas utilisables et, d'une façon plus large, la spécification réserve les interruptions 5 à 31 à l'usage du matériel.
Toutes les autres interruptions, 32 et au-delà, sont libres d'usage et peuvent notamment être déclenchées par une instruction INT x.

### Ports d'entrées/sorties

Les ports d'E/S disposent de leur propre espace d'adressage couvrant un total de 64 Ko. Les ports s'étendent de 0x0000 à 0xFFFF et sont manipulés par deux instructions spécifiques :
* IN pppp,vv pour lire une valeur (octet) depuis le port numéro pppp ;
* OUT pppp,vv pour écrire une valeur (octet) vers le port numéro pppp ;