Порядок байтів

Порядок байтів - метод запису байтів мультибайтних чисел в інформатиці.

У загальному випадку, для представлення числа M, більшого 255 (тут 255 = 2 ^ 8-1 - Максимальне ціле число, що записується одним октетом), доводиться використовувати кілька байтів-октетів. При цьому число M записується в позиційній системі числення за основою 256:

M = \ sum_ {i = 0} ^ {n} A_i \ cdot 256 ^ i = A_0 \ cdot 256 ^ 0 + A_1 \ cdot 256 ^ 1 + A_2 \ cdot 256 ^ 2 + \ dots + A_n \ cdot 256 ^ n .

Набір цілих чисел A_0, \ dots, A_n , Кожне з яких лежить в інтервалі від 0 до 255, є послідовністю байтів, складових M. При цьому A_0 називається молодшим байтом, а A_n - Старшим байтом числа M.


1. Варіанти запису

1.1. Порядок від старшого до молодшого

Порядок від старшого до молодшого або ( англ. big-endian , Дослівно: "тупокінцеву"): A_n, \ dots, A_0 , Запис починається зі старшого і закінчується молодшим. Цей порядок є стандартним для протоколів TCP / IP, він використовується в заголовках пакетів даних і в багатьох протоколах більш високого рівня, розроблених для використання поверх TCP / IP. Тому, порядок байтів від старшого до молодшого часто називають мережевим порядком байтів ( англ. network byte order ). Цей порядок байтів використовується процесорами IBM 360 / 370/390, Motorola 68000, SPARC (звідси третя назва - порядок байтів Motorola, Motorola byte order).

У цьому ж виді (використовуючи уявлення в десятковій системі числення) записуються числа індійсько-арабськими цифрами в письменностях з порядком знаків зліва направо (латиниця, кирилиця). Для писемностей із зворотним порядком (арабська) та ж запис числа сприймається як "від молодшого до старшого".

Порядок байтів від старшого до молодшого застосовується в багатьох форматах файлів - наприклад, PNG, FLV, EBML.


1.2. Порядок від молодшого до старшого

Порядок від молодшого до старшого або ( англ. little-endian , Дослівно: "гострокінцевий"), про походження терміна нижче): A_0, \ dots, A_n , Запис починається з молодшого і закінчується старшим. Цей порядок запису прийнятий в пам'яті персональних комп'ютерів з x86 -процесорами, у зв'язку з чим іноді його називають интеловский порядок байтів (за назвою фірми-творця архітектури x86). У деяких колах використовується назва англ. VAX order , Наприклад, в документації Perl [1].

На противагу "тупокінцеву" порядком, менше крос-платформних протоколів і форматів даних з "гострим" порядком байт; помітні винятки: USB, конфігурація PCI, таблиця розділів GUID, рекомендації FidoNet.


1.3. Перемикається порядок

Багато процесори можуть працювати і в порядку від молодшого до старшого, і в зворотному, наприклад, ARM, PowerPC (але не PowerPC 970), DEC Alpha, MIPS, PA-RISC і IA-64. Зазвичай порядок байтів вибирається програмно під час ініціалізації операційної системи, але може бути вибраний і апаратно перемичками на материнській платі. У цьому випадку правильніше говорити про порядок байтів операційної системи. Перемикається порядок байтів іноді називають англ. bi-endian .


1.4. Змішаний порядок

Змішаний порядок байтів ( англ. middle-endian) іноді використовується при роботі з числами, довжина яких перевищує машинне слово. Число представляється послідовністю машинних слів, які записуються у форматі, природному для даної архітектури, але самі слова слідують у зворотному порядку.

Класичний приклад middle-endian - представлення 4-байтних цілих чисел на 16-бітних процесорах сімейства PDP-11 (відомий як PDP-endian). Для представлення двобайтових значень (слів) використовувався порядок little-endian, але 4-хбайтное подвійне слово записувалося від старшого слова до молодшого.

У процесорах VAX і ARM використовується змішане уявлення для довгих дійсних чисел.


