Порядок следования байтов: LE против BE

Перед тем, как разобраться с разными порядками следования байтов для записи целых чисел в памяти ЭВМ, рекомендуется вспомнить способы машинного представления целых чисел:

Порядок следования битов

Тут же следует договориться, что в двоичной записи чисел нумеровать биты будем по старшинству разрядов. То есть если представить двоичную запись числа в виде разложения по степеням основания позиционной системы счисления, то младший бит b0 — это коэффициент при младшем разряде, то есть при двойке в нулевой степени:

 x = bn−1 2n−1 + bn−2 2n−2 + . . . + b2 22 + b1 21 + b0 20bn−1 bn−2 . . . b2 b1 b0

Так, например, число 23710 имеет в двоичной системе счисления два нулевых бита b1 и b4, так как в многочлене слагаемые с первой и четвертой степенью двойки имеют нулевые коэффициенты:

 23710 = 1 × 27 + 1 × 26 + 1 × 25 + 0 × 24 + 1 × 23 + 1 × 22 + 0 × 21 + 1 × 20 → 111011012

1 1 1 0 1 1 0 1
b7 b6 b5 b4 b3 b2 b1 b0

Важно, что договориться надо только о старшинстве и нумерации битов, а то, как они располагаются (слева-направо или справа-налево) в ячейке памяти, абсолютно не важно. Дело в том, что напрямую из памяти можно прочитать только ячейку целиком. А когда ячейка уже загружена в регистр центрального процессора, можно работать с отдельными битами с помощью арифметико-логических операций. Тут-то и пригодится соглашение о том, как мы нумеруем биты для соблюдения консенсуса.

Порядок следования байтов

Длинные целые числа в памяти могут занимать несколько соседних ячеек: слово (2 ячейки), двойное слово (4 ячейки), четверное слово (8 ячеек) и т. д. В пределах одной ЭВМ, на первый взгляд, не так важно, в каком порядке хранятся части длинного целого числа в памяти.

От младшего к старшему (Little-Endian)

Если длинное число разместить в памяти от младшего байта к старшему в порядке возрастания адресов памяти, тогда на иллюстрации можно использовать единое направление порядка нумерации битов и нумерации ячеек памяти. Так, например, представление числа 1 957 227 809 (111 0100 1010 1000 1110 1101 0010 00012, 74 A8 ED 2116) по адресу Y будет выглядеть так:

7 4
0 1 1 1 0 1 0 0
b7 b6 b5 b4 b3 b2 b1 b0
Y + 3
 
A 8
1 0 1 0 1 0 0 0
b7 b6 b5 b4 b3 b2 b1 b0
Y + 2
 
E D
1 1 1 0 1 1 0 1
b7 b6 b5 b4 b3 b2 b1 b0
Y + 1
 
2 1
0 0 1 0 0 0 0 1
b7 b6 b5 b4 b3 b2 b1 b0
Y
N ←  адреса ячеек ← 0

Кстати, такой способ иллюстрации позволяет легко понять, где находится, например, 25-й бит этого большого числа. Так как направление порядка нумерации битов и ячеек памяти тут совпадает, то можно перенумеровать биты всего числа «насквозь»:

7 4
0 1 1 1 0 1 0 0
b31 b30 b29 b28 b27 b26 b25 b24
Y + 3
 
A 8
1 0 1 0 1 0 0 0
b23 b22 b21 b20 b19 b18 b17 b16
Y + 2
 
E D
1 1 1 0 1 1 0 1
b15 b14 b13 b12 b11 b10 b9 b8
Y + 1
 
2 1
0 0 1 0 0 0 0 1
b7 b6 b5 b4 b3 b2 b1 b0
Y
N ←  адреса ячеек ← 0

И тогда сразу видно, что 25-й бит располагается в байте по адресу Y + 3.

От старшего к младшему (Big-Endian)

А если длинное число размещать в памяти от старшего байта к младшему в порядке возрастания адресов памяти, тогда на иллюстрации надо поменять направление нумерации ячеек памяти, и рисовать их слева-направо:

7 4
0 1 1 1 0 1 0 0
b31 b30 b29 b28 b27 b26 b25 b24
Y
 
A 8
1 0 1 0 1 0 0 0
b23 b22 b21 b20 b19 b18 b17 b16
Y + 1
 
E D
1 1 1 0 1 1 0 1
b15 b14 b13 b12 b11 b10 b9 b8
Y + 2
 
2 1
0 0 1 0 0 0 0 1
b7 b6 b5 b4 b3 b2 b1 b0
Y + 3
0 →  адреса ячеек → N

Еще раз взгляните на иллюстрации и найдите «10 отличий». Согласитесь, что разница только в направлении порядка нумерации ячеек памяти. Именно поэтому рекомендуется при решении задач менять направление нумерации адресов памяти, чтобы не нарушать привычный естественный порядок записи числа в позиционной системе счисления.

Почему не остался только один вариант?

Большинство ЭВМ (за некоторым исключением) размещают данные в памяти в порядке возрастания старшинства: младшие значения размещают в ячейках с меньшим адресом, а старшие значения — в ячейках с большим адресом (LE — Little Endian). Такой подход упрощает обработку длинных данных, занимающих несколько ячеек памяти подряд.

Но при межмашинном взаимодействии, например, по вычислительной сети, применяются сетевые протоколы, среди которых наиболее распространенный протокол TCP/IP использует порядок Big-Endian. TCP/IP — основа современной сети Интернет — вырос из североамериканского проекта ARPANET военного ведомства DARPA, который развивался в эпоху вычислительных машин семейства IBM System/360. А это как раз те самые ЭВМ, в которых применялся порядок следования байтов «от старшего к младшему», то есть Big-Endian.

Более того, порядок BE можно встретить в цифровых форматах мультимеда, используемых для хранения медиаданных или для потоковой трансляции.