|
|
  |
А кто ткнет в наиболее правильный способ, борьбы с индианностью в С |
|
|
|
Jul 11 2005, 13:37
|
Гуру
     
Группа: СуперМодераторы
Сообщений: 2 065
Регистрация: 11-01-05
Из: Москва
Пользователь №: 1 892

|
Цитата(Andrew2000 @ Jul 11 2005, 17:20) #ifdef BIG_ENDIAN #define intswap(x) ((((x)&0x00ff)<<8)|(((x)& 0xff00)>>8)) #else #define intswap(a) a #endif или что-то типа этого Спасибо! Но в таком случае при разной индианности будет разное количество операций. Что не есть гуд. Хотелось бы идею, как свести алгоритм к примитивам, а их уже менять макросами в зависимости от дефайна.
|
|
|
|
|
Jul 18 2005, 14:07
|
Частый гость
 
Группа: Свой
Сообщений: 185
Регистрация: 30-12-04
Пользователь №: 1 761

|
Можно ещё попробовать вот такую функцию: Код /* Вычисление endian'ности в реальном времени */ int is_little_endian( void ) { union { unsigned long i; unsigned char b[sizeof(i)]; } test;
}
|
|
|
|
|
Jul 18 2005, 14:10
|
Частый гость
 
Группа: Свой
Сообщений: 185
Регистрация: 30-12-04
Пользователь №: 1 761

|
Можно ещё попробовать вот такую функцию: Код /* Вычисление 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]; }
|
|
|
|
|
Jul 19 2005, 10:45
|
Участник

Группа: Свой
Сообщений: 19
Регистрация: 12-04-05
Из: Таганрог, Ростовской обл.
Пользователь №: 4 048

|
Цитата(Evgeny_CD @ Jul 11 2005, 15:55) Пишется код. Он будет идти на разных платформах/компилерах. Почти наверняка будет разная endian: младший байт вначале (прямой порядок, Little Endian) или старший байт в начале (обратный порядок, Big Endian). Соотвественно, если к какой-то переменной обращаются не только как, например, int (он тоже разный на разных платформах), но и как к массиву из 2 или 4 байтов, то это вызовет очень веселые глюки. Кстати, а с 32 битами приколов разной индианности не бывает (когда для dword и word раные endian)? Какой наиболее правильный способ борьбы с этим? Если программа работает c данными только на одной платформе, то проблем меньше. Endian-о зависимые участки кода локализуются и переписываются для разных Endian-ов, далее под разные платформы выбираются (линкуются) разные варианты.  Другой момент - обмен данными между устройствами (процессорами), у которых разный endian. Частный случай - если данные как-либо сохраняются в одном типе, а считываются уже на платформе с другим типом. Проблемы возникают тоько при обмене и только если данные процессором беруться из канала обмена (или из файла) не по байтам, а бОльшими порциями. Одно из решений (не самое лучшее по скорости работы, но лучшее в смысле переносимости) - передавать и принимать данные побайтно. Т.е. если надо передать 2х байтное слово, то выделяем и передаём сначала старший байт, далее младший; на приёмной стороне обратный процесс - считываем один байт, другой, и из двух этих байтов формируем сдвигами нужное нам число. Переносимость стопроцентная. То же можно организовать при сохранении/считывании данных на/с долговременных носителей. Если же нужна скорость, то при передаче данных всё равно кто-то должен делать перекодировку endiana, и выбирается та сторона, которой можно потормозить больше.
|
|
|
|
|
Jul 19 2005, 12:39
|
Участник

Группа: Свой
Сообщений: 19
Регистрация: 12-04-05
Из: Таганрог, Ростовской обл.
Пользователь №: 4 048

|
Цитата(Evgeny_CD @ Jul 11 2005, 15:55) Кстати, а с 32 битами приколов разной индианности не бывает (когда для dword и word раные endian)? Проверил, как TI компилирует сохранение long-a, который у них 40-битный, но, естественно, при обменен с памятью сохраняет-считывает в регистровую пару все 64 бита (8 байт). Так вот, в зависимости от установленного в опциях endian-a сохраняет по разному. Т.е. получается, что все восемь байт будут при этом идти по разному и при попытки обратится как к массиву из int-ов 32-битных для разного endiana получим разные результаты! Цитата(acex2) Иногда в таких случаях можно плату развести с учетом индианности, тогда и тормозить никого не придется Это если сам разводишь плату (или влияешь на этот процесс).
|
|
|
|
|
Jul 20 2005, 06:01
|
Участник

Группа: Свой
Сообщений: 54
Регистрация: 2-03-05
Пользователь №: 3 000

|
Цитата(Eugeno @ Jul 19 2005, 13:45)  Другой момент - обмен данными между устройствами (процессорами), у которых разный 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 */
--------------------
Best regards, Hercules
|
|
|
|
|
Jul 20 2005, 09:12
|
Гуру
     
Группа: СуперМодераторы
Сообщений: 2 065
Регистрация: 11-01-05
Из: Москва
Пользователь №: 1 892

|
Спасибо всем ответившим!!! Но у меня окончательно снесло башню  . Пытаюсь разобраться. Код [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ов одинаковы????
|
|
|
|
|
Jul 20 2005, 14:07
|
Участник

Группа: Свой
Сообщений: 54
Регистрация: 2-03-05
Пользователь №: 3 000

|
Цитата(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 имеют один и тот же порядок следования байт в слове (если это имелось ввиду).
--------------------
Best regards, Hercules
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|