реклама на сайте
подробности

 
 
2 страниц V  < 1 2  
Reply to this topicStart new topic
> Линкер: Расположение переменной, как расположить локальную переменную в памяти, а не в регистре?
mdmitry
сообщение Jun 22 2012, 11:14
Сообщение #16


Начинающий профессионал
*****

Группа: Свой
Сообщений: 1 215
Регистрация: 25-10-06
Из: СПб
Пользователь №: 21 648



Цитата(Кирилл__ @ Jun 22 2012, 10:27) *
Код-то другой, но отличается лишь позиционированием некоторых локальных переменных. Я верю, что компилятор правильно делает свое дело. wink.gif

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

Цитата
Справедливо, конечно: этот подход не выявляет все баги. Но он помогает выявить баги, не зависящие от уровня оптимизации, а это уже очень хорошо.

Конечно лучше чем ничего, но остануться неочевидные баги.


--------------------
Наука изощряет ум; ученье вострит память. Козьма Прутков
Go to the top of the page
 
+Quote Post
Sergey_Aleksandr...
сообщение Sep 28 2012, 08:15
Сообщение #17


Частый гость
**

Группа: Свой
Сообщений: 168
Регистрация: 8-10-08
Из: РФ Смоленск
Пользователь №: 40 764



Столкнулся с аналогичной проблемой: IAR 6.30.4, STM32F1xx платформа. На Medium уровне оптимизации переменная из R0
CODE

void RunUpdatePackParser(void)
{
bool isSoftwareError = false;
unsigned long CRC32;
/*static*/ unsigned int ResetAddr = 0;

// Явно привести передающий буфер к структуре принятого пакета
tRun_Update_Pack_Struct * pPack = (tRun_Update_Pack_Struct *)Wiz_RxBuf;

// Поле контрольной суммы
if (pPack->Mask[0] & (1<<7))
{
// Вычислить контрольную сумму все буферной области Flash-памяти
CRC32 = CalcCRC32((unsigned char*)LOADER_BUF_START, LOADER_BUF_SIZE);
if (pPack->CheckSum != CRC32)
isSoftwareError = true;

// Проверить байты [4..7] новой прошивки. Это адрес ResetVector +1(особенности Thumb). Должен попадать в ROM
/*unsigned int*/ ResetAddr = *(unsigned int*)(LOADER_BUF_START+4);
if ( (ResetAddr < ROM_START) || (ResetAddr > ROM_END) )
isSoftwareError = true;

if ( (ResetAddr & 0x00000003) != 1) //Адрес кратен 4, +1, т.е. 2 младших бита 0b0..01.
isSoftwareError = true;


if (isSoftwareError)
StatusReg |= RUN_UPDATE_SW_ERROR;
else
{
// Установить в Option Byte Data1 ключ "Переписать прошивку" (учесть мизерную вероятность аппаратной ошибки)
if (WriteOptionByte((unsigned int)&OB->Data0, RUN_UPDATE_KEY) != 0)
{
StatusReg |= RUN_UPDATE_HW_ERROR;
}
// Запустить механизм входа в загрузчик
else
{
StatusReg |= UPDATER_RUN;
DoSomething();
}
}

}
// Сформировать пакет-ответ со статусной информацией
TransmitStPack();
}



Программа ведёт себя некорректно. Пошагал отладчиком, строку "unsigned int ResetAddr = *(unsigned int*)(LOADER_BUF_START+4);" пропускает (привык я переменные объявлять по месту их первого использования). Переменная в отладчике значится как <unavailable>.
Унёс объявление ResetAddr в начало фунции, вручную проинициализировал 0. Результат - переменная помещается в R0. Отладчик всё-равно не шагает на строку "ResetAddr = *(unsigned int*)(LOADER_BUF_START+4);".
Пометил её как static. При этом отладка падает на строке "if ( (ResetAddr < ROM_START) || (ResetAddr > ROM_END) )", где макросы ROM_START и ROM_END - числа объявленные в одном из заголовочных файлов. Стек раздул с 1кБайта до 4. Вот сижу и голову ломаю: поставить более свежий IAR или всё-таки моя ошибка в коде.
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Sep 28 2012, 08:38
Сообщение #18


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



QUOTE (Sergey_Aleksandrovi4 @ Sep 28 2012, 11:15) *
Отладчик всё-равно не шагает на строку "ResetAddr = *(unsigned int*)(LOADER_BUF_START+4);".
Возможно потому что он встроил эту операцию в следующие команды? Надо смотреть ассемблерный код и шагать отладчиком по нему. Вполе возможно что он знает значение, которое должно грузиться в ResetAddr на этапе компиляции и в нужный момент загружает в регистр константу?. А если вы хотите, чтобы он таки считывал его несмотря ни на что - пришите ResetAddr = *(unsigned int volatile *)(LOADER_BUF_START+4), а еще лучше ResetAddr = *(unsigned int volatile const *)(LOADER_BUF_START+4);

