# Architecture 16 bits

En informatique, l’architecture 16 bits est un type de structure d'ordinateur exploitant des mots (processeur, mémoire, bus, etc.) d'une taille de 16 bits (soit deux octets).
Un mot de 16 bits peut stocker 2$^{16}$ valeurs différentes, soit 65 536 valeurs. Un processeur 16 bits peut donc directement adresser 64 kio de mémoire.

## Histoire

Au milieu des années 1960, les premiers ordinateurs 16 bits commercialisés incluent le HP-2116 de HP, le PDP-11 de DEC et le Nova de Data General. Ils sont conçus et fabriqués à base de composants discrets et de ce fait relativement complexes et volumineux.
Vers le milieu des années 1970, des microprocesseurs $^8$⁄$_{16}$ bits (bus de données 8 bits, bus d'adresse de 16 bits) se multiplient, comme le Zilog Z80, le MOS Technology 6502 ou le Motorola 6809.
Le TMS9900 de Texas Instrument est un des premiers microprocesseur 16 bits, et a été utilisé dans les ordinateurs familiaux TI-99/4 à partir de 1979.
Au début des années 1980, les constructeurs développent des microprocesseurs 16 bits, comme l’Intel 8086, l’Intel 80286 et le MOS Technology 65C816. Les registres et les instructions arithmétiques de l'Intel 8088 opéraient sur des entiers de 16 bits, mais sa mémoire et son bus de données externe ne sont que de 8 bits de large.
Un entier de 16 bits permet de stocker 2$^{16}$ (soit 65 536) valeurs différentes. Dans une représentation non signée, ces valeurs sont des entiers compris entre 0 et 65 535. Dans une représentation en complément à deux, ces valeurs sont comprises entre −32 768 et 32 767. Par conséquent, un processeur gérant des adresses mémoire de 16 bits peut accéder directement à 64 kio de mémoire.

## Modèles de la mémoire 16 bits

Les processeurs 16 bits ont disparu de l'industrie des ordinateurs personnels actuels (remplacé par 64 bits), mais ils restent en service dans une grande variété d'applications embarquées. Par exemple, le processeur 16 bits XAP est utilisé dans de nombreux circuits ASIC.

### Intel 8086 80186 et 80286

En 1978, Intel utilise des registres 16 bits dans son 8086. Une adresse peut représenter un espace de 64 Ko comme sur le 8080/8085 mais le processeur utilise différents registres de segment 16 bits selon les instructions. Chaque segment pointe sur une zone de la mémoire et élargit l'adresse à 20 bits, la véritable adresse physique est calculée par segment * 16 + offset (l'offset étant celui spécifié comme adresse). Le 8086 peut ainsi accéder à 1 Mo de mémoire malgré ses registres 16 bits, à condition de jouer sur les contenus des registres segments pendant l'exécution.
Les registres de segment sont au nombre de quatre :
* CS est utilisé par le pointeur de code, il indique où exécuter la prochaine instruction, il est implicite dans les instructions de saut ou d'appel de routines
* SS pointe sur la pile d'exécution pour les adresses de retour des CALL ou le passage de paramètres, il est lui aussi implicite
* DS et ES sont en usage libre pour l'accès aux données
Ce mode d'accès à la mémoire est assez lourd puisqu'à un moment donné, seuls 64 Ko de code, 64 Ko de pile et deux blocs de 64 Ko de données sont accessibles sans modifier le contenu des registres de segment.
Ce mode est dit réel car le registre segment et l'offset représentent directement la véritable adresse physique. Il est dangereux puisque le programme peut écrire à n'importe quelle adresse, pire encore il peut le faire de plusieurs façons différentes (une même adresse physique peut être représentée de multiples manières avec des segments et offsets différents). Néanmoins, le modèle permet une transposition assez simple des programmes développés pour les processeurs 8 bits, et facilite l'architecture interne en utilisant un bus interne de 16 bits qui n'induit aucun retard pour véhiculer les données de registre à registre ou de registre à mémoire. Il permet aussi de séparer physiquement le code et les données si l'on gère correctement le calcul des segments.
Le 80186 qui lui succède en 1982 fonctionne comme le 8086 en matière d'adressage mémoire. Il sera principalement employé comme un 8086 plus rapide, ses fréquences allant au delà de celles de son prédécesseur.
Avec le 80286 qui apparait lui aussi début 1982, Intel met en place un mode protégé : le registre de segment pointe alors vers un bloc de données appelé descripteur, qui pointe vers la véritable zone mémoire et l'isole des autres segments. De plus, le segment de code est protégé contre l'écriture pendant l'exécution. La largeur du bus passe à 24 bits, le processeur peut donc adresser 16 Mo de mémoire. Le mode protégé possède aussi des dispositifs de commutation de tâches.
Un mode réel compatible avec le 8086 reste accessible sur le 80286, mais cela le cantonne dans le rôle d'un super 8086 plus rapide pour MS-DOS et Windows 3. Le changement de mode implique un reset du processeur et implique généralement de rester dans le mode protégé, interdisant la compatibilité avec les programmes MS-DOS. En dehors des systèmes XENIX et OS/2, peu d'applications bénéficient du mode protégé du 80286. Il ouvre néanmoins la porte au mode protégé du futur 32 bits Intel 80386.