1.5. Приклад

Далі наведено приклад, в якому описується розміщення 4-байтового числа в ОЗУ ЕОМ, доступ до якого може вироблятися як до 32-розрядному слову, так і побайтно.

Всі числа записані у 16-річної системі числення.

Число: 0xA1B2C3D4
Подання D4 * 0x01 + C3 * 0x100 + B2 * 0x10000 + A1 * 0x1000000
Порядок від молодшого до старшого (Little-endian) 0xD4, 0xC3, 0xB2, 0xA1
Порядок від старшого до молодшого (Big-endian) 0xA1, 0xB2, 0xC3, 0xD4
Порядок, прийнятий в PDP-11 (PDP-endian) 0xB2, 0xA1, 0xD4, 0xC3

1.6. Порівняння

Розміщення байтів слова в пам'яті Big-endian і Little-endian ЕОМ

Істотним достоїнством little-endian в порівнянні з big-endian порядком запису вважається можливість "неявній типізації" цілих чисел при читанні меншого обсягу байт (за умови, що читаемое число поміщається в діапазон). Так, якщо в комірці пам'яті міститься число 0x00000022, то прочитавши його як int16 (два байти) ми отримаємо число 0x0022, прочитавши один байт - число 0x22. Однак, це ж може вважатися і недоліком, тому що провокує помилки втрати даних.

Назад, вважається що у little-endian, в порівнянні з big-endian є "неочевидність" значення байтів пам'яті при налагодженні (послідовність байтів (A1, B2, C3, D4) насправді означає 0xD4C3B2A1, для big-endian ця послідовність (A1, B2, C3, D4) читалася б "природним" для арабської запису чисел чином: 0xA1B2C3D4). Найменш зручним в роботі вважається middle-endian формат запису; він зберігся тільки на старих платформах.

Для запису довгих чисел (чисел, довжина яких істотно перевищує розрядність машини) зазвичай переважніше порядок слів в числі little-endian (оскільки арифметичні операції над довгими числами виробляються від молодших розрядів до старших). Порядок байтів в слові - звичайний для даної архітектури.


2. Проблеми сумісності

Запис багатобайтові числа з пам'яті комп'ютера в файл або передача по мережі вимагає дотримання угод про те, який з байтів є старшим, а який молодшим. Прямий запис комірок пам'яті призводить до можливих проблем при перенесенні додатки з платформи на платформу.

3. Визначення порядку байтів

Порядок байтів в конкретній машині можна визначити за допомогою програми на мові Сі (testendian.c):

 # Include   unsigned  short  x  =  1  ;  / * 0x0001 * /  int  main  (  void  )  {  printf  (  "% S  \ N  "  ,  *  (  (  unsigned  char  *  )  &  x  )  ==  0  ?  "Big-endian"  :  "Little-endian"  )  ;  return  0  ;  } 
Висновок даної програми осмислений тільки на платформах, де розмір типу unsigned short більше, ніж розмір типу unsigned char. Це свідомо вірно на переважній більшості комп'ютерів, так як вони мають 8-розрядний байт. Однак існують і апаратні платформи, в яких розмір байта дорівнює розміру слова (або, в термінах мови C: sizeof (char) == sizeof (int)). Наприклад, в суперкомп'ютерах Cray.

Результати запуску на big-endian машині ( SPARC):

 $ Uname-m sparc64 $ gcc-o testendian testendian.c $. / Testendian big-endian 

Результати запуску на little-endian машині ( x86):

 $ Uname-m i386 $ gcc-o testendian testendian.c $. / Testendian little-endian 

4. Речові числа

Зберігання дійсних чисел може залежати від порядку байтів; так, на x86 використовуються формати IEEE 754 зі знаком і порядком числа в старших байтах.

5. Юнікод

Якщо Юнікод записаний у вигляді UTF-16 або UTF-32, то порядок байтів є істотним. Одним із способів позначення порядку байтів в юнікодових текстах є постановка на початку спеціального символу BOM ( byte order mark, U + FEFF) - "перевернутий" варіант цього символу (U + FFFE) не існує і не допускається в текстах.

