Типы достоверности

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

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

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

Ответ 1

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

Инвариантность адресов

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

Пример

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

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

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, независимое от конформации. Тем не менее, для доступа меньше полуслова адрес байтов меняется на противоположные между большими и маленькими отображениями endian.

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

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)

Ответ 2

Там также средний или смешанный конец. Подробнее см. wikipedia.

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

Ответ 3

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

Биты

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

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

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

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

Ответ 4

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

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

FFFF 0000

или это:

0000 FFFF

в памяти, в зависимости от степени.

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

FF 00

или

00 FF

и т.д.

Ответ 6

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

В двух ситуациях, когда вам нужно помнить о endianess, есть сетевой код, и если вы выполняете кастинг с помощью указателей.

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

Проблемы с литьем:


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

 data = *((uint16_t*)lptr);

Какова будет ценность данных? В системе с большим энтузиазмом это было бы 0 В системе с малыми значениями, это было бы FFFF

Ответ 7

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;
};

Ответ 8

базовое понятие - упорядочение бит:

1010 0011

в little-endian совпадает с

0011 1010

в big-endian (и наоборот).

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

1100 0101

будет "другой" версией первой версии.