### Motorola 68000 et 68010

De son côté, Motorola choisit en 1979 de reproduire dans son 68000 le modèle des processeurs 8 bits : données sur 16 bits (au lieu de 8), adresses sur 32 (au lieu de 16). Mais Motorola va plus loin car tous les registres ont une taille de 32 bits : les instructions peuvent ainsi gérer les données sur 8, 16 ou 32 bits bien que l'ALU et le bus interne soient de 16 bits.
Les adresses peuvent être exprimées sur 32 bits linéaires, toutefois l'espace physique réellement accessible est de 16 Mo en raison des limites du bus à 24 signaux d'adresse.
Ce modèle est lui aussi un mode réel et les adresses physiques correspondent directement aux adresses dans les registres. Toutefois le 68000 possède quatre états qui permettent de séparer la mémoire en quatre zones protégées les unes des autres selon l'état, pour empêcher par exemple le programme utilisateur d'écrire dans les zones superviseur.
Motorola ajoute quelques améliorations dans le 68010 mais le modèle mémoire ne change pas fondamentalement.

### Modèles mémoire des compilateurs sur 16 bits Intel

Les compilateurs de langages de programmation sont confrontés au modèle de la mémoire segmentée sur les processeurs Intel. En raison du mode mémoire linéaire sur le Motorola 68000, les compilateurs n'ont généralement pas à gérer la taille des pointeurs, bien que manière les pointeurs 32 bits soient ralentis par un bus interne de 16 bits seulement.
Le Turbo Pascal 3.0 de Borland fait l'impasse et les registres segment ne changent pas de valeur tout au long de la vie du programme : on peut donc avoir un programme d'au maximum 64 Ko de code, utilisant au maximum 64 Ko de données et 64 Ko de pile (la pile cependant peut dépasser la limite). Des librairies de Turbo Power pour ce compilateur gèrent les segments pour relier plusieurs parties de code ou utiliser davantage de données, au détriment de la vitesse d'exécution.
Mais la plupart des compilateurs vont s'écarter de ce modèle simpliste, y compris Borland à partir de Turbo Pascal 4.0 et vont utiliser soit des adressages near sur seulement 16 bits d'adresse, soit des adressages far combinant 16 bits de segment et 16 bits d'adresse. L'utilisation des pointeurs far pénalise la vitesse d'exécution, mais donne accès à tout l'espace mémoire surtout à partir du 80286 qui peut accéder à 16 Mo.
Dans les compilateurs Turbo Pascal, le choix des pointeurs near ou far pour le code est effectué par le compilateur selon la proximité du code, et les données sont toujours en pointeurs far. L'utilisateur peut forcer le compilateur à n'utiliser que des pointeurs far dans le code à l'aide d'une option ou d'une directive de compilation.
Dans le compilateur Borland C++, le choix est accessible par le biais des mots clés ajoutés au langage near far et huge, et des options de compilation choisissent le modèle mémoire à employer par le compilateur :
Modèles mémoire de Borland C++ 3.1 :
| Modèle | Pointeur de code | Pointeur de données | Remarque |
| tiny | near (16) | near (16) | Code et données sont dans le même segment (les registres CS, DS, ES, SS pointent vers le même segment). Les pointeurs near sont toujours utilisés. Code, données et pile ensemble ne peuvent pas excéder 64 Ko |
| small | near (16) | near (16) | Code et données sont dans des segments différents, et les pointeurs near sont toujours utilisés. Il y a 64 Ko d'espace disponible pour le code et 64 Ko pour les données et la pile. |
| medium | far (32) | near (16) | Le code utilise des pointeurs far permettant l'accès à 1 Mo de code. Les pointeurs de données restent du type near limitant les données à 64 Ko. |
| compact | near (16) | far (32) | Les données utilisent des pointeurs far pour 1 Mo de données, le code reste sur des pointeurs near permettant 64 Ko de code. Les données statiques utilisent des pointeurs near et sont limitées à 64 Ko séparés. |
| large | far (32) | far (32) | Code et données peuvent accéder à 1 Mo chacun. Les données statiques utilisent des pointeurs near et sont limitées à 64 Ko séparés. |
| huge | far (32) | far (32) | Code et données accèdent à 1 Mo, y compris les données statiques. |
Des modèles similaires sont disponibles avec le compilateur Microsoft C/C++ dès 1983.

