Comprendre l'endianness (boutisme): little-endian et big-endian

Introduction

Lors de l'exécution d'une application, les processeurs travaillent avec des valeurs numériques appelées variables. Par exemple, un processeur peut additionner, soustraire ou multiplier des variables. Une variable est stockée à une adresse donnée dans le mémoire (ou plutôt à partir d'une adresse donnée, comme nous allons le voir). Elle a également une taille donnée, qui peut être exprimée en bytes ou en bits. Cela peut être une valeur composée d'un byte unique ("single-byte") (8 bits) ou de plusieurs bytes ("multi-byte") (n x 8 bits).

Quand une variable est "single-byte", l'adresse de la variable pointe évidemment sur son unique byte.

Mais s'il s'agit d'une variable "multi-byte", sur lequel de ses bytes l'adresse de la variable pointe-t-elle, et dans quel ordre sont ils stockés? La réponse est: cela dépend.

Définition de l'endianness (ou boutisme)

En informatique, le terme "endianness" (ou "boutisme" en français, plus rarement utilisé), se réfère à l'ordre dans lequel les bytes d'une variable sont stockés en mémoire. L'endianness dépend de l'architecture d'un processeur.

Le concept d'endianness existe également pour les protocoles réseau pour l'ordre des bytes de données dans une trame (message), ainsi que pour les formats de fichiers pour l'ordre des bytes dans un flux de données.

Les deux types principaux d'endianness sont appelés little-endian et big-endian.

Voici une comparaison de ces deux types d'endianness:

Type d'endianness Little-endian (LE) Big-endian (BE)
Ordre des bytes Le byte de poids faible (least significant byte, LSB) (le "petit bout") est stocké en premier (à l'adresse mémoire la plus basse). Le byte de poids fort (most significant byte, MSB) (le "gros bout") est stocké en premier (à l'adresse mémoire la plus basse).
Exemples d'architectures de processeurs Intel x86
La plupart des processeurs basés sur ARM: Apple silicon, STM32, PIC32
ESP32
RISC-V
MSP430
Motorola 68000
PowerPC
SPARC
Exemples de protocoles réseau USB
CANopen
TCP/IP
Modbus
Exemples de formats de fichiers BMP
GIF
PNG
JPEG
Autres noms Petit-boutiste
LSB-first
Intel order
Gros-boutiste
MSB-first
Motorola order

Exemples

Voyons l'impact de l'endianness pour une valeur d'un seul byte, avec la valeur 0x42:

Comparaison de l'endianness pour une valeur d'un seul byte

Evidemment, dans le cas d'une valeur d'un seul byte, l'endianness n'a aucun impact, comme le pointeur pointe vers son unique byte, peu importe son endianness.

Voyons maintenant l'impact de l'endianness pour une valeur de 32-bits (4 bytes), avec la valeur 0x12345678:

Comparaison de l'endianness pour une valeur de 32-bits

Pour une valeur de plusieurs bytes, l'endianness a une influence notable. Le pointeur (adresse mémoire la plus basse parmi tous les bytes de la variable) pointe sur le byte de poids faible (LSB) dans le cas du little-endian, alors qu'il pointe sur le byte de poids fort (MSB) dans le cas du big-endian.

Quand l'endianness peut-il être un problème ?

Dans de nombreux cas, nous n'avons pas à nous soucier de l'endianness. Dans un application dans laquelle on lit et écrit simplement des variables, et on les utilise, le processeur les lit et les écrit selon son endianness "naturel".

Cependant, dans certaines situations spécifiques, une gestion correcte de l'endianness est cruciale:

  • Protocoles réseau

    Quand on envoie ou reçoit des données par un protocole réseau, les données sont généralement placées dans un buffer en mémoire dans le même ordre que ces données sont reçues. Si l'endianness du protocole est différent de celui de la machine, il est alors nécessaire d'échanger les bytes ("bytes swapping") des valeurs à plusieurs bytes.

  • Shared memory

    Quand des valeurs sont stockées dans une mémoire partagée par deux (ou plus) processes qui tournent sur des processeurs différents basés sur des architectures différentes, leur endianness peut être différent. Dans ce cas, un format commun (par rapport à l'endianness) doit être défini, et les bytes doivent être réordonnées si cela s'avère nécessaire.

  • Fichiers binaires

    Quand on travaille avec des fichiers binaires, l'endianness du format de fichier doit être connu, afin d'interpréter ou encoder correctement les données du fichier. L'endianness pour un format donnée peut être fixe (c'est-à-dire défini dans la spécification de ce format), ou indiqué de manière dynamique dans le fichier.

  • Manipulation de bytes par arithmétique de pointeurs

    Quand on connait l'endianness d'une application, il est possible d'extraire un byte d'une valeur en manipulant un pointeur sur cette valeur, en ajoutant un offset à son adresse de base. Mais pour cela il faut tenir compte de l'endianness du système.

Conclusion

En informatique, l'endianness est un concept simple, mais crucial à comprendre, spécialement en programmation bas niveau, réseau et manipulation de fichiers binaires.

L'endianness peut être vu comme une convention pour l'encodage de valeurs de plusieurs bytes (multi-byte): l'endianness défini si le bytes de poids faible (little-endian) ou le byte de poids fort (big-endian) est stockée en premier dans la mémoire, c'est-à-dire à l'adresse la plus basse.