Типы байтов - PullRequest
       38

Типы байтов

12 голосов
/ 22 августа 2008

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

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

Существуют ли другие типы / варианты?

Ответы [ 8 ]

24 голосов
/ 15 сентября 2008

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

Адрес инвариантности

В этом типе отображения адрес байтов всегда сохраняется между большим и маленьким. Это имеет побочный эффект изменения порядка значимости (от наиболее значимого к наименее значимому) конкретного элемента данных (например, 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. Эффект сохранения значения данных определенного размера заключается в том, что байтовые адреса байтов в пределах данных меняются местами между большими и младшими байтовыми отображениями .

Пример * +1026 *

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)
* +1033 * Пример * ** +1036 тысяча тридцать пять * 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) * ** 1044 тысяча сорок-три * Пример * * тысяча сорок-шести

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)
3 голосов
/ 27 августа 2010

Филиберт сказал,

биты были фактически инвертированы

Я сомневаюсь, что любая архитектура нарушит неизменность байтового значения. Порядок битовых полей может нуждаться в инверсии при отображении структур, содержащих их, против данных. Такое прямое отображение опирается на особенности компилятора, которые находятся за пределами стандарта 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;

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

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

3 голосов
/ 22 августа 2008

Есть также средний или смешанный порядок байтов. Подробнее см. Википедия .

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

1 голос
/ 22 августа 2008

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

1 голос
/ 22 августа 2008

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

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

FFFF 0000

или это:

0000 FFFF

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

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

FF 00

или

00 FF

и т. Д.

0 голосов
/ 16 сентября 2008

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;
};
0 голосов
/ 16 сентября 2008

Практически говоря, 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

0 голосов
/ 22 августа 2008

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

1010 0011

в младшем порядке совпадает с

0011 1010

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

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

1100 0101

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

...