### Types de données compilateurs sur processeur 16 bits

Les compilateurs de l'ère 16 bits proposent généralement des types de données entières d'une taille prédéterminée :
Types de nombres entiers 16 bits :
| Modèle de données | short | int | long | Pointeurs |
| IP16L32 (near) | 16 | 16 | 32 | 16 |
| I16LP32 (far) | 16 | 16 | 32 | 32 |
Lors du passage aux processeurs 32 bits et au modes protégés, les entiers int passeront parfois à 32 bits en particulier en langage C et C++ : ils ne définissent pas strictement la taille du type int qui est laissée à l'appréciation du compilateur. Le type int étant facultatif car type par défaut, les modificateurs short et long exprimés seuls sont gérés comme des synonymes de short int et long int par le compilateur.
En langage Pascal il n'y a pas de type de données par défaut, Borland propose alors plusieurs types de données entières pour un usage optimal selon les besoins :
Types de données Turbo Pascal :
| Type | Valeurs | Taille en octets | Equivalent C |
| Byte | 0 à 255 | 1 | unsigned char |
| Shortint | -128 à 127 | 1 | char |
| Integer | -32768 à 32767 | 2 | short (int) ou int |
| Word | 0 à 65535 | 2 | unsigned short (int) ou unsigned int |
| Longint | -2147483648 à 2147483647 | 4 | long (int) |

## Le Motorola 16/32 68000 et l'Intel 386SX

Le Motorola 68000 est parfois qualifié de 16 bits parce que son bus de données et son unité arithmétique et logique ont 16 bits de large, et son bus mémoire ne peut adresser que 16 Mio de mémoire vive. Il expose toutefois une architecture 32 bits dans la mesure où ses registres généraux ont une capacité de 32 bits et que la plupart des instructions arithmétiques supportent des entiers de 32 bits. Les programmes écrits pour le Motorola 68000 sont donc compatibles avec les processeurs 32 bits de la famille M68k et exploitent pleinement leurs capacités 32 bits.
Le processeur 68000 de la Sega Mega Drive fut très mis en avant dans les publicités, la console ayant même une inscription « 16-bit » sur le dessus de sa coque, ce qui conduisit cette période de l'histoire des consoles de jeux vidéo à être qualifiée d'« ère 16 bits ».
De nombreuses machines familiales de l'époque utilisèrent le microprocesseur 68000 : le Macintosh, l'Amiga 500, l'Atari ST, le Sharp X68000 mais également la console Neo-Geo AES. Le 68000 fut utilisé dans la console Jaguar d'Atari, présentée à l'époque comme la première 64 bits du marché (alors que seule une partie de son architecture était effectivement 64 bits).
Une analyse similaire s'applique à l'Intel 80386SX, microprocesseur bas de gamme, qui est également un processeur 32 bits associé à un bus 16 bits.