Warning: session_name(): Cannot change session name when session is active in /home/stalko/rodina-ru.com/docs/dokuwiki/inc/init.php on line 231

Warning: session_set_cookie_params(): Cannot change session cookie parameters when session is active in /home/stalko/rodina-ru.com/docs/dokuwiki/inc/init.php on line 232
======Порядок байтов====== В современной вычислительной технике и цифровых системах связи информация обычно представлена в виде последовательности [[байт|байтов]]. В том случае, если число не может быть представлено одним байтом, имеет значение в каком порядке байты записываются в памяти компьютера или передаются по линиям связи. Часто выбор порядка записи байтов произволен и определяется только соглашениями. В общем случае, для представления числа //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//. =====Варианты записи===== ====Порядок от старшего к младшему==== Порядок //от старшего к младшему// или ([[английский-язык|англ.]] //big-endian//, дословно: «тупоконечный»): A_{n},\dots ,A_{0}, запись начинается со старшего и заканчивается младшим. Этот порядок является стандартным для протоколов [[tcp/ip|TCP/IP]], он используется в заголовках пакетов данных и во многих протоколах более высокого уровня, разработанных для использования поверх TCP/IP. Поэтому, порядок байтов от старшего к младшему часто называют сетевым порядком байтов ([[английский-язык|англ.]] //network byte order//). Этот порядок байтов используется процессорами [[ibm-360|IBM 360]]/370/390, [[m68k|Motorola 68000]], [[sparc|SPARC]] (отсюда третье название — //порядок байтов Motorola//, //Motorola byte order//). В этом же виде (используя представление в [[десятичная-система-счисления|десятичной системе счисления]]) записываются числа [[арабские-цифры|индийско-арабскими цифрами]] в письменностях с порядком знаков слева направо (латиница, кириллица). Для письменностей с обратным порядком (арабская) та же запись числа воспринимается как «от младшего к старшему». Порядок байтов от старшего к младшему применяется во многих [[формат-файла|форматах файлов]] — например, [[png|PNG]], [[flv|FLV]], [[ebml|EBML]]. ====Порядок от младшего к старшему==== Порядок //от младшего к старшему// или ([[английский-язык|англ.]] //little-endian//, дословно: «остроконечный», о происхождении термина [[#.D0.AD.D1.82.D0.B8.D0.BC.D0.BE.D0.BB.D0.BE.D0.B3.D0.B8.D1.8F_.D0.BD.D0.B0.D0.B7.D0.B2.D0.B0.D0.BD.D0.B8.D1.8F|ниже]]): A_{0},\dots ,A_{n}, запись начинается с младшего и заканчивается старшим. Этот порядок записи принят в памяти персональных компьютеров с [[x86]]-процессорами, в связи с чем иногда его называют //[[интел|интеловский]] порядок байт// (по названию фирмы-создателя [[компьютерная-архитектура|архитектуры]] x86). Процессоры x86 позволяют работать с одно-, двух-, четырёх-, восьмибайтными операндами. При изменении размера операнда в памяти адрес не изменяется при таком порядке байт. В некоторых кругах используется название [[английский-язык|англ.]] //VAX order//, например, в документации Perl(([[http://perldoc.perl.org/functions/pack.html|pack() в Perl]])). В противоположность порядку «от старшего к младшему» (англ. //big-endian//, «тупоконечный»), соглашение //little-endian// поддерживают меньше кросс-платформенных протоколов и форматов данных; существенные исключения: [[usb|USB]], конфигурация [[pci|PCI]], [[таблица-разделов-guid|таблица разделов GUID]], рекомендации [[fidonet|FidoNet]]. ====Переключаемый порядок==== Многие процессоры могут работать и в порядке от младшего к старшему, и в обратном, например, [[arm-архитектура-|ARM]], [[powerpc|PowerPC]] (но не [[powerpc-970|PowerPC 970]]), [[dec-alpha|DEC Alpha]], [[mips-архитектура-|MIPS]], [[pa-risc|PA-RISC]] и [[ia-64|IA-64]]. Обычно порядок байтов выбирается программно во время инициализации [[операционная-система|операционной системы]], но может быть выбран и аппаратно перемычками на материнской плате. В этом случае правильнее говорить о порядке байтов операционной системы. Переключаемый порядок байтов иногда называют [[английский-язык|англ.]] //bi-endian//. ====Смешанный порядок==== Смешанный порядок байтов ([[английский-язык|англ.]] //middle-endian)// иногда используется при работе с числами, [[длинная-арифметика|длина которых превышает машинное слово]]. Число представляется последовательностью [[машинное-слово|машинных слов]], которые записываются в формате, естественном для данной архитектуры, но сами слова следуют в обратном порядке. В процессорах [[vax|VAX]] и [[arm-архитектура-|ARM]] используется смешанное представление для длинных вещественных чисел. ====Пример==== Далее приведён пример, в котором описывается размещение 4-байтового числа в ОЗУ ЭВМ, доступ к которому может производиться и как к 32-разрядному слову, и побайтно. Все числа записаны в 16-ричной системе счисления. {| |+ Число: 0xA1B2C3D4 | colspan="2"| Представление | 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 |} ====Сравнение==== [{{wiki:300px-endianmem.png|Размещение байтов слова в памяти 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 (поскольку арифметические операции над длинными числами производятся от младших разрядов к старшим). Порядок //байтов в слове// — обычный для данной архитектуры. =====Определение порядка байтов===== Порядок байтов в конкретной машине можно определить с помощью программы на языке [[си-язык-программирования-|Си]] (testbyteorder.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**(short)''). Например, в суперкомпьютерах [[cray|Cray]].// Результаты запуска на big-endian машине ([[sparc|SPARC]]): $ uname -m sparc64 $ gcc -o testbyteorder testbyteorder.c $ ./testbyteorder big-endian Результаты запуска на little-endian машине ([[x86]]): $ uname -m i386 $ gcc -o testbyteorder testbyteorder.c $ ./testbyteorder little-endian =====Вещественные числа===== Хранение [[вещественное-число|вещественных чисел]] может зависеть от порядка байт; так, на [[x86]] используются форматы [[ieee-754-2008|IEEE 754]] со знаком и порядком числа в старших байтах. =====Юникод===== Если [[юникод|Юникод]] записан в виде [[utf-16|UTF-16]] или [[utf-32|UTF-32]], то порядок байтов является существенным. Одним из способов обозначения порядка байтов в юникодовых текстах является постановка в начале специального символа BOM (byte order mark, [[маркер-последовательности-байтов|маркер последовательности байтов]], U+FEFF) — «перевёрнутый» вариант этого символа (U+FFFE) не существует и не допускается в текстах. Символ U+FEFF изображается в UTF-16 последовательностью байтов 0xFE 0xFF (big-endian) или 0xFF 0xFE (little-endian), а в UTF-32 — последовательностью 0x00 0x00 0xFE 0xFF (big-endian) или 0xFF 0xFE 0x00 0x00 (little-endian). =====Проблемы совместимости и конвертация===== Запись многобайтового числа из памяти компьютера в файл или передача по сети требует соблюдения соглашений о том, какой из байтов передается первым. Прямая запись в том порядке, в котором байты расположены в ячейках памяти приводит к проблемам при переносе приложения с платформы на платформу. Для преобразования между сетевым порядком байтов ([[английский-язык|англ.]] //network byte order//), который всегда big-endian, и порядком байтов, использующимся на машине ([[английский-язык|англ.]] //host byte order//), стандарт [[posix|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|Linux]]: le16_to_cpu(), cpu_to_be32(), cpu_to_le16p(), и так далее; Ядро [[freebsd|FreeBSD]]: htobe16(), le32toh(), и так далее; [[erlang|Erlang]]: <> = Chunk Message = <> [[python|Python]]: import struct Count, Average = struct.unpack(">Ld", Chunk) Message = struct.pack("[[perl|Perl]]: ($Count, $Average) = unpack('L>d>', $Chunk); $Message = pack('(LS)<', $Length, $MType) . $MessageBody; (или то же самое: $Message = pack('Vv', $Length, $MType) . $MessageBody;) данные примеры для Erlang, Python, Perl содержат идентичную функциональность. Процессоры Intel x86-64 имеют инструкцию BSWAP для смены порядка байт. =====Этимология названия===== Термины big-endian и little-endian первоначально не имели отношения к информатике. В сатирическом произведении [[свифт-джонатан|Джонатана Свифта]] «[[путешествия-гулливера|Путешествия Гулливера]]» описываются вымышленные государства Лилипутия и Блефуску, в течение многих лет ведущие между собой войны из-за разногласия по поводу того, с какого конца следует разбивать варёные яйца. Тех, кто считает, что их нужно разбивать с тупого конца, в произведении называют Big-endians («тупоконечники»). Споры между сторонниками big-endian и little-endian в информатике также часто носят характер т. н. «религиозных войн».(([[http://www.rdrop.com/~cary/html/endian_faq.html|DAV’s Endian FAQ]](недоступная ссылка — [[https://web.archive.org/web/*/http://www.rdrop.com/~cary/html/endian_faq.html|история]], [[https://web.archive.org/web/20060314113340/http://www.rdrop.com/~cary/html/endian_faq.html|копия]]))) Термины big-endian и little-endian ввёл [[коэн-денни|Коэн]] ([[английский-язык|англ.]] //[[danny-cohen-engineer-|Danny Cohen]]//) в 1980 году в своей статье «On Holy Wars and a Plea for Peace».((//Danny Cohen.// [[http://www.ietf.org/rfc/ien/ien137.txt|On Holy Wars and a Plea for Peace]] (англ.) (1 апреля 1980). Проверено 24 января 2010. [[http://www.webcitation.org/65T8LbcEF|Архивировано из первоисточника 15 февраля 2012]].))((//Таненбаум Э.// Архитектура компьютера. — 5-е изд. — СПб.: Питер, 2007. — 844 с. — С. 89.)) =====См. также===== * [[компьютерная-сеть|Компьютерная сеть]] =====Ссылки===== * [[http://www.intuit.ru/studies/courses/2249/52/lecture/1567?page=5|Сетевой порядок байтов, функции htons(), htonl(), ntohs(), ntohl()]] * [[http://computing-dictionary.thefreedictionary.com/byte%20order|Порядок байтов]] * [[https://underground.nipl.net/docs/endianness.txt|Порядок байтов]] {{tag>Компьютер}}