Что значит "отладка падает на строке"?


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
Sergey_Aleksandr...
сообщение Sep 28 2012, 09:23
Сообщение #19


Частый гость
**

Группа: Свой
Сообщений: 168
Регистрация: 8-10-08
Из: РФ Смоленск
Пользователь №: 40 764



Под "отладка падает на строке" имел в виду то, находясь на строке Х и вызывая "Step Into" отладчик переходил не к следующей команде, а улетал неизвестно куда. Расставив брэкпойнты выяснил, что со строки "ResetAddr = *(unsigned int*)(LOADER_BUF_START+4)" отладчик перескакивал сразу к условному оператору "if (isSoftwareError)". Но, открыл окно дизасемблера, стал шагать по асм-командам. Все они исправно выполняются. Видимо есть нюансы при отладке при ненулевом уровне оптимизации.
"ResetAddr = *(unsigned int*)(LOADER_BUF_START+4);" выполняется правильно (LOADER_BUF_START находится за границами указанными линкеру), volatile добавлю для надёжности, спасибо за совет.
Глюк ушёл и не появляется даже если я теперь убираю квалификатор static при объявлении переменной ResetAddr. Не понятно из-за чего возникла ошибка, почему она пропала и, ГЛАВНОЕ, ожидать ли её появление вновь.
asm для STM32 не знаю, вот листинг на всякий случай.
CODE

ResetAddr = *(unsigned int*)(LOADER_BUF_START+4);
if ( (ResetAddr < ROM_START) || (ResetAddr > ROM_END) )
isSoftwareError = true;

if ( (ResetAddr & 0x00000003) != 1) //Адрес кратен 4, +1, т.е. 2 младших бита 0b0..01.
isSoftwareError = true;


if (isSoftwareError)
StatusReg |= RUN_UPDATE_SW_ERROR;

.......................
ResetAddr = *(unsigned int*)(LOADER_BUF_START+4);
??RunUpdatePackParser_2:
0x8000a14: 0x6870 LDR R0, [R6, #0x4]
if ( (ResetAddr < ROM_START) || (ResetAddr > ROM_END) )
0x8000a16: 0x4932 LDR.N R1, ??DataTable4_14 ; 0xf7ffe000 (-134225920)
0x8000a18: 0x1809 ADDS R1, R1, R0
0x8000a1a: 0xf5b1 0x3ff0 CMP.W R1, #122880 ; 0x1e000
0x8000a1e: 0xd300 BCC.N ??RunUpdatePackParser_3 ; 0x8000a22
isSoftwareError = true;
0x8000a20: 0x2501 MOVS R5, #1
if ( (ResetAddr & 0x00000003) != 1) //дрес кратен 4, +1, т.е. 2 младших бита 0b0..01.
??RunUpdatePackParser_3:
0x8000a22: 0xf000 0x0003 AND.W R0, R0, #3
0x8000a26: 0x2801 CMP R0, #1
0x8000a28: 0xd000 BEQ.N ??RunUpdatePackParser_4 ; 0x8000a2c
isSoftwareError = true;
0x8000a2a: 0x2501 MOVS R5, #1
if (isSoftwareError)
??RunUpdatePackParser_4:
0x8000a2c: 0x2d00 CMP R5, #0
0x8000a2e: 0xd004 BEQ.N ??RunUpdatePackParser_5 ; 0x8000a3a
.......................
Go to the top of the page
 
+Quote Post
scifi
сообщение Sep 28 2012, 11:13
Сообщение #20


Гуру
******

Группа: Свой
Сообщений: 3 020
Регистрация: 7-02-07
Пользователь №: 25 136



Цитата(Sergey_Aleksandrovi4 @ Sep 28 2012, 13:23) *
Видимо есть нюансы при отладке при ненулевом уровне оптимизации.

При ненулевом уровне оптимизации нюансы были всегда. Среди прочего: сокращается время жизни переменных (компилятор старается по максимуму использовать регистры), код может стать нелинейным (одни куски кода могут уйти за ненадобностью, вторые - выделиться в общие подпрограммы, третьи - переместиться, циклы могут разворачиваться или сворачиваться, inline-подстановка и т.д.). Ну и вскрывается целый класс багов, зависящих от уровня оптимизации. Поэтому полезно уметь читать листинг дизассемблера.

Цитата(Sergey_Aleksandrovi4 @ Sep 28 2012, 13:23) *
Глюк ушёл и не появляется даже если я теперь убираю квалификатор static при объявлении переменной ResetAddr. Не понятно из-за чего возникла ошибка, почему она пропала и, ГЛАВНОЕ, ожидать ли её появление вновь.

В отладке хорошо помогает научный метод познания: нужно отделять мнения от фактов, стараться собирать объективные данные, не смешивать в кучу разные эффекты.
Go to the top of the page
 
+Quote Post

2 страниц V  < 1 2
Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 29th August 2025 - 17:23
Рейтинг@Mail.ru


Страница сгенерированна за 0.01356 секунд с 7
ELECTRONIX ©2004-2016