Типы байтов

В чем разница между следующими типами байтов?

  • byte (8b) инвариантный порядок байтов и младший порядок байтов
  • полуслова (16b) инвариант большой и малой байтов
  • word (32b) инвариант большой и малой последовательности байтов
  • двойное слово (64b) инвариант большой и малой порядков байтов

Есть ли другие типы / варианты?

Если ваша система имеет 128-битные типы данных, у вас, конечно же, есть четверное слово большой и малый порядок байтов. // Это часто возникает в многопроцессорном коде, где у вас есть такие инструкции, как Intel CMPXCHG16B: представьте, что LE x86 обращается к устройству ввода-вывода Big Endian.

Krazy Glew 15.09.2016 01:34
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
15
1
11 803
8

Ответы 8

основная концепция - это порядок битов:

1010 0011

in little-endian это то же самое, что

0011 1010

с прямым порядком байтов (и наоборот).

Вы заметите изменения порядка по группировке, а не по отдельности. Я не знаю, например, системы, где

1100 0101

будет версией первой версии с обратным порядком байтов.

Обычно байтовый порядок байтов, но то, что вы здесь описали, является байтовым порядком байтов (группы из 4, а не 8 битов, что, я сомневаюсь, что-либо использует).

Scott Griffiths 10.09.2009 00:41

Также существует средний или смешанный порядок байтов. Подробнее см. википедия.

Единственный раз, когда мне приходилось беспокоиться об этом, было при написании сетевого кода на C. В сети обычно используется алгоритм IIRC с прямым порядком байтов. Большинство языков либо абстрагируют все, либо предлагают библиотеки, чтобы гарантировать, что вы используете правильный порядок байтов.

Фактически, я бы описал порядок байтов машины как порядок байты внутри слова, а не порядок биты.

Под «байтами» я подразумеваю «наименьшую единицу памяти, которой архитектура может управлять индивидуально». Итак, если наименьшая единица имеет длину 16 бит (то, что в x86 будет называться слово), то 32-битное «слово», представляющее значение 0xFFFF0000, может быть сохранено следующим образом:

FFFF 0000

или это:

0000 FFFF

в памяти, в зависимости от порядка байтов.

Итак, если у вас 8-битный порядок байтов, это означает, что каждое слово, состоящее из 16 бит, будет сохранено как:

FF 00

или же:

00 FF

и так далее.

Извините, но это очень запутано. Порядок байтов (почти) всегда либо побитовый, либо чаще побайтный, где байт - это стандартные восемь битов. Ваш пример FFFF0000 выбран неудачно, поскольку он становится 0000FFFF, если вы поменяете местами побитовое, побайтовое или словесное, поэтому невозможно сказать, что вы пытаетесь сказать!

Scott Griffiths 26.10.2009 19:18

Ага, вы абсолютно правы, я просто ленился, LOL. Спасибо, что указали :)

dguaraglia 16.11.2009 01:18

Я говорю «байтовый порядок байтов» или «битовый порядок байтов», когда мне нужно различать.

Krazy Glew 19.02.2014 06:05

Лучшая статья о порядке байтов "Понимание порядка байтов с прямым и обратным порядком байтов", которую я читал.

Существует два подхода к отображению порядка байтов: адресная инвариантность и инвариантность данных.

Адресная неизменность

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

Пример

Инвариантность адреса (также известная как байтовая инвариантность): байтовый адрес постоянен, но значение байта инвертировано.

Addr   Memory
       7    0
       |    |    (LE)   (BE)
       |----|
 +0    | aa |    lsb    msb
       |----|
 +1    | bb |     :      :
       |----|
 +2    | cc |     :      :
       |----|
 +3    | dd |    msb    lsb
       |----|
       |    |

At Addr=0:          Little-endian          Big-endian
Read 1 byte:              0xaa                0xaa   (preserved)
Read 2 bytes:           0xbbaa              0xaabb
Read 4 bytes:       0xddccbbaa          0xaabbccdd

Инвариантность данных

