Старший и младший байты

Старший и младший байты

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

В общем случае, для представления числа M, большего 255 (здесь 255 = 2 8 − 1 <displaystyle 255=2^<8>-1> — максимальное целое число, записываемое одним байтом), приходится использовать несколько байтов. При этом число M записывается в позиционной системе счисления по основанию 256:

M = ∑ i = 0 n A i ⋅ 256 i = A 0 ⋅ 256 0 + A 1 ⋅ 256 1 + A 2 ⋅ 256 2 + ⋯ + A n ⋅ 256 n . <displaystyle M=sum _^A_cdot 256^=A_<0>cdot 256^<0>+A_<1>cdot 256^<1>+A_<2>cdot 256^<2>+dots +A_cdot 256^.>

Набор целых чисел A 0 , … , A n <displaystyle A_<0>,dots ,A_> , каждое из которых лежит в интервале от 0 до 255, является последовательностью байтов, составляющих M. При этом A 0 <displaystyle A_<0>> называется младшим байтом, а A n <displaystyle A_> старшим байтом числа M.

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

Содержание

Варианты записи [ править | править код ]

Порядок от старшего к младшему [ править | править код ]

Порядок от старшего к младшему (англ. big-endian — большим концом): A n , … , A 0 <displaystyle A_,dots ,A_<0>> . Этот порядок соответствует привычному порядку записи арабских цифр, например, число сто двадцать три было бы записано при таком порядке как 123. В этом же порядке принято записывать байты в технической и учебной литературе, если другой порядок явно не обозначен.

Этот порядок является стандартным для протоколов TCP/IP, он используется в заголовках пакетов данных и во многих протоколах более высокого уровня, разработанных для использования поверх TCP/IP. Поэтому порядок байтов от старшего к младшему часто называют «сетевым порядком байтов» (англ. network byte order ). Этот порядок байтов используется процессорами IBM 360/370/390, SPARC, Motorola 68000 (отсюда третье название — порядок байтов Motorola, англ. Motorola byte order ).

При таком порядке байтов удобно проводить сравнение строк (можно сравнивать их целочисленными большей разрядности, каждое из которых содержит несколько символов сразу).

Порядок байтов от старшего к младшему применяется также во многих форматах файлов — например, PNG, FLV, EBML, JPEG.

Порядок от младшего к старшему [ править | править код ]

Порядок от младшего к старшему (англ. little-endian — малым концом): A 0 , … , A n <displaystyle A_<0>,dots ,A_>

Это обратный порядок по отношению к привычному порядку записи арабских цифр, например, число сто двадцать три было бы записано при таком порядке как 321.

Этот порядок записи принят в памяти персональных компьютеров с процессорами архитектуры x86, в связи с чем иногда его называют интеловский порядок байтов (по названию компании-создателя архитектуры x86). Современные процессоры x86 позволяют работать с одно-, двух-, четырёх- и восьмибайтовыми операндами. При таком порядке байтов очень удобно то обстоятельство, что при увеличении размера (количества байт) операнда, значение его первого байта остаётся прежним: 3210 → 3210’0000. При порядке от старшего к младшему значение изменилось бы, например: 0123 → 0000’0123;

Кроме x86, такой порядок байтов применяется в архитектурах VAX (отсюда ещё одно название англ. VAX byte order [1] ), DEC Alpha и многих других.

Также порядок от младшего к старшему применяется в USB, PCI, таблице разделов GUID, он рекомендован FidoNet. Но в целом соглашение little-endian поддерживают меньше кросс-платформенных протоколов и форматов данных, чем big-endian.

Переключаемый порядок [ править | править код ]

Многие процессоры могут работать и в порядке от младшего к старшему, и в обратном, например, ARM (по умолчанию — little endian), PowerPC (но не PowerPC 970), DEC Alpha, MIPS, PA-RISC и IA-64. Обычно порядок байтов выбирается программно во время инициализации операционной системы, но может быть выбран и аппаратно перемычками на материнской плате. В этом случае правильнее говорить о порядке байтов операционной системы. Переключаемый порядок байтов иногда называют англ. bi-endian .

Читайте также:  Как выбрать имя пользователя в инстаграме

Смешанный порядок [ править | править код ]

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

В процессорах VAX и ARM используется смешанное представление для длинных вещественных чисел.

Пример [ править | править код ]

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

Все числа записаны в 16-ричной системе счисления.

Число: 0xA1B2C3D4

Представление A 1 ∗ 1000000 16 + B 2 ∗ 10000 16 + C 3 ∗ 100 16 + D 4 ∗ 1 16 = D 4 C 3 B 2 A 1 <displaystyle A1*1000000_<16>+B2*10000_<16>+C3*100_<16>+D4*1_<16>=D4C3B2A1> 161 ∗ 16 10 6 + 178 ∗ 16 10 4 + 195 ∗ 16 10 2 + 212 10 = 2712847316 10 <displaystyle 161*16_<10>^<6>+178*16_<10>^<4>+195*16_<10>^<2>+212_<10>=2712847316_<10>>
Порядок от младшего к старшему (little-endian) D 4 16 , C 3 16 , B 2 16 , A 1 16 <displaystyle D4_<16>,C3_<16>,B2_<16>,A1_<16>> 212 10 , 195 10 , 178 10 , 161 10 <displaystyle 212_<10>,195_<10>,178_<10>,161_<10>>
Порядок от старшего к младшему (big-endian) A 1 16 , B 2 16 , C 3 16 , D 4 16 <displaystyle A1_<16>,B2_<16>,C3_<16>,D4_<16>> 161 10 , 178 10 , 195 10 , 212 10 <displaystyle 161_<10>,178_<10>,195_<10>,212_<10>>
Порядок, принятый в PDP-11 (PDP-endian) B 2 16 , A 1 16 , D 4 16 , C 3 16 <displaystyle B2_<16>,A1_<16>,D4_<16>,C3_<16>> 178 10 , 161 10 , 212 10 , 195 10 <displaystyle 178_<10>,161_<10>,212_<10>,195_<10>>

Определение порядка байтов [ править | править код ]

Порядок байтов в конкретной машине можно определить с помощью программы на языке Си (testbyteorder.c):

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

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

Вещественные числа [ править | править код ]

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

Юникод [ править | править код ]

Если Юникод записан в виде UTF-16 или 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 предусматривает функции 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(), и так далее;

Вы просматриваете архив форума.

Этот форум работает только в режиме просмотра и поиска.

Действующий форум переведен на новый движок и
находится по адресу www.microchip.su

Читайте также:  Mysql запрос с параметрами
Вопрос по СИ
Автор: tester ()
Дата: 06/12/2005 10:19

ламерский вопрос
есть некоторая переменная размера int

b= (low a)
c= (high a)
это не работает

как правильно выделить из него младший и старший байт (Low и High)
для присвоения их двум переменным char
(можно через указатель, а как проще — с минимумом операций)

Отправка отредактированного (06/12/2005 10:21)

Re: Вопрос по СИ
Автор: stiker ()
Дата: 06/12/2005 10:21

Без использования указателей:

#define hibyte(a) ((a>>8) & 0xFF)
#define lobyte(a) ((a) & 0xFF)

Re: Вопрос по СИ
Автор: tester ()
Дата: 06/12/2005 10:22
А еще есть union — тоже полезная вещь
Автор: alho ()
Дата: 06/12/2005 10:31

______________________________________________________
Никогда не спорьте с дураком — люди могут не заметить
разницу между вами

Насчет экономии памяти весьма большие сомнения.
Автор: Bill ()
Дата: 06/12/2005 11:06

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

.
Автор: alho ()
Дата: 06/12/2005 12:36

Union tst <
int a;
char i[2];
> tst1;

использует 2 байта RAM

извините 4 байта RAM.

При чем здесь тупизна компилятора .

______________________________________________________
Никогда не спорьте с дураком — люди могут не заметить
разницу между вами

Речь-то не об этом шла,
Автор: Bill ()
Дата: 06/12/2005 13:09

насколько я понял. Вопрос был как выделить из 16-разрядного числа старший и младший байты.
Использование union только один из вариантов. Другой вариант был приведен выше, но по программному
коду они оба эквивалентны между собой. Только самый "тупой" компилятор будет явно выполнять сдвиг и
логическое "И".
Экономия ОЗУ при использовании union сомнений не вызывает, поэтому и пояснений особых не требует.

🙂 некорректно написАл:
Автор: alho ()
Дата: 06/12/2005 13:23

имел в виду как раз экономию RAM.

______________________________________________________
Никогда не спорьте с дураком — люди могут не заметить
разницу между вами

Re: Вопрос по СИ
Автор: rik ()
Дата: 08/12/2006 01:53

Подскажите, а как сделать наоборот , т.е. имеется две переменных размера char и
переменная размера int. Как записать две переменные char в одну переменную размера
int.

char h,l ; // h — high byte, l — low byte
int a;

все правильно
Автор: Greg ()
Дата: 08/12/2006 07:56

> Подскажите, а как сделать наоборот , т.е. имеется две
> переменных размера char и
> переменная размера int. Как записать две переменные char в
> одну переменную размера
> int.
> пробовал так
> char h,l ; // h — high byte, l — low byte
> int a;
> a = (h Вроде работает, но можно ли так делать? (форматы то у чисел
> разные, не буде ли
> преобразование форматоа из char в int)
>
> А как надо делать?

так и делайте
a = h*256 +l;
или
a = h

лучше сразу запомнить, int на старший-младший байты, тем более char, не делится
Автор: pal ()
Дата: 08/12/2006 09:50

в остальном, см. пост от Greg-а

Спасибо
Автор: rik ()
Дата: 08/12/2006 11:12
Re: лучше сразу запомнить, int на старший-младший байты, тем более char, не делится
Автор: rik ()
Дата: 08/12/2006 12:08

Да, конечно. Просто я пока не нашёл другого способа как принять по USART-у байты и
потом и потом работать с этими байтами как с данными типа int . Опыта написания
програм на СИ нет. Время, как обычно, поджимает. Потом найду более элегантный
способ. Примерно знаю, но надо пробовать, читать книжки, искать в нете .

ну да, второй пример от Greg-a.
Автор: pal ()
Дата: 08/12/2006 12:30

через копирование с приведением типа указателя это и делается

uchar uartbuff[123];
struct CmdStruct
<
uchar field0,field01;
uint field2;
uchar f0:1,f1:3,f2:4;
>CmdStruct;

Инструменты пользователя

Инструменты сайта

Содержание

Операнды поразрядных операций могут быть любого целого типа. К побитовым, или поразрядным операциям относятся:

Читайте также:  Acer al1916w драйвер windows 7 x64

Кроме того, рассматриваются операции сдвигов «, ».

Запись многобайтового числа из памяти компьютера в файл или передача по сети требует соблюдения соглашений о том, какой из байтов является старшим, а какой младшим. Прямая запись ячеек памяти приводит к возможным проблемам при переносе приложения с платформы на платформу. Варианты записи: от старшего к младшему или (англ. big-endian, дословно: «тупоконечный»): этот порядок является стандартным для протоколов TCP/IP, он используется в заголовках пакетов данных и во многих протоколах более высокого уровня, разработанных для использования поверх TCP/IP. Поэтому, порядок байтов от старшего к младшему часто называют сетевым порядком байтов (англ. network byte order). От младшего к старшему или (англ. little-endian, дословно: «остроконечный»): запись начинается с младшего и заканчивается старшим. Этот порядок записи принят в памяти персональных компьютеров с x86-процессорами, в связи с чем иногда его называют интеловский порядок байтов.

Чтобы получить значение младщего слова (OWORD)

Считать старшим битом самую левую единицу — ошибочно, в противном случае в системе со знаком все числа будут или нулем, или отрицательными числами.

Мы знаем, что считать можно до бесконечности, а потому при записи числа на листочке количество знаков может быть неограниченным. Понятие "старший" возникает только тогда, когда есть некоторое ограничение на количество записываемых символов (разрядов). Поэтому старший бит — это самый левый бит в записи N-битного числа, содержащей N разрядов (которые при необходимости слева добираются нулями). Просто глядя на число нельзя сказать, какой бит у него старший, нужно ещё знать, во сколько разрядов мы его хотим записать. Т.е. если мы число 128 записываем в переменную типа unsigned char (8 бит), то cтаршим битом будет единица, а если записываем в unsigned int (16 или 32 бита в зависимости от платформы), то старшим битом будет 0.

В случае знакового представления самый старший бит является знаковым (при условии что мы используем запись в дополнительном коде). И именно этот знаковый бит называют старшим (потому что больше нечего назвать этим термином). Вообще, старший бит — это крайний бит некоего абстрактного регистра (ограниченной длины) для хранения числа.

потому что только нулевой и четвертый разряды обоих операндов содержат 1.

потому что все разряды (кроме шестого) в одном из двух операндов имеют значение 1.

Заметим, что, поскольку нулевой разряд в обоих операндах имеет значение 1, нулевой разряд результата имеет значение 0.

Описанные выше операции часто используются для установки некоторых битов, причем другие биты остаются неизменными. Они удобны для фильтрации или маскирования битов.

Таким образом, х«2 сдвигает х влево на 2 позиции, заполняя освобождающиеся позиции нулями (эквивалентно умножению на 4).

Для значений без знака имеем

Эти две операции выполняют сдвиг, а также эффективное умножение и деление на степени числа 2.

Комментарии к коду.

Для понимания побитовых операторов необходимо свободно уметь работать с двоичным представлением чисел. Если это не так, остается только надеяться, что данные операторы не часто вам будут попадаться в вашей практике. Ниже следует перечень побитовых операторов с примерами их применения (примеры и результаты даны, так же, и в бинарной (двоичной) форме):

Таблица. Побитовые операторы.

Принцип работы побитовых операторов достаточно прост: JavaScript рассматривает последовательно каждый бит операндов, выполняет над ними одну из логических операций (исходя из того, что 1 — true, a 0 — false) и формирует бит результата. Исключением являются лишь операции побитового сдвига. Рассмотрим небольшой пример применения побитовых операций — определение четности числа. Если число является четным, то его первый (крайний правый) бит равен "0" и операция "&" с числом "1" вернет значение "0". Исходя из этого, напишем скрипт:

Листинг: определение четности числа

Если в результате получится значение false, то заданное число является нечетным, в противном случае, число является четным.

Ссылка на основную публикацию
Adblock detector