Сведения о вопросе

HEIGTH

09:29, 23rd August, 2020

Теги

endianness    

Типы байтов

Просмотров: 470   Ответов: 8

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

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

Есть ли другие types/variations?



  Сведения об ответе

prince

13:51, 17th August, 2020

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

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

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

Пример

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

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)

  Сведения об ответе

lourence

22:10, 17th August, 2020

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

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

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

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

"order of bits" в каждом байте не имеет значения, поскольку единственный способ извлечь их-это применить маски значений и перейти в направлении least-significant-bit или most-significant-bit. Проблема "order of bits" станет важной только в воображаемых архитектурах с понятием битовых адресов. Я считаю, что все существующие архитектуры скрывают это понятие в аппаратном обеспечении и обеспечивают только наименьшее и самое значительное извлечение битов, которое основано на конечных нейтральных байтовых значениях.


  Сведения об ответе

dump

17:39, 22nd August, 2020

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

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


  Сведения об ответе

darknet

12:54, 1st August, 2020

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

Под "bytes" там наверху я подразумеваю "smallest unit of memory the architecture can manage individually". Итак, если самая маленькая единица имеет длину 16 бит (то, что в x86 называется словом ) , то 32 бит "word", представляющий значение 0xFFFF0000, может быть сохранен следующим образом:

FFFF 0000

или вот это:

0000 FFFF

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

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

FF 00

или:

00 FF

и так далее.


  Сведения об ответе

PHPH

03:19, 4th August, 2020

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


  Сведения об ответе

dump

17:00, 7th August, 2020

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


  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 macros, чтобы гарантировать, что данные передаются big endian. Если вы отправляете данные от процессора с малым концом к процессору с большим концом (или наоборот), данные будут искажены...

Вопросы кастинга:


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

 data = *((uint16_t*)lptr);

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


  Сведения об ответе

DO__IT

03:38, 8th August, 2020

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

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


  Сведения об ответе

dumai

20:22, 27th August, 2020

основной концепцией является упорядочение битов:

1010 0011

в little-endian является таким же, как

0011 1010

у тупоконечников (и наоборот).

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

1100 0101

это будет версия "other-endian" первой версии.


Ответить на вопрос

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