6. Конвертація

Для перетворення між мережевим порядком байтів ( англ. network byte order ), Який завжди big-endian, і порядком байтів, що використовується на машині ( англ. host byte order ), Стандарт POSIX передбачає функції htonl(), htons(), ntohl(), ntohs() :

  • uint32_t htonl(uint32_t hostlong); - конвертує 32-бітну беззнакову величину з локального порядку байтів в мережевій;
  • uint16_t htons(uint16_t hostshort); - конвертує 16-бітну беззнакову величину з локального порядку байтів в мережевій;
  • uint32_t ntohl(uint32_t netlong); - конвертує 32-бітну беззнакову величину з мережевого порядку байтів в локальний;
  • uint16_t ntohs(uint16_t netshort); - конвертує 16-бітну беззнакову величину з мережевого порядку байтів в локальний.

У разі збігу поточного порядку байтів і мережевого, функції можуть бути "порожніми" (тобто, не міняти близько байтів). Стандарт також допускає, щоб ці функції були реалізовані макросами.

Існує багато мов і бібліотек із засобами конвертації в обидва основні порядку байт і назад.

Ядро Linux : le16_to_cpu (), cpu_to_be32 (), cpu_to_le16p (), і так далі;

Ядро FreeBSD : htobe16 (), le32toh (), і так далі;

Erlang :

 <<  Count  :  32  /  big  -  unsigned  -  integer  ,  Average  :  64  /  big  -  float  >>  =  Chunk  Message  =  <<  Length  :  32  /  little  -  unsigned  -  integer  ,  MType  :  16  /  little  -  unsigned  -  integer  ,  MessageBody  >> 

Python :

 import  struct  Count  ,  Average  =  struct  .  unpack  (  "> Ld"  ,  Chunk  )  Message  =  struct  .  pack  (  " ,  Length  ,  MType  )  + MessageBody 

Perl :

 (  $ Count  ,  $ Average  )  =  unpack  (  'L> d>'  ,  $ Chunk  )  ;  $ Message  =  pack  (  '(LS) <'  ,  $ Length  ,  $ MType  )  .  $ MessageBody  ;  (  або те ж саме  :  $ Message  =  pack  (  'Vv'  ,  $ Length  ,  $ MType  )  .  $ MessageBody  ;  ) 

дані приклади для Erlang, Python, Perl містять ідентичну функціональність.


7. Етимологія назви

Терміни big-endian і little-endian спочатку не мали відношення до інформатики. У сатиричному творі Джонатана Свіфта " Подорожі Гуллівера "описуються вигадані держави Лилипутия і Блефуску, протягом багатьох років ведуть між собою війни через розбіжності з приводу того, з якого кінця слід розбивати варені яйця. Тих, хто вважає, що їх потрібно розбивати з тупого кінця, у творі називають Big-endians ("тупоконечников"). Суперечки між прихильниками big-endian і little-endian в інформатиці також часто носять характер т. н. "Релігійних війн". [2]

Терміни big-endian і little-endian ввів Коен ( англ. Danny Cohen ) В 1980 році у своїй статті "On Holy Wars and a Plea for Peace". [3] [4]


Примітки

  1. pack () в Perl - perldoc.perl.org / functions / pack.html
  2. DAV's Endian FAQ - www.rdrop.com/ ~ cary / html / endian_faq.html (Недоступна посилання - історія - web.archive.org / web / * / http://www.rdrop.com/ ~ cary / html / endian_faq.html)
  3. Danny Cohen. On Holy Wars and a Plea for Peace - www.ietf.org/rfc/ien/ien137.txt (Англ.) (1 квітня 1980). Читальний - www.webcitation.org/65T8LbcEF з першоджерела 15 лютого 2012.
  4. Таненбаум Е. Архітектура комп'ютера. - 5-е изд. - СПб. : Питер, 2007. - 844 с. - С. 89.