Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: А кто ткнет в наиболее правильный способ
Форум разработчиков электроники ELECTRONIX.ru > Цифровая обработка сигналов - ЦОС (DSP) > Алгоритмы ЦОС (DSP)
Evgeny_CD
Пишется код. Он будет идти на разных платформах/компилерах. Почти наверняка будет разная endian: младший байт вначале (прямой порядок, Little Endian) или старший байт в начале (обратный порядок, Big Endian).

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

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

Какой наиболее правильный способ борьбы с этим?
Andrew2000
#ifdef BIG_ENDIAN
#define intswap(x) ((((x)&0x00ff)<<8)|(((x)& 0xff00)>>8))
#else
#define intswap(a) a
#endif
или что-то типа этого
Evgeny_CD
Цитата(Andrew2000 @ Jul 11 2005, 17:20)
#ifdef BIG_ENDIAN
#define intswap(x) ((((x)&0x00ff)<<8)|(((x)& 0xff00)>>8))
#else
#define intswap(a) a
#endif
или что-то типа этого
*
Спасибо! Но в таком случае при разной индианности будет разное количество операций. Что не есть гуд.

Хотелось бы идею, как свести алгоритм к примитивам, а их уже менять макросами в зависимости от дефайна.
acex2
Цитата(Evgeny_CD @ Jul 11 2005, 10:37)
Хотелось бы идею, как свести алгоритм к примитивам, а их уже менять макросами в зависимости от дефайна.


А вы посмотрите исходники криптографических алгоритмов на Си - там такая задача решается именно через define и макроопределения базовых операций с байтами в зависимости от индианности. Но вот сохранить равное количество команд вряд-ли получится, разве что отключать оптимизацию компилятора или специально вводить nop.
Evgeny_CD
Цитата(acex2 @ Jul 11 2005, 18:30)
А вы посмотрите исходники криптографических алгоритмов на Си - там такая задача решается именно через define и макроопределения базовых операций с байтами в зависимости от индианности. Но вот сохранить равное количество команд вряд-ли получится, разве что отключать оптимизацию компилятора или специально вводить nop.
Хорошая мысль! Спасибо!

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

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

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

Код
/*
Вычисление 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];
}
acex2
Цитата(Zig @ Jul 18 2005, 11:10)
Можно ещё попробовать вот такую функцию:
Вычисление endian'ности в реальном времени
Должно возвращать 1: Intel (little endian), 0: Power PC (big endian)

skipped


А смысл такой функции кроме академического интереса? Бинарный код все равно придется перекомпилировать под конкретный процессор.
Eugeno
Цитата(Evgeny_CD @ Jul 11 2005, 15:55)
Пишется код. Он будет идти на разных платформах/компилерах. Почти наверняка будет разная endian: младший байт вначале (прямой порядок, Little Endian) или старший байт в начале (обратный порядок, Big Endian).

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

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

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


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

angry.gif Другой момент - обмен данными между устройствами (процессорами), у которых разный endian. Частный случай - если данные как-либо сохраняются в одном типе, а считываются уже на платформе с другим типом.
Проблемы возникают тоько при обмене и только если данные процессором беруться из канала обмена (или из файла) не по байтам, а бОльшими порциями. Одно из решений (не самое лучшее по скорости работы, но лучшее в смысле переносимости) - передавать и принимать данные побайтно. Т.е. если надо передать 2х байтное слово, то выделяем и передаём сначала старший байт, далее младший; на приёмной стороне обратный процесс - считываем один байт, другой, и из двух этих байтов формируем сдвигами нужное нам число. Переносимость стопроцентная. То же можно организовать при сохранении/считывании данных на/с долговременных носителей.
Если же нужна скорость, то при передаче данных всё равно кто-то должен делать перекодировку endiana, и выбирается та сторона, которой можно потормозить больше.
acex2
Цитата(Eugeno @ Jul 19 2005, 07:45)
Если же нужна скорость, то при передаче данных всё равно кто-то должен делать перекодировку endiana, и выбирается та сторона, которой можно потормозить больше.


Иногда в таких случаях можно плату развести с учетом индианности, тогда и тормозить никого не придется wink.gif
Eugeno
Цитата(Evgeny_CD @ Jul 11 2005, 15:55)
Кстати, а с 32 битами приколов разной индианности не бывает (когда для dword и word раные endian)?
*

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

Это если сам разводишь плату (или влияешь на этот процесс).
Hercules
Цитата(Eugeno @ Jul 19 2005, 13:45)
angry.gif Другой момент - обмен данными между устройствами (процессорами), у которых разный 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 */
Evgeny_CD
Спасибо всем ответившим!!!

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

Код
[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ов одинаковы????
Hercules
Цитата(Evgeny_CD @ Jul 20 2005, 12:12)
Вопрос: когда говорят 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-ти разрядный доступ)


Цитата(Evgeny_CD @ Jul 20 2005, 12:12)
Они у всех ARMов одинаковы????
*


Все ARM-ы с одинаковым ENDIAN имеют один и тот же порядок следования байт в слове (если это имелось ввиду).
Evgeny_CD
Цитата(Hercules @ Jul 20 2005, 18:07)
Все ARM-ы с одинаковым ENDIAN имеют один и тот же порядок следования байт в слове (если это имелось ввиду).
*
Спасибо за "альтернативный" вариант!

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

А что, что я назвал CRAZY, это, вероятно, существует только в глюканутых бошках творцов компиляторов на 8 и 16 битные системы. smile3046.gif
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2024 Invision Power Services, Inc.