Порядок следования байтов: LE против BE
Перед тем, как разобраться с разными порядками следования байтов для записи целых чисел в памяти ЭВМ, рекомендуется вспомнить способы машинного представления целых чисел:
Порядок следования битов
Тут же следует договориться, что в двоичной записи чисел нумеровать биты будем по старшинству разрядов.
То есть если представить двоичную запись числа в виде разложения по степеням основания позиционной системы счисления, то младший бит b
0 — это коэффициент при младшем разряде, то есть при двойке в нулевой степени:
x = bn−1 2n−1 + bn−2 2n−2 + . . . + b2 22 + b1 21 + b0 20
→
bn−1 bn−2 . . . b2 b1 b0
Так, например, число 237
10 имеет в двоичной системе счисления два нулевых бита b
1 и b
4, так как в многочлене слагаемые с первой и четвертой степенью двойки имеют нулевые коэффициенты:
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 0001
2, 74 A8 ED 21
16) по адресу 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 можно встретить в цифровых форматах мультимедиа, используемых для хранения медиаданных (аудио, видео) или для потоковой трансляции.