В этом типе отображения относительная значимость байтов сохраняется для данных определенного размера. Следовательно, существуют разные типы инвариантных для данных сопоставлений с порядком байтов для разных размеров данных. Например, 32-битное инвариантное отображение порядка следования слов будет использоваться для размера данных 32. Эффект от сохранения значения данных определенного размера заключается в том, что байтовые адреса байтов в пределах данных меняются местами между отображениями большого и малого порядка байтов. .

Пример

32-битная инвариантность данных (также известная как неизменность слов): датум представляет собой 32-битное слово, которое всегда имеет значение 0xddccbbaa, независимо от порядка байтов. Однако для доступа размером меньше одного слова адреса байтов меняются местами между отображениями с прямым порядком байтов и обратным порядком байтов.

Addr                Memory

            | +3   +2   +1   +0 |  <- LE
            |-------------------|
+0      msb | dd | cc | bb | aa |  lsb
            |-------------------|
+4      msb | 99 | 88 | 77 | 66 |  lsb
            |-------------------|
     BE ->  | +0   +1   +2   +3 |


At Addr=0:             Little-endian              Big-endian
Read 1 byte:                 0xaa                    0xdd
Read 2 bytes:              0xbbaa                  0xddcc
Read 4 bytes:          0xddccbbaa              0xddccbbaa   (preserved)
Read 8 bytes:  0x99887766ddccbbaa      0x99887766ddccbbaa   (preserved)

Пример

16-битная инвариантность данных (также известная как полусловная инвариантность): данные являются 16-битными. который всегда имеет значение 0xbbaa, независимо от порядка байтов. Однако для обращений размером меньше полуслова адреса байтов меняются местами между отображениями с прямым порядком байтов и обратным порядком байтов.

Addr           Memory

            | +1   +0 |  <- LE
            |---------|
+0      msb | bb | aa |  lsb
            |---------|
+2      msb | dd | cc |  lsb
            |---------|
+4      msb | 77 | 66 |  lsb
            |---------|
+6      msb | 99 | 88 |  lsb
            |---------|
     BE ->  | +0   +1 |


At Addr=0:             Little-endian              Big-endian
Read 1 byte:                 0xaa                    0xbb
Read 2 bytes:              0xbbaa                  0xbbaa   (preserved)
Read 4 bytes:          0xddccbbaa              0xddccbbaa   (preserved)
Read 8 bytes:  0x99887766ddccbbaa      0x99887766ddccbbaa   (preserved)

Пример

64-битная инвариантность данных (также известная как двойное слово инвариантность): данные являются 64-битными. слово, которое всегда имеет значение 0x99887766ddccbbaa, независимо от порядка байтов. Однако для обращений размером меньше двойного слова адреса байтов меняются местами между отображениями с прямым порядком байтов и обратным порядком байтов.

Addr                         Memory

            | +7   +6   +5   +4   +3   +2   +1   +0 |  <- LE
            |---------------------------------------|
+0      msb | 99 | 88 | 77 | 66 | dd | cc | bb | aa |  lsb
            |---------------------------------------|
     BE ->  | +0   +1   +2   +3   +4   +5   +6   +7 |


At Addr=0:             Little-endian              Big-endian
Read 1 byte:                 0xaa                    0x99
Read 2 bytes:              0xbbaa                  0x9988
Read 4 bytes:          0xddccbbaa              0x99887766
Read 8 bytes:  0x99887766ddccbbaa      0x99887766ddccbbaa   (preserved)

Фактически, endianess относится к способу интерпретации процессором содержимого данной ячейки памяти. Например, если у нас есть ячейка памяти 0x100 со следующим содержимым (шестнадцатеричные байты)


  0x100:  12 34 56 78 90 ab cd ef

Reads    Little Endian            Big Endian
 8-bit:  12                        12
16-bit:  34 12                     12 34
32-bit:  78 56 34 12               12 34 56 78
64-bit:  ef cd ab 90 78 56 34 12   12 34 56 78 90 ab cd ef

Две ситуации, когда вам нужно помнить о порядке байтов, - это сетевой код и приведение вниз с помощью указателей.

