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

Ошибка считывание DWORD данных из BYTE массива

В программе, написанной на C++ (Keil) для LPC2366 обнаружилась следующая проблема при работе с массивом:

 

Вот оптимизированный для просмотра отрывок из программы:

 

BYTE byData[8] = {0x12, 0x00, 0x0A, 0x00, 0x01, 0x00, 0x02, 0x00};

BYTE* prtBuf = (BYTE*)byData;

DWORD dwVal1 = *((DWORD*)(prtBuf));

DWORD dwVal2 = *((DWORD*)(prtBuf + 1));

DWORD dwVal3 = *((DWORD*)(prtBuf + 2));

DWORD dwVal4 = *((DWORD*)(prtBuf + 4));

 

На выходе получаю следующие значения:

dwVal1 = 0x000A0012;

dwVal2 = 0x12000A00;

dwVal3 = 0x0012000A;

dwVal4 = 0x00020001;

 

Ошибка возникает в значении dwVal2 и dwVal3, т.е. при смещении относительно начала массива, не кратно DWORD. Из-за чего это происходит и можно ли с этим бороться!?

Изменено пользователем Yaumen

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


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

Из-за чего это происходит и можно ли с этим бороться!?

Из-за того, что ARM7 сам по себе не умеет читать слова по невыровненным адресам.

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


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

Из-за того, что ARM7 сам по себе не умеет читать слова по невыровненным адресам.

 

Т.е. или все выравнивать или формировать DWORD самому, считывая побайтно?

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


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

Ну, не обязательно самому, можно написать:

DWORD dwVal2 = *((__packed DWORD*)(prtBuf + 1));

 

Но лучше, естественно, выравнивать.

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


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

Т.е. или все выравнивать или формировать DWORD самому, считывая побайтно?

Вообще-то крайне желательно с форумом ознакомится - вопрос обыденный. Только с неделю назад очередное обострение было.

Руками незачем. Лучше поставить правильно задачу компилятору правильно описав данные. На худой конец memcpy().

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


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

Вообще-то крайне желательно с форумом ознакомится - вопрос обыденный. Только с неделю назад очередное обострение было.

Руками незачем. Лучше поставить правильно задачу компилятору правильно описав данные. На худой конец memcpy().

memcpy тоже лажался на невыровненных 32-битных переменных (float в т.ч.)

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

Сейчас на Cortex такой проблемы нет

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


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

Подробностей уже не помню...

Не надо рассказывать байки, тем более, которые не помните. memcpy(), как минимум, не знает ведать не ведает ни о каких типах данных, поскольку работает исключительно с void *. По этой банальной причине он просто не способен различить float и не способен с ним работать иначе и неправильнее чем с любым другим типом.

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


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

А будет ли та же проблема со структурой, объявленной как:

 

#pragma pack(1)

struct MSGHEADER

{

BYTE ...

BYTE ...

BYTE ...

WORD wParameter

};

#pragma pack()

 

т.е. смогу ли нормально вычитать WORD переменную:

WORD wVal = pMsg->wParameter

или тоже будут проблемы с выравниванием?

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


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

Проблем быть не должно - будет медленное обращение по байтам с последующим "склеиванием".

Соответственно, если хочется скорости работы, лучше так не делать.

 

 

Да, если сделать, например, так:

int fnc (WORD *ptr);
...
fnc (&pMsg->wParameter);

проблема будет.

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


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

Не надо рассказывать байки, тем более, которые не помните. memcpy(), как минимум, не знает ведать не ведает ни о каких типах данных, поскольку работает исключительно с void *. По этой банальной причине он просто не способен различить float и не способен с ним работать иначе и неправильнее чем с любым другим типом.

Посмотрите там: http://www.alylab.eu/Subjects/STR91x/STR91x.htm "Команда memcpy((void*)dst_buf,(void*)src_buf2,4) даже при 0-ом уровне оптимизации может быть превращена в простую пересылку 32-х разрядных регистров..."

Я столкнулся с этим на LPC (кажется, это был 2138), но я уже знал тогда о потенциальной проблеме (из указанного источника) и обошел её именно "ручным" копированием. Перед этим коллеги столкнулись с "необъяснимыми глюками" (как они говорили) на ADUC7024, и сами обошли тем же способом. Я не разбирался, чей это глюк - ядра или кейла, ни желания, ни времени на это не было. Последнее время работаю с STM32 (именно в кейле) - этой проблемы не возникало.

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


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

кейла, ни желания, ни времени на это не было.

Явный чистейшей воды баг Кейла. Подлежит исправлению, что и сделали.

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


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

Явный чистейшей воды баг Кейла. Подлежит исправлению, что и сделали.

А как Вы прокомментируете это?

By default, ARM7 and ARM9 based microcontrollers do not allow un-aligned accesses to 16-bit and 32-bit data types.

http://www.keil.com/support/docs/3194.htm

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


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

Хм. А какой комментарий вы рассчитываете получить к изложению общеизвестной архитектурной особенности?

 

"Баг Кейла", как я понимаю, заключался в замене вызова memcpy на LDR/STR при высоком уровне оптимизации без контроля выравнивания.

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


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

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

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

Гость
К сожалению, ваш контент содержит запрещённые слова. Пожалуйста, отредактируйте контент, чтобы удалить выделенные ниже слова.
Ответить в этой теме...

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

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

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

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

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

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