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

 
 
2 страниц V   1 2 >  
Reply to this topicStart new topic
> новая проблема Оптимизация компилятора IAR
Alex ma
сообщение Mar 21 2007, 20:03
Сообщение #1


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

Группа: Новичок
Сообщений: 81
Регистрация: 9-08-06
Пользователь №: 19 445



Есть глобальная структура с 4 переменными которые используются во функции MiDI
По адресу 01F4.

Есть функция:
void MiDI(void){
while(1){
здесь код.
ret //выход
};
};

Данная функция вызывается из другого места по указателю на нее.
Выполнив нужные действия выходим из нее, потом возвращаемся обратно, при минимальной оптимизации все нормально вот асм:
4: void MiDI (void){
+000005EF: C020 RJMP PC+0x0021 Relative jump

Но стоит повысить оптимизацию так вот получается вот что асм
4: void MiDI (void){
+00000444: 93BA ST -Y,R27 Store indirect and predecrement
+00000445: 93AA ST -Y,R26 Store indirect and predecrement
+00000446: EFA4 LDI R26,0xF4 Load immediate
+00000447: E0B1 LDI R27,0x01 Load immediate
+00000448: C020 RJMP PC+0x0021 Relative jump

СОХРАНЯЕТ В СТЕКЕ ДАННЫХ регистры R27, R26!
Он думает цикл бесконечный а, я выхожу из него ! по ret (макрос), и происходит потеря данных, ведь я не восстанавливаю из стека данных.
Как компилятор отучить делать вот так
+00000444: 93BA ST -Y,R27 Store indirect and predecrement
+00000445: 93AA ST -Y,R26 Store indirect and predecrement
Go to the top of the page
 
+Quote Post
rezident
сообщение Mar 21 2007, 20:21
Сообщение #2


Гуру
******

Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882



Попробуйте выходить по break, а ret поставить после бесконечного цикла.
Цикл с выходом из середины (Википедия). Или см. K&R раздел 3.7. Оператор BREAK.
Go to the top of the page
 
+Quote Post
Alex ma
сообщение Mar 21 2007, 21:14
Сообщение #3


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

Группа: Новичок
Сообщений: 81
Регистрация: 9-08-06
Пользователь №: 19 445



Цитата(rezident @ Mar 21 2007, 22:21) *
Попробуйте выходить по break, а ret поставить после бесконечного цикла.
Цикл с выходом из середины (Википедия). Или см. K&R раздел 3.7. Оператор BREAK.


Решил проблему в лоб, спрятал работу со структурой в функцию processingDI();
Теперь функция с бесконечным циклом MiDI состоит только из переключателя switch и функций. Данных нет. :
void MiDI(void){ //
while(1){
processingDI();
switch(GetExeKey()){ //здесь считываем функцией переменную из структуры, которую //обрабатывает processingDI();
case DI_UP_FAN:{
OutFan(0);
Delay(2, MiDIPr);
UpDownFan(UP);
}
И т.д.

Асм при старте void MiDI(void)
4: void MiDI(void){
+0000045D: C020 RJMP PC+0x0021 Relative jump – переход на processingDI();
Теперь при максимальной оптимизации по скорости все нормально работает



Вот асм функции processingDI();
180: void processingDI(void){
+000001BB: 93BA ST -Y,R27 Store indirect and predecrement
+000001BC: 93AA ST -Y,R26 Store indirect and predecrement
181: key.currentKey = ReadDI();
Здесь еще код для работы сос структурой
: key.previousKey = key.currentKey;
+000001CD: 930C ST X,R16 Store indirect
190: };
+000001CE: 91A9 LD R26,Y+ Load indirect and postincrement
+000001CF: 91B9 LD R27,Y+ Load indirect and postincrement
+000001D0: 9508 RET Subroutine return
Go to the top of the page
 
+Quote Post
IgorKossak
сообщение Mar 22 2007, 12:45
Сообщение #4


Шаман
******

Группа: Модераторы
Сообщений: 3 064
Регистрация: 30-06-04
Из: Киев, Украина
Пользователь №: 221



Каков смысл городить ret (макрос), если стандартного return(); вполне достаточно для корректного выхода из любого цикла, да и из функции заодно?
Go to the top of the page
 
+Quote Post
Alex ma
сообщение Mar 22 2007, 19:04
Сообщение #5


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

Группа: Новичок
Сообщений: 81
Регистрация: 9-08-06
Пользователь №: 19 445



Цитата(IgorKossak @ Mar 22 2007, 14:45) *
Каков смысл городить ret (макрос), если стандартного return(); вполне достаточно для корректного выхода из любого цикла, да и из функции заодно?


Error[Pe118]: a void function may not return a value E:\Documens\Alex\Ìîè äîêóìåíòû\MUKS-01\MUKS01v02\task.c 10
это на return();
Go to the top of the page
 
+Quote Post
rezident
сообщение Mar 22 2007, 19:28
Сообщение #6


Гуру
******

Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882



Цитата(Alex ma @ Mar 22 2007, 21:04) *
Error[Pe118]: a void function may not return a value E:\Documens\Alex\Ìîè äîêóìåíòû\MUKS-01\MUKS01v02\task.c 10
это на return();

Все верно ошибку компилятор выдает. "Пустая" функция не может возвращать значение.
И все же стандартизованный способ прерывания цикла это оператор break. wink.gif В крайнем случае goto на метку вне цикла.
Go to the top of the page
 
+Quote Post
singlskv
сообщение Mar 23 2007, 00:17
Сообщение #7


дятел
*****

Группа: Свой
Сообщений: 1 681
Регистрация: 13-05-06
Из: Питер
Пользователь №: 17 065



Цитата(Alex ma @ Mar 22 2007, 19:04) *
Error[Pe118]: a void function may not return a value E:\Documens\Alex\Ìîè äîêóìåíòû\MUKS-01\MUKS01v02\task.c 10
это на return();

А что оно говорит если написать так return; // без скобочек ?

Цитата(rezident @ Mar 22 2007, 19:28) *
Все верно ошибку компилятор выдает. "Пустая" функция не может возвращать значение.
И все же стандартизованный способ прерывания цикла это оператор break. wink.gif В крайнем случае goto на метку вне цикла.

return это вполне валидный способ прекращения цикла,
а вот goto - не всегда
при использовании goto можно легко получать переполнение стека,
если его использовать необдуманно
Go to the top of the page
 
+Quote Post
zltigo
сообщение Mar 23 2007, 00:50
Сообщение #8


Гуру
******

Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244



Цитата(singlskv @ Mar 22 2007, 23:17) *
при использовании goto можно легко получать переполнение стека,
если его использовать необдуманно

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


--------------------
Feci, quod potui, faciant meliora potentes
Go to the top of the page
 
+Quote Post
singlskv
сообщение Mar 23 2007, 01:26
Сообщение #9


дятел
*****

Группа: Свой
Сообщений: 1 681
Регистрация: 13-05-06
Из: Питер
Пользователь №: 17 065



Цитата(zltigo @ Mar 23 2007, 00:50) *
Легко? Cтрашилка. Никакое необдуманоое и даже преднамеренное "плохое" использование goto не должно приводить к переполнению стека или каким либо другим деструктивным последствиям при сколь-нибудь пригодном для работы компиляторе языка высокого уровня. Потеря оптимальности кода может в некоторых "необдуманных" случаях действительно заметной.

goto не возвращает стек в исходное состояние, то есть если переменная была заведена
на стеке то стек будет расходоваться зазря до выхода из функции
ну и в принципе можно нарисовать такую ситуацию когда отведенного стека
просто не хватит
наверное на AVR это не очень актуальная проблемма, но например на
PC легко таким образом организовать переполнение
Go to the top of the page
 
+Quote Post
zltigo
сообщение Mar 23 2007, 09:07
Сообщение #10


Гуру
******

Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244



Цитата(singlskv @ Mar 23 2007, 00:26) *
goto не возвращает стек в исходное состояние, то есть если переменная была заведена
на стеке то стек будет расходоваться зазря до выхода из функции

А return, типа, возвращает, поскольку из функции выходит smile.gif.
Весь обьем стека под локальные переменные выделяется сразу и соответственно освобождается сразу а не по кусочкам. Другого поведения для компиляторов с языков высокого уровня не наблюдал ни разу. В поминаемом далее PC, вообще комады enter, leave для организации единого стекового фрейма заведены..
Цитата
ну и в принципе можно нарисовать такую ситуацию когда отведенного стека
просто не хватит

Легко, только goto к этому ни сном ни духом.
Цитата
наверное на AVR это не очень актуальная проблемма,

Мало памяти - мало проблем smile.gif
Цитата
но например на PC легко таким образом организовать переполнение

Каким таким "таким образом"???


--------------------
Feci, quod potui, faciant meliora potentes
Go to the top of the page
 
+Quote Post
Rst7
сообщение Mar 23 2007, 09:11
Сообщение #11


Йа моск ;)
******

Группа: Модераторы
Сообщений: 4 345
Регистрация: 7-07-05
Из: Kharkiv-city
Пользователь №: 6 610



Цитата(singlskv @ Mar 23 2007, 00:26) *
goto не возвращает стек в исходное состояние, то есть если переменная была заведена
на стеке то стек будет расходоваться зазря до выхода из функции


Дело в том, что это вас интересовать не должно. Компилятор (ИАР особенно) - он грамотный, он посмотрит, как все выполняется, и переменную уберет (или не уберет) из стека в нужный момент. Обычно этот момент - всегда выход из функции, т.к. постоянно дергать стек вперед/назад довольно накладно. Так что пользуйте goto, пользуйте return, break, все будет ок, а вот ассемблеровкий ret поперк - это неправильно в любом случае.

И вообще, правильно написаная программа должна компилироваться с макс. оптимизацией и работать. Если такого не происходит, ищите ошибки у себя (обычное дело - volatile забыли, вот как у вас - ret поперек всадили - это даже не ошибка, это... Ну не хочу плохие слова говорить wink.gif )


--------------------
"Практика выше (теоретического) познания, ибо она имеет не только достоинство всеобщности, но и непосредственной действительности." - В.И. Ленин
Go to the top of the page
 
+Quote Post
_Bill
сообщение Mar 23 2007, 13:25
Сообщение #12


Местный
***

Группа: Участник
Сообщений: 416
Регистрация: 18-04-06
Из: Челябинск
Пользователь №: 16 219



Цитата(Alex ma @ Mar 21 2007, 20:03) *
Есть глобальная структура с 4 переменными которые используются во функции MiDI
По адресу 01F4.

Есть функция:
void MiDI(void){
while(1){
здесь код.
ret //выход
};
};

Приведите весь код полностью, тогда все ясно будет.
Go to the top of the page
 
+Quote Post
singlskv
сообщение Mar 24 2007, 01:06
Сообщение #13


дятел
*****

Группа: Свой
Сообщений: 1 681
Регистрация: 13-05-06
Из: Питер
Пользователь №: 17 065



Цитата(zltigo @ Mar 23 2007, 09:07) *
А return, типа, возвращает, поскольку из функции выходит smile.gif.

конечно, return; всегда востанавливает указатель стека smile.gif
Цитата
Весь обьем стека под локальные переменные выделяется сразу и соответственно освобождается сразу а не по кусочкам. Другого поведения для компиляторов с языков высокого уровня не наблюдал ни разу.

Хорошо, сколько по вашему должен расходовать стека данных
следующий код на хорошем компиляторе ?
Код

void func()
{
  while(.......)
  {
     char str1[10];
     .................
     .................
  }

  while ( ........)
  {
    char str2[12];
    ..................
    ..................
  }
}

12 или 22 байта ?
а если будут множественное goto причем как вперед так и назад ?

Цитата
Мало памяти - мало проблем smile.gif

много регистров меньше проблем smile.gif
Go to the top of the page
 
+Quote Post
Rst7
сообщение Mar 24 2007, 10:33
Сообщение #14


Йа моск ;)
******

Группа: Модераторы
Сообщений: 4 345
Регистрация: 7-07-05
Из: Kharkiv-city
Пользователь №: 6 610



Цитата
12 или 22 байта ?а если будут множественное goto причем как вперед так и назад ?

Если без goto - иар постелит 12 байт, если будут goto - 22. Не волнуйтесь за компилятор.


--------------------
"Практика выше (теоретического) познания, ибо она имеет не только достоинство всеобщности, но и непосредственной действительности." - В.И. Ленин
Go to the top of the page
 
+Quote Post
xemul
сообщение Mar 24 2007, 11:29
Сообщение #15



*****

Группа: Свой
Сообщений: 1 928
Регистрация: 11-07-06
Пользователь №: 18 731



Цитата(singlskv @ Mar 24 2007, 01:06) *
Хорошо, сколько по вашему должен расходовать стека данных
следующий код на хорошем компиляторе ?
12 или 22 байта?
а если будут множественное goto причем как вперед так и назад ?

Собственно Rst7 уже ответил. Позволю добавить, что даже при определении переменной внутри оператора место на стеке под нее будет выделено при входе в функцию (оптимизатор может, конечно, затолкнуть переменную и в регистры, но мы сейчас не о том).
Без оптимизации на стеке будет по-любому выделено 22 байта, а уж что оптимизатор сможет наоптимизировать... Это к оптимизаторуsmile.gif
Go to the top of the page
 
+Quote Post

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

 


RSS Текстовая версия Сейчас: 18th July 2025 - 20:45
Рейтинг@Mail.ru


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