Перейти к содержанию
    

А кто ткнет в наиболее правильный способ

Пишется код. Он будет идти на разных платформах/компилерах. Почти наверняка будет разная endian: младший байт вначале (прямой порядок, Little Endian) или старший байт в начале (обратный порядок, Big Endian).

 

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

 

Кстати, а с 32 битами приколов разной индианности не бывает (когда для dword и word раные endian)?

 

Какой наиболее правильный способ борьбы с этим?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

#ifdef BIG_ENDIAN

#define intswap(x) ((((x)&0x00ff)<<8)|(((x)& 0xff00)>>8))

#else

#define intswap(a) a

#endif

или что-то типа этого

Спасибо! Но в таком случае при разной индианности будет разное количество операций. Что не есть гуд.

 

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

 

А вы посмотрите исходники криптографических алгоритмов на Си - там такая задача решается именно через define и макроопределения базовых операций с байтами в зависимости от индианности. Но вот сохранить равное количество команд вряд-ли получится, разве что отключать оптимизацию компилятора или специально вводить nop.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А вы посмотрите исходники криптографических алгоритмов на Си - там такая задача решается именно через define и макроопределения базовых операций с байтами в зависимости от индианности. Но вот сохранить равное количество команд вряд-ли получится, разве что отключать оптимизацию компилятора или специально вводить nop.
Хорошая мысль! Спасибо!

 

Искуственно замедлять проц не надо, надо не нагружать его лишней работой. :biggrin:

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Можно ещё попробовать вот такую функцию:

 

/*
Вычисление endian'ности в реальном времени
*/
int is_little_endian( void )
{
union
   {
       unsigned long i;
       unsigned char b[sizeof(i)];
   } test;

}

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Можно ещё попробовать вот такую функцию:

 

/*
Вычисление endian'ности в реальном времени

Должно возвращать 1: Intel (little endian), 0: Power PC (big endian)
*/
int is_little_endian( void )
{
   union Test
   {
       int i;
       char b[sizeof(int)];
   };

   static const Test test = { 1 };

   return test.b[0];
}

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Можно ещё попробовать вот такую функцию:

Вычисление endian'ности в реальном времени

Должно возвращать 1: Intel (little endian), 0: Power PC (big endian)

 

skipped

 

А смысл такой функции кроме академического интереса? Бинарный код все равно придется перекомпилировать под конкретный процессор.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Пишется код. Он будет идти на разных платформах/компилерах. Почти наверняка будет разная endian: младший байт вначале (прямой порядок, Little Endian) или старший байт в начале (обратный порядок, Big Endian).

 

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

 

Кстати, а с 32 битами приколов разной индианности не бывает (когда для dword и word раные endian)?

 

Какой наиболее правильный способ борьбы с этим?

 

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

 

:angry2: Другой момент - обмен данными между устройствами (процессорами), у которых разный endian. Частный случай - если данные как-либо сохраняются в одном типе, а считываются уже на платформе с другим типом.

Проблемы возникают тоько при обмене и только если данные процессором беруться из канала обмена (или из файла) не по байтам, а бОльшими порциями. Одно из решений (не самое лучшее по скорости работы, но лучшее в смысле переносимости) - передавать и принимать данные побайтно. Т.е. если надо передать 2х байтное слово, то выделяем и передаём сначала старший байт, далее младший; на приёмной стороне обратный процесс - считываем один байт, другой, и из двух этих байтов формируем сдвигами нужное нам число. Переносимость стопроцентная. То же можно организовать при сохранении/считывании данных на/с долговременных носителей.

Если же нужна скорость, то при передаче данных всё равно кто-то должен делать перекодировку endiana, и выбирается та сторона, которой можно потормозить больше.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Если же нужна скорость, то при передаче данных всё равно кто-то должен делать перекодировку endiana, и выбирается та сторона, которой можно потормозить больше.

 

Иногда в таких случаях можно плату развести с учетом индианности, тогда и тормозить никого не придется ;)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Кстати, а с 32 битами приколов разной индианности не бывает (когда для dword и word раные endian)?

