В вычислительной технике порядок байтов — это порядок, в котором байты в слове цифровых данных передаются по среде передачи данных или адресуются (по возрастающим адресам) в памяти компьютера , при этом учитывается только значимость байта по сравнению с ранностью. Порядок байтов в первую очередь выражается как big-endian (BE) или little-endian (LE), термины, введенные Дэнни Коэном в информатику для упорядочивания данных в Internet Experiment Note, опубликованном в 1980 году. [1] Прилагательное endian берет свое начало в трудах англо-ирландского писателя 18 века Джонатана Свифта . В романе 1726 года « Путешествия Гулливера» он изображает конфликт между сектами лилипутов, разделенных на тех, кто разбивает скорлупу вареного яйца с большого конца или с маленького конца. [2] [3] По аналогии, процессор может считывать цифровое слово big end first или little end first.
Компьютеры хранят информацию в группах двоичных битов разного размера. Каждой группе присваивается номер, называемый адресом , который компьютер использует для доступа к этим данным. На большинстве современных компьютеров наименьшая группа данных с адресом имеет длину восемь бит и называется байтом. Более крупные группы состоят из двух или более байтов, например, 32-битное слово содержит четыре байта. Существует два возможных способа, которыми компьютер может пронумеровать отдельные байты в большей группе, начиная с любого конца. Оба типа порядка байтов широко используются в цифровой электронной инженерии. Первоначальный выбор порядка байтов новой конструкции часто произволен, но более поздние технологические пересмотры и обновления увековечивают существующий порядок байтов для поддержания обратной совместимости .
Система big-endian хранит самый старший байт слова по самому маленькому адресу памяти , а самый младший байт — по самому большому. Система little-endian, напротив, хранит самый младший байт по самому маленькому адресу. [4] [5] [6] Из этих двух big-endian, таким образом, ближе к тому, как цифры чисел пишутся слева направо в английском языке, сравнивая цифры с байтами. Bi-endianness — это функция, поддерживаемая многочисленными компьютерными архитектурами, которые имеют переключаемый порядок байтов при выборке и хранении данных или для выборки инструкций. Другие порядки обычно называются middle-endian или mixed-endian . [7] [8] [9] [10]
Big-endianness — доминирующий порядок в сетевых протоколах, например, в наборе протоколов Интернета , где он называется сетевым порядком , передающим сначала самый значимый байт. Наоборот, little-endianness — доминирующий порядок для архитектур процессоров ( x86 , большинство реализаций ARM , базовые реализации RISC-V ) и их связанной памяти. Форматы файлов могут использовать любой из этих порядков; некоторые форматы используют смесь обоих или содержат индикатор того, какой порядок используется во всем файле. [11]
Память компьютера состоит из последовательности ячеек памяти (наименьших адресуемых единиц); в машинах, поддерживающих байтовую адресацию , эти единицы называются байтами . Каждый байт идентифицируется и доступен в аппаратном и программном обеспечении по его адресу памяти . Если общее количество байтов в памяти равно n , то адреса нумеруются от 0 до n − 1.
Компьютерные программы часто используют структуры данных или поля , которые могут состоять из большего количества данных, чем может быть сохранено в одном байте. В контексте этой статьи, где его тип не может быть произвольно сложным, «поле» состоит из последовательной последовательности байтов и представляет собой «простое значение данных», которым — по крайней мере потенциально — можно манипулировать одной единственной аппаратной инструкцией . В большинстве систем адрес многобайтового простого значения данных — это адрес его первого байта (байт с самым низким адресом). Из этого правила есть исключения — например, инструкция Add IBM 1401 адресует поля переменной длины в их младшей (самой высокой) позиции, а их длины определяются словесным обозначением , установленным в их старшей (самой низкой) позиции. Когда выполняется такая операция, как сложение, процессор начинает с младших позиций в старших адресах двух полей и работает до старшего порядка. [ необходима цитата ]
Другим важным атрибутом байта, являющегося частью «поля», является его «значимость». Эти атрибуты частей поля играют важную роль в последовательности, в которой к байтам обращается компьютерное оборудование, точнее: низкоуровневые алгоритмы, вносящие вклад в результаты компьютерной инструкции.
Позиционные системы счисления (в основном с основанием 2 или реже с основанием 10) являются преобладающим способом представления и, в частности, манипулирования целыми данными с помощью компьютеров. В чистом виде это справедливо для неотрицательных целых чисел среднего размера, например, типа данных C. unsigned
В такой системе счисления значение цифры, которое она вносит в целое число, определяется не только ее значением как отдельной цифры, но и позицией, которую она занимает в полном числе, называемой ее значимостью. Эти позиции могут быть отображены в памяти в основном двумя способами: [12]
В этих выражениях термин «конец» подразумевает ту крайность, где большая или маленькая буква пишется первой , а именно там, где начинается поле .
Целочисленные данные, которые напрямую поддерживаются компьютерным оборудованием, имеют фиксированную ширину малой степени 2, например, 8 бит ≙ 1 байт, 16 бит ≙ 2 байта, 32 бита ≙ 4 байта, 64 бита ≙ 8 байтов, 128 бит ≙ 16 байтов. Низкоуровневая последовательность доступа к байтам такого поля зависит от выполняемой операции. Младший байт первым доступен для сложения , вычитания и умножения . Старший байт первым доступен для деления и сравнения . См. § Порядок вычислений.
Когда строки символов (текста) должны сравниваться друг с другом, например, для поддержки некоторого механизма, такого как сортировка , это очень часто делается лексикографически, где один позиционный элемент (символ) также имеет позиционное значение. Лексикографическое сравнение означает почти везде: первый символ имеет наивысший ранг – как в телефонной книге. Почти все машины, которые могут делать это с помощью одной инструкции, имеют big-endian или, по крайней мере, mixed-endian. [ необходима цитата ]
Целые числа, записанные в виде текста, всегда представляются в памяти старшей значащей цифрой вперед, что аналогично порядку байтов от старшего к младшему, независимо от направления текста .
Когда байты памяти печатаются последовательно слева направо (например, в шестнадцатеричном дампе ), little-endian представление целых чисел имеет значимость, увеличивающуюся слева направо. Другими словами, оно отображается в обратном порядке при визуализации, что может быть нелогичным.
Такое поведение возникает, например, в FourCC или подобных методах, которые включают упаковку символов в целое число, так что оно становится последовательностью определенных символов в памяти. Например, возьмем строку "JOHN", сохраненную в шестнадцатеричном ASCII . На машинах с обратным порядком байтов значение отображается слева направо, совпадая с правильным порядком строк для чтения результата ("JOH N"). Но на машине с прямым порядком байтов можно увидеть "NHO J". Машины со средним порядком байтов еще больше усложняют ситуацию; например, на PDP-11 32-битное значение хранится как два 16-битных слова "JO" "HN" в обратном порядке байтов, причем символы в 16-битных словах хранятся в прямом порядке байтов, что дает "OJN H". [ необходима цитата ]
Обмен байтами заключается в перестановке байтов для изменения порядка байтов. Многие компиляторы предоставляют встроенные функции , которые, скорее всего, будут скомпилированы в собственные инструкции процессора ( bswap
/ movbe
), например __builtin_bswap32
. Программные интерфейсы для обмена включают:
winsock2.h
.endian.h
(из/в BE и LE, до 64-бит). [14]OSByteOrder.h
(из/в BE и LE, до 64-бит).std::byteswap
в C++23 . [15]Некоторые наборы инструкций ЦП обеспечивают встроенную поддержку перестановки байтов в порядке байтов, например bswap
[16] ( x86 — 486 и более поздние версии, i960 — i960Jx и более поздние версии [17] ) и rev
[18] ( ARMv6 и более поздние версии).
Некоторые компиляторы имеют встроенные возможности для обмена байтами. Например, компилятор Intel Fortran поддерживает нестандартный CONVERT
спецификатор при открытии файла, например: . Другие компиляторы имеют опции для генерации кода, который глобально включает преобразование для всех операций ввода-вывода файла. Это позволяет повторно использовать код в системе с противоположным порядком байтов без изменения кода.OPEN(unit, CONVERT='BIG_ENDIAN',...)
В большинстве систем адрес многобайтового значения является адресом его первого байта (байта с наименьшим адресом); системы с прямым порядком байтов такого типа обладают свойством, что для достаточно низких значений данных одно и то же значение может быть прочитано из памяти с разной длиной без использования разных адресов (даже при наложении ограничений на выравнивание ). Например, 32-битная ячейка памяти с содержимым 4A 00 00 00
может быть прочитана по тому же адресу, что и 8-битная (значение = 4A), 16-битная (004A), 24-битная (00004A) или 32-битная (0000004A), все из которых сохраняют одно и то же числовое значение. Хотя это свойство прямого порядка байтов редко используется напрямую высокоуровневыми программистами, оно иногда применяется оптимизаторами кода, а также программистами на языке ассемблера . Хотя это не разрешено C++, такой код каламбуров типа разрешен как «определяемый реализацией» стандартом C11 [19] и широко используется [20] в коде, взаимодействующем с оборудованием. [21]
Некоторые операции в позиционных системах счисления имеют естественный или предпочтительный порядок, в котором должны выполняться элементарные шаги. Этот порядок может повлиять на их производительность на процессорах с байтовой адресацией малого масштаба и микроконтроллерах . Однако высокопроизводительные процессоры обычно извлекают многобайтовые операнды из памяти за то же время, за которое они извлекли бы один байт, поэтому сложность оборудования не зависит от порядка байтов.
Сложение, вычитание и умножение начинаются с позиции младшей значащей цифры и распространяют перенос на следующую более значимую позицию. В большинстве систем адрес многобайтового значения — это адрес его первого байта (байт с самым низким адресом). Реализация этих операций немного проще с использованием машин с прямым порядком байтов, где этот первый байт содержит младшую значащую цифру.
Сравнение и деление начинаются с самой значимой цифры и распространяют возможный перенос на последующие менее значимые цифры. Для числовых значений фиксированной длины (обычно длиной 1,2,4,8,16) реализация этих операций немного проще на машинах с обратным порядком байтов.
Некоторые процессоры с обратным порядком байтов (например, IBM System/360 и его последователи) содержат аппаратные инструкции для лексикографического сравнения строк символов различной длины .
Обычная передача данных с помощью оператора присваивания в принципе не зависит от порядка байтов процессора.
Многие исторические и существующие процессоры используют представление памяти big-endian, либо исключительно, либо как вариант дизайна. IBM System/360 использует big-endian порядок байтов, как и его преемники System/370 , ESA/390 и z/Architecture . PDP-10 использует big-endian адресацию для байт-ориентированных инструкций. Миникомпьютер IBM Series/1 использует big-endian порядок байтов. Процессоры Motorola 6800 / 6801, 6809 и 68000 серий используют big-endian формат. Архитектуры исключительно big-endian включают IBM z/Architecture и OpenRISC .
Datapoint 2200 использовал простую последовательную битовую логику с прямым порядком байтов для облегчения распространения переноса . Когда Intel разработала микропроцессор 8008 для Datapoint, они использовали прямой порядок байтов для совместимости. Однако, поскольку Intel не смогла вовремя выпустить 8008, Datapoint использовала эквивалент средней интеграции , но прямой порядок байтов был сохранен в большинстве проектов Intel, включая MCS-48 и 8086 и его преемников x86 . [22] [23] DEC Alpha , Atmel AVR , VAX , семейство MOS Technology 6502 (включая Western Design Center 65802 и 65C816 ), Zilog Z80 (включая Z180 и eZ80 ), Altera Nios II и многие другие процессоры и семейства процессоров также имеют прямой порядок байтов.
Intel 8051 , в отличие от других процессоров Intel, ожидает 16-битные адреса для LJMP и LCALL в формате big-endian; однако инструкции xCALL сохраняют адрес возврата в стеке в формате little-endian. [24]
Архитектуры наборов инструкций IA -32 и x86-64 используют формат little-endian. Другие архитектуры наборов инструкций, которые следуют этому соглашению, допуская только режим little-endian, включают Nios II , Andes Technology NDS32 и Qualcomm Hexagon .
Некоторые архитектуры наборов инструкций являются «bi-endian» и позволяют запускать программное обеспечение с любым порядком байтов; к ним относятся Power ISA , SPARC , ARM AArch64 , C-Sky и RISC-V . IBM AIX и IBM i работают в режиме big-endian на bi-endian Power ISA; Linux изначально работал в режиме big-endian, но к 2019 году IBM перешла на режим little-endian для Linux, чтобы облегчить портирование программного обеспечения Linux с x86 на Power. [25] [26] SPARC не имеет соответствующего развертывания little-endian, поскольку и Oracle Solaris, и Linux работают в режиме big-endian на bi-endian системах SPARC и могут считаться big-endian на практике. ARM, C-Sky и RISC-V не имеют соответствующих развертываний big-endian и могут считаться little-endian на практике.
Некоторые архитектуры (включая ARM версии 3 и выше, PowerPC , Alpha , SPARC V9, MIPS , Intel i860 , PA-RISC , SuperH SH-4 и IA-64 ) имеют настройку, которая позволяет переключать порядок байтов при выборке и хранении данных, выборке инструкций или и том, и другом. Эта функция может повысить производительность или упростить логику сетевых устройств и программного обеспечения. Слово bi-endian , когда оно употребляется по отношению к оборудованию, обозначает способность машины вычислять или передавать данные в любом формате порядка байтов.
Многие из этих архитектур можно переключить с помощью программного обеспечения на определенный формат порядка байтов по умолчанию (обычно это делается при запуске компьютера); однако в некоторых системах порядок байтов по умолчанию выбирается аппаратно на материнской плате и не может быть изменен с помощью программного обеспечения (например, Alpha, которая работает только в режиме big-endian на Cray T3E ).
Термин bi-endian относится в первую очередь к тому, как процессор обрабатывает доступ к данным. Доступ к инструкциям (выборка командных слов) на данном процессоре может по-прежнему предполагать фиксированный порядок байтов, даже если доступ к данным полностью bi-endian, хотя это не всегда так, например, на процессоре Itanium на базе IA-64 от Intel, который допускает оба варианта.
Некоторые номинально bi-endian CPU требуют помощи материнской платы для полного переключения порядка байтов. Например, 32-битные процессоры PowerPC , ориентированные на настольные компьютеры, в режиме little-endian действуют как little-endian с точки зрения выполняемых программ, но они требуют, чтобы материнская плата выполняла 64-битную подкачку по всем 8 байтовым полосам, чтобы гарантировать, что little-endian представление вещей будет применяться к устройствам ввода-вывода . При отсутствии этого необычного оборудования материнской платы программное обеспечение драйвера устройства должно записывать данные по разным адресам, чтобы отменить неполное преобразование, а также должно выполнять обычную подкачку байтов. [ оригинальное исследование? ]
Некоторые процессоры, такие как многие процессоры PowerPC, предназначенные для встраиваемого использования, и почти все процессоры SPARC, позволяют выбирать порядок байтов на каждой странице.
Процессоры SPARC с конца 1990-х годов (процессоры, совместимые со SPARC v9) позволяют выбирать порядок байтов данных для каждой отдельной инструкции, которая загружает данные из памяти или сохраняет их в памяти.
Архитектура ARM поддерживает два режима big-endian, называемые BE-8 и BE-32 . [27] Процессоры до ARMv5 поддерживают только BE-32 или режим инвариантности слов. Здесь любой естественно выровненный 32-битный доступ работает как в режиме little-endian, но доступ к байту или 16-битному слову перенаправляется на соответствующий адрес, и невыровненный доступ не допускается. ARMv6 представляет BE-8 или режим инвариантности байтов, где доступ к одному байту работает как в режиме little-endian, но доступ к 16-битному, 32-битному или (начиная с ARMv8) 64-битному слову приводит к перестановке байтов данных. Это упрощает невыровненный доступ к памяти, а также отображаемый в память доступ к регистрам, отличным от 32-битных.
Многие процессоры имеют инструкции для преобразования слова в регистре в противоположный порядок байтов, то есть они меняют порядок байтов в 16-, 32- или 64-битном слове.
В последних процессорах архитектуры Intel x86 и x86-64 есть инструкция MOVBE ( Intel Core с 4-го поколения, после Atom ), [28] которая извлекает слово в формате big-endian из памяти или записывает слово в память в формате big-endian. В остальном эти процессоры полностью little-endian.
Существуют также устройства, которые используют разные форматы в разных местах. Например, индикатор батареи BQ27421 Texas Instruments использует формат little-endian для своих регистров и формат big-endian для своей памяти с произвольным доступом .
SPARC исторически использовал big-endian до версии 9, которая является bi-endian. Аналогично, ранние процессоры IBM POWER были big-endian, но потомки PowerPC и Power ISA теперь bi-endian. Архитектура ARM была little-endian до версии 3, когда она стала bi-endian.
Хотя многие процессоры используют хранение с прямым порядком байтов для всех типов данных (целые числа, числа с плавающей точкой), существует ряд аппаратных архитектур, в которых числа с плавающей точкой представлены в форме с прямым порядком байтов, а целые числа — в форме с прямым порядком байтов. [29] Существуют процессоры ARM , которые имеют смешанное представление с плавающей точкой для чисел двойной точности: каждое из двух 32-битных слов хранится как с прямым порядком байтов, но самое значимое слово хранится первым. VAX с плавающей точкой хранит 16-битные слова с прямым порядком байтов в порядке с прямым порядком байтов. Поскольку существует множество форматов с плавающей точкой без сетевого стандартного представления для них, стандарт XDR использует в качестве своего представления IEEE 754 с прямым порядком байтов. Поэтому может показаться странным, что широко распространенный стандарт IEEE 754 с плавающей точкой не определяет порядок байтов. [30] Теоретически это означает, что даже стандартные данные IEEE с плавающей точкой, записанные одной машиной, могут быть нечитаемы другой. Однако на современных стандартных компьютерах (т. е. реализующих IEEE 754) можно смело предположить, что порядок байтов для чисел с плавающей точкой и целых чисел одинаковы, что делает преобразование простым независимо от типа данных. Однако небольшие встроенные системы, использующие специальные форматы с плавающей точкой, могут быть другим вопросом.
Большинство рассмотренных до сих пор инструкций содержат размер (длину) своих операндов в коде операции . Часто доступные длины операндов составляют 1, 2, 4, 8 или 16 байт. Но существуют также архитектуры, в которых длина операнда может храниться в отдельном поле инструкции или вместе с самим операндом, например, с помощью словесного знака . Такой подход допускает длину операнда до 256 байт или больше. Типами данных таких операндов являются символьные строки или BCD . Машины, способные манипулировать такими данными с помощью одной инструкции (например, сравнить, сложить), включают IBM 1401 , 1410 , 1620 , System/360 , System/370 , ESA/390 и z/Architecture , все они имеют тип big-endian.
Возможны и другие многочисленные порядки, которые обычно называются средним порядком байтов или смешанным порядком байтов .
PDP -11 в принципе является 16-битной системой little-endian. Инструкции для преобразования между плавающей точкой и целыми числами в дополнительном процессоре с плавающей точкой PDP-11/45, PDP-11/70 и в некоторых более поздних процессорах хранили 32-битные значения "double precision integer long" с 16-битными половинами, переставленными из ожидаемого little-endian порядка. Компилятор UNIX C использовал тот же формат для 32-битных длинных целых чисел. Этот порядок известен как PDP-endian . [31]
UNIX была одной из первых систем, которая позволяла компилировать один и тот же код для платформ с разными внутренними представлениями. Одна из первых преобразованных программ должна была печатать Unix
, но на Series/1 она nUxi
вместо этого печатала. [32]
Один из способов интерпретации этого порядка байтов заключается в том, что он хранит 32-битное целое число как два 16-битных слова с прямым порядком байтов, с обратным порядком слов:
Дескрипторы сегментов процессоров IA-32 и совместимых с ними процессоров содержат 32-битный базовый адрес сегмента, хранящийся в порядке от младшего к старшему, но в четырех непоследовательных байтах, в относительных позициях 2, 3, 4 и 7 начала дескриптора. [33]
Языки описания оборудования (HDL), используемые для выражения цифровой логики, часто поддерживают произвольный порядок байтов с произвольной степенью детализации. Например, в SystemVerilog слово может быть определено как little-endian или big-endian. [ необходима цитата ]
Распознавание порядка байтов важно при чтении файла или файловой системы, созданных на компьютере с другим порядком байтов.
Последовательные неформатированные файлы Fortran, созданные с одним порядком байтов, обычно не могут быть прочитаны в системе, использующей другой порядок байтов, поскольку Fortran обычно реализует запись (определяемую как данные, записанные одним оператором Fortran) как данные, которым предшествуют и следуют поля счетчика, которые являются целыми числами, равными количеству байтов в данных. Попытка прочитать такой файл с помощью Fortran в системе с другим порядком байтов приводит к ошибке времени выполнения, поскольку поля счетчика неверны.
Текст Unicode может опционально начинаться с метки порядка байтов (BOM), чтобы обозначить порядок байтов файла или потока. Его кодовая точка — U+FEFF. Например, в UTF-3200 00 FE FF
файл с прямым порядком байтов должен начинаться с ; файл с прямым порядком байтов должен начинаться с FF FE 00 00
.
Форматы двоичных данных приложений, такие как файлы MATLAB .mat или формат данных .bil , используемые в топографии, обычно не зависят от порядка байтов. Это достигается путем хранения данных всегда в одном фиксированном порядке байтов или переноса с данными переключателя для указания порядка байтов. Примером первого является двоичный формат файла XLS , который является переносимым между системами Windows и Mac и всегда имеет прямой порядок байтов, требуя от приложения Mac менять байты при загрузке и сохранять при запуске на процессоре Motorola 68K или PowerPC с обратным порядком байтов. [34]
Файлы изображений TIFF являются примером второй стратегии, заголовок которой сообщает приложению о порядке байтов их внутренних двоичных целых чисел. Если файл начинается с подписи, MM
это означает, что целые числа представлены как big-endian, в то время как II
означает little-endian. Эти подписи требуют одного 16-битного слова каждая, и они являются палиндромами , поэтому они независимы от порядка байтов. I
обозначает Intel и M
обозначает Motorola . Процессоры Intel имеют прямой порядок байтов, в то время как процессоры Motorola 680x0 имеют прямой порядок байтов. Эта явная подпись позволяет программе чтения TIFF менять байты, если это необходимо, когда данный файл был сгенерирован программой записи TIFF, запущенной на компьютере с другим порядком байтов.
В результате своей первоначальной реализации на платформе Intel 8080 файловая система таблицы размещения файлов (FAT), не зависящая от операционной системы, определена с прямым порядком байтов даже на платформах, изначально использующих другой порядок байтов, что требует операций по перестановке байтов для поддержания FAT на этих платформах.
ZFS , объединяющая файловую систему и менеджер логических томов , известна тем, что обеспечивает адаптивный порядок байтов и работает как с системами с прямым, так и с обратным порядком байтов. [35]
Многие IETF RFC используют термин сетевой порядок , означающий порядок передачи байтов по проводам в сетевых протоколах . Среди прочего, исторический RFC 1700 определяет сетевой порядок для протоколов в наборе протоколов Интернета как big-endian. [36]
Однако не все протоколы используют порядок байтов big-endian в качестве сетевого порядка. Протокол Server Message Block (SMB) использует порядок байтов little-endian. В CANopen многобайтовые параметры всегда отправляются наименее значимым байтом первым (little-endian). То же самое справедливо и для Ethernet Powerlink . [37]
API сокетов Беркли определяет набор функций для преобразования 16- и 32-битных целых чисел в сетевой порядок байтов и обратно: функции (host-to-network-short) и (host-to-network-long) преобразуют 16- и 32 -битные значения соответственно из машинного ( host ) в сетевой порядок байтов; функции и преобразуют из сетевого порядка байтов в хостовый. [38] [39] Эти функции могут быть пустыми операциями в системе с обратным порядком байтов.htons
htonl
ntohs
ntohl
В то время как высокоуровневые сетевые протоколы обычно рассматривают байт (чаще всего подразумеваемый как октет ) в качестве своей атомарной единицы, самые низкие уровни сетевого стека могут иметь дело с порядком битов внутри байта.