TCP / IP указывает, что данные в проводе должны иметь прямой порядок байтов. Если вы передаете типы, отличные от байтовых массивов (например, указатели на структуры), вы должны обязательно использовать макросы ntoh / hton, чтобы гарантировать, что данные отправляются с прямым порядком байтов. Если вы отправляете от процессора с прямым порядком байтов к процессору с прямым порядком байтов (или наоборот), данные будут искажены ...

Проблемы с кастингом:


 uint32_t* lptr = 0x100;
 uint16_t  data;
 *lptr = 0x0000FFFF

 data = *((uint16_t*)lptr);

Какова будет ценность данных? В системе с прямым порядком байтов это будет 0 В системе с прямым порядком байтов это будет FFFF

13 лет назад я работал над инструментом, переносимым как на систему DEC ALPHA, так и на ПК. На этом DEC ALPHA биты были фактически инвертированы. То есть:

1010 0011

фактически переведено на

1100 0101

Он был почти прозрачным и бесшовным в коде C, за исключением того, что я объявил битовое поле, например

typedef struct {
   int firstbit:1;
   int middlebits:10;
   int lastbits:21;
};

в который нужно было перевести (с использованием условной компиляции #ifdef)

typedef struct {
   int lastbits:21;
   int middlebits:10;
   int firstbit:1;
};

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

Jonathan Leffler 19.04.2015 09:05

Филибер сказал:

bits were actually inverted

Я сомневаюсь, что какая-либо архитектура нарушит инвариантность байтовых значений. Порядок битовых полей может нуждаться в инверсии при сопоставлении содержащих их структур с данными. Такое прямое сопоставление зависит от особенностей компилятора, которые выходят за рамки стандарта C99, но все же могут быть распространены. Прямое отображение выполняется быстрее, но не соответствует стандарту C99, который не предусматривает упаковки, выравнивания и порядка байтов. Код, совместимый с C99, должен использовать медленное отображение на основе значений, а не адресов. То есть вместо этого

#if LITTLE_ENDIAN
  struct breakdown_t {
    int least_significant_bit: 1;
    int middle_bits: 10;
    int most_significant_bits: 21;
  };
#elif BIG_ENDIAN
  struct breakdown_t {
    int most_significant_bits: 21;
    int middle_bits: 10;
    int least_significant_bit: 1;
  };
#else
  #error Huh
#endif

uint32_t data = ...;
struct breakdown_t *b = (struct breakdown_t *)&data;

нужно написать это (и именно так компилятор все равно будет генерировать код даже для вышеупомянутого «прямого сопоставления»),

uint32_t data = ...;
uint32_t least_significant_bit = data & 0x00000001;
uint32_t middle_bits = (data >> 1) & 0x000003FF;
uint32_t most_significant_bits = (data >> 11) & 0x001fffff;

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

«Порядок битов» в каждом байте не имеет значения, поскольку единственный способ их извлечь - это применить маски значений и сдвиг в направлении наименее значимого или наиболее значимого бита. Проблема «порядка битов» станет важной только в воображаемых архитектурах с понятием битовых адресов. Я считаю, что все существующие архитектуры скрывают это понятие в оборудовании и обеспечивают извлечение только наименьшего и наиболее значимого битов, что является понятием, основанным на значениях байтов, нейтральных к порядку байтов.

Нарушить неизменность байтовых значений несложно. Например. у вас есть 8-битная шина, биты данных 0-7, и вы подключаете их к устройству или памяти в обратном порядке, то есть подключаете Dev0.Bit0-Dev1.Bit7, Dev0.Bit1-Dev1.Bit6 ... Dev0.Bit7- Dev1.Bit0. // Возможно, вы вряд ли столкнетесь с этим во всей системе, но это МОЖЕТ произойти, и часто случается для узкой области памяти и так далее. // Я обычно использую такие термины, как "порядок байтов" и "порядок байтов", чтобы быть точным в отношении того, что обсуждается.

Krazy Glew 15.09.2016 01:26

Другие вопросы по теме