Проверил, как TI компилирует сохранение long-a, который у них 40-битный, но, естественно, при обменен с памятью сохраняет-считывает в регистровую пару все 64 бита (8 байт). Так вот, в зависимости от установленного в опциях endian-a сохраняет по разному. Т.е. получается, что все восемь байт будут при этом идти по разному и при попытки обратится как к массиву из int-ов 32-битных для разного endiana получим разные результаты! :(

Иногда в таких случаях можно плату развести с учетом индианности, тогда и тормозить никого не придется

Это если сам разводишь плату (или влияешь на этот процесс).

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

:angry2: Другой момент - обмен данными между устройствами (процессорами), у которых разный endian. Частный случай - если данные как-либо сохраняются в одном типе, а считываются уже на платформе с другим типом.

Проблемы возникают тоько при обмене и только если данные процессором беруться из канала обмена (или из файла) не по байтам, а бОльшими порциями. Одно из решений (не самое лучшее по скорости работы, но лучшее в смысле переносимости) - передавать и принимать данные побайтно. Т.е. если надо передать 2х байтное слово, то выделяем и передаём сначала старший байт, далее младший; на приёмной стороне обратный процесс - считываем один байт, другой, и из двух этих байтов формируем сдвигами нужное нам число. Переносимость стопроцентная. То же можно организовать при сохранении/считывании данных на/с долговременных носителей.

Если же нужна скорость, то при передаче данных всё равно кто-то должен делать перекодировку endiana, и выбирается та сторона, которой можно потормозить больше.

 

Вообще-то, обычная практика при обмене между двумя устройствами (с разными или одинаковыми endian) приводить порядок следования байт к одному виду, а именно к "network byte order" (ака bigendian). А на хосте используются функции конвертации из "network byte order" к порядку следования байт на хосте и обратно типа: htonl (для 32-х разрядов), htons (для 16-ти разрядов).

Эти функции в зависимости от того какой endian на хосте либо крутят байты, либо нет.

 

Пример:

 

#ifndef LITTLE_ENDIAN

#define LITTLE_ENDIAN 3412

#endif /* LITTLE_ENDIAN */

 

#ifndef BIG_ENDIAN

#define BIG_ENDIAN 1234

#endif /* BIG_ENDIAN */

 

 

#ifndef BYTE_ORDER

#error BYTE_ORDER is not defined

#endif

 

#if BYTE_ORDER == LITTLE_ENDIAN

u16_t htons(u16_t n)

{

return ((n & 0xff) << 8) | ((n & 0xff00) >> 8);

}

 

u16_t ntohs(u16_t n)

{

return htons(n);

}

 

u32_t htonl(u32_t n)

{

return ((n & 0xff) << 24) |

((n & 0xff00) << 8) |

((n & 0xff0000) >> 8) |

((n & 0xff000000) >> 24);

}

 

u32_t ntohl(u32_t n)

{

return htonl(n);

}

#else /* BYTE_ORDER == BIG_ENDIAN */

 

#define htons(x) (x)

#define ntohs(x) (x)

#define htonl(x) (x)

#define ntohl(x) (x)

 

#endif /* BYTE_ORDER == LITTLE_ENDIAN */

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Спасибо всем ответившим!!!

 

Но у меня окончательно снесло башню :wacko: . Пытаюсь разобраться.

 

[b31---byte_dword_3---b24][b23---byte_dword_2---b16][b15---byte_dword_1---b8][b7---byte_dword_0---b0]
|~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~dword_0~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~~~~|
[b15----byte_word_1----b8][b7----byte_word_0-----b0][b15----byte_word_1---b8][b7----byte_word_0---b0]
|~~~~~~~~~~~~~~~~~~~~word_1~~~~~~~~~~~~~~~~~~~~~~~~||~~~~~~~~~~~~~~~~~~~~~word_0
~~~~~~~~~~~~~~~~~~~~|

b0 - бит 0 - младший бит - LSB
b31 - бит 31 - старший бит - MSB

byte_dword_0 - младший байт - LSB
byte_dword_3 - старший байт - MSB

word_0 - младший word - LSW (его так и вправду обозначают???)
word_1 - старший word - MSW (его так и вправду обозначают???)

byte_word_0 - младший байт - LSB
byte_word_1 - старший байт - MSB

BASE - адрес dword_0

********************** BIG ENDIAN ******************************************************
* байты внутри word - {BIG ENDIAN}, старшие вначале
* байты внутри dword - {BIG ENDIAN}, старшие вначале
* word внутри dword - {BIG ENDIAN}, старшие вначале

word_0{BIG ENDIAN}----BASE+0x00 = [byte_dword_3] = word_1{BIG ENDIAN}-[byte_word_1]
                  \---BASE+0x01 = [byte_dword_2] =                   \[byte_word_0]
                   \--BASE+0x02 = [byte_dword_1] = word_0{BIG ENDIAN}-[byte_word_1]
                    \-BASE+0x03 = [byte_dword_0] =                   \[byte_word_0]
********************************************************************************
*********

*********************** LITTLE ENDIAN ***************************************************
* байты внутри word - {LITTLE ENDIAN}, младшие вначале
* байты внутри dword - {LITTLE ENDIAN}, младшие вначале
* word внутри dword - {LITTLE ENDIAN}, младшие вначале

word_0{LITTLE ENDIAN}----BASE+0x00 = [byte_dword_0] = word_0{LITTLE ENDIAN}-[byte_word_0]
                     \---BASE+0x01 = [byte_dword_1] =                      \[byte_word_1]
                      \--BASE+0x02 = [byte_dword_2] = word_1{LITTLE ENDIAN}-[byte_word_0]
                       \-BASE+0x03 = [byte_dword_3] =                      \[byte_word_1]
********************************************************************************
*********

*** А это что за нафиг??? И как его назвать??? Насколько я понимаю, так PDP-11 жила... **
* байты внутри word - {BIG ENDIAN}, старшие вначале
* word внутри dword - {LITTLE ENDIAN}, младшие вначале
* байты внутри word ????

word_0{CRAZY_1}----BASE+0x00 = [byte_dword_1] = word_0{BIG ENDIAN}-[byte_word_1]
               \---BASE+0x01 = [byte_dword_0] =                   \[byte_word_0]
                \--BASE+0x02 = [byte_dword_3] = word_1{BIG ENDIAN}-[byte_word_1]
                 \-BASE+0x03 = [byte_dword_2] =                   \[byte_word_0]
********************************************************************************
*********

************************** комплементарное извращение ***********************************
* байты внутри word - {LITTLE ENDIAN}, младшие вначале
* word внутри dword - {BIG ENDIAN}, старшие вначале
* байты внутри word ???
word_0{CRAZY_2}----BASE+0x00 = [byte_dword_2] = word_1{LITTLE ENDIAN}-[byte_word_0]
               \---BASE+0x01 = [byte_dword_3] =                      \[byte_word_1]
                \--BASE+0x02 = [byte_dword_0] = word_0{LITTLE ENDIAN}-[byte_word_0]
                 \-BASE+0x03 = [byte_dword_1] =                      \[byte_word_1]
********************************************************************************
*********

Интересно, а в 64 битных машинках все тоже не договорились, и там существуют 8 комбинаций индианов???

 

Вопрос: когда говорят ARM LITTLE ENDIAN, ARM BIG ENDIAN - кака я из комбинаций имеется в виду? Они у всех ARMов одинаковы????

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Вопрос: когда говорят ARM LITTLE ENDIAN, ARM BIG ENDIAN - кака я из комбинаций имеется в виду?

 

Может быть так будет понятней:

 

   
Пусть у нас при 8-ми битном доступе:
addr      value
0x0000   0x12
0x0001   0x34
0x0002   0x56
0x0003   0x78
0x0004   0x9A
0x0005   0xBC
0x0006   0xDE
0x0007   0xF0

Тогда для LITLE_ENDIAN эта же память при 16-ти разрядном доступе будет выглядеть так:
addr      value
0x0000   0x3412
0x0002   0x7856
0x0004   0xBC9A
0x0006   0xF0DE

При 32-ти разрядном доступе:
addr      value
0x0000   0x78563412
0x0004   0xF0DEBC9A

При 64-ти разрядном доступе:
addr      value
0x0000   0xF0DEBC9A78563412

А для BIG_ENDIAN эта же память при 16-ти разрядном доступе будет выглядеть так:
addr      value
0x0000   0x1234
0x0002   0x5678
0x0004   0x9ABC
0x0006   0xDEF0

При 32-ти разрядном доступе:
addr      value
0x0000   0x12345678
0x0004   0x9ABCDEF0

При 64-ти разрядном доступе:
addr      value
0x0000   0x123456789ABCDEF0

 

т.е. если говорят ARM LITTLE ENDIAN, то имеется ввиду порядок байт в слове: 0x4321 (если рассматривать 16-ти разрядный доступ),

 

а если говорят ARM BIG ENDIAN, то имеется ввиду порядок байт в слове: 0x1234 (если рассматривать 16-ти разрядный доступ)

 

 

Они у всех ARMов одинаковы????

 

Все ARM-ы с одинаковым ENDIAN имеют один и тот же порядок следования байт в слове (если это имелось ввиду).

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Все ARM-ы с одинаковым ENDIAN имеют один и тот же порядок следования байт в слове (если это имелось ввиду).

Спасибо за "альтернативный" вариант!

 

Я, прежде всего, хотел выяснить, совпадает ли индианность для байтов внутри word и для word внутри dword. Судя по Вашим ответам - совпадает.

 

А что, что я назвал CRAZY, это, вероятно, существует только в глюканутых бошках творцов компиляторов на 8 и 16 битные системы. :smile3046:

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

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

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...