|
Принудительное размещение локальной переменной в стеке, Компилятор IAR EW3.30A (MSP430F449) |
|
|
|
Feb 12 2007, 17:31
|
Участник

Группа: Участник
Сообщений: 27
Регистрация: 21-10-05
Пользователь №: 9 922

|
Добрый день, уважаемые коллеги! Компилятор размещает локальные переменные, определенные в теле функции либо в регистрах, либо в стеке. Код void Func(char Var1) { char Var2; ... Var2 = Var1; ... } Если переменная 1 или 2-х байтная, то скорее всего компилятор ее разместит в регистрах. А мне нужно, чтобы он принудительно разместил ее (Var2) в сегменте стека. А еще лучше, если сразу Var1 будет размещаться в стеке. Как мне его это заставить сделать?
|
|
|
|
|
Feb 12 2007, 18:13
|

Местный
  
Группа: Свой
Сообщений: 426
Регистрация: 20-01-05
Из: Зеленоград
Пользователь №: 2 070

|
Цитата(Petrooo @ Feb 12 2007, 17:31)  А мне нужно, чтобы он принудительно разместил ее (Var2) в сегменте стека. Вызвать подпрограмму, которой передать в качестве аргумента адрес Var2. void dummy(int *p) { } void func(void) { int Var2; dummy(&var2); }
|
|
|
|
|
Feb 12 2007, 18:55
|
Гуру
     
Группа: Свой
Сообщений: 2 702
Регистрация: 14-07-06
Пользователь №: 18 823

|
Цитата(vmp @ Feb 12 2007, 19:13)  Вызвать подпрограмму, которой передать в качестве аргумента адрес Var2. Компилятор может точно так же поместить в регистры указатель. Поэтому встает вопрос о целях автора. Какая разница, где переменная, указатель и прочее? По большому счету задай оптимизацию - по коду или быстродействию и отдайся компилятору, закрыв глаза.
--------------------
Уходя, оставьте свет...
|
|
|
|
|
Feb 12 2007, 19:21
|

Местный
  
Группа: Свой
Сообщений: 426
Регистрация: 20-01-05
Из: Зеленоград
Пользователь №: 2 070

|
Цитата(Dog Pawlowa @ Feb 12 2007, 18:55)  Цитата(vmp @ Feb 12 2007, 19:13)  Вызвать подпрограмму, которой передать в качестве аргумента адрес Var2.
Компилятор может точно так же поместить в регистры указатель. В вызываемой подпрограмме - да. А в вызывающей переменная будет создана на стеке, ибо регистры (по крайней мере в данной архитектуре) адреса не имеют.
|
|
|
|
|
Feb 12 2007, 20:50
|
Гуру
     
Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882

|
Цитата(vmp @ Feb 12 2007, 21:21)  Цитата(Dog Pawlowa @ Feb 12 2007, 18:55)  Цитата(vmp @ Feb 12 2007, 19:13)  Вызвать подпрограмму, которой передать в качестве аргумента адрес Var2.
Компилятор может точно так же поместить в регистры указатель. В вызываемой подпрограмме - да. А в вызывающей переменная будет создана на стеке, ибо регистры (по крайней мере в данной архитектуре) адреса не имеют. Это зависит от компилятора. В IAR, например, передача параметров функции производится через регистры R15-R12. Если же размер параметров функции превышает совокупный размер этих регистров то тогда да, параметры передаются через стек.
|
|
|
|
|
Feb 12 2007, 23:07
|

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

|
Цитата(rezident @ Feb 12 2007, 21:31)  Извиняюсь, невнимательно прочитал сообщения топика. Похоже я тоже невнимательно читал. Если передавать Var1 прямо в стеке, можно попробовать что-то вроде Код typedef struct { char Value; } char_struct_t;
void Func(char_struct_t Var1) По идее структура должна передаваться через стек, но никто не гарантирует, что оптимизатор не окажется слишком умным и не решит, что такая структура влезет и в регистр.
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Feb 13 2007, 15:15
|
Участник

Группа: Участник
Сообщений: 27
Регистрация: 21-10-05
Пользователь №: 9 922

|
ссори за долгое отсутствие Цитата(Dog Pawlowa @ Feb 13 2007, 10:37)  Ребят, ну давайте не пытаться быть умнее компилятора! :-) Я вот прикинул.... Я пишу программы для микропроцессоров и микроконтроллеров 22 года, из них 16 последних на ЯВУ, и ни разу не задумывался, как передаются параметры в функцию. Пишу для микропроцессоров менее 22 лет, но вот пришлось задуматься где передаются параметры  Есть девайс (ККМ), в котором пользователь иногда запускает "критический" процесс с "критическими" секциями исполнения программы. Например печать журнала чеков. Если при печати вырубается питание, то по включении ККМ должна продолжить печать с того чека, на котором прервалась печать. Причем все накопления по предыдущим чекам не должны пропасть. Что я делаю: 1. при выключении питания по прерыванию сохраняю адрес критической секции (печать одного чека) 2. ее параметры - номер чека и прочее 3 и стек в котором лежат локальные переменные По включению девайс: 1. проходит все начальные тесты и прочее 2. смотрит была ли "свертка" 3. если была, восстанавливаю адрес верхушки стека Код asm ("MOV.W &SVERTKA+2, SP"); и его содержимое 4. перехожу по адресу Код asm ("BR &SVERTKA+4"); Теперь, полагаю, уважаемой публике стало понятно, почему собственно встал вопрос топика. Локальные переменные, которые в стеке свои значения "сохранили" от старого сеанса, а которые в регистрах - похерились! Можно, конечно, при свертке еще и регисты сохранять, но думал, что можно забороть умный копмилятор еще более умной директивой или ключевым словом, которые я не нарыл  Пока решил проблему так: чтобы меньше переделывать код тупо "умыл" компилятор, объявив Var2 8-ым байтным long long'ом (в регистры запухнуть это копмилятору оказалось слабо)! Кстати, если мне не изменяет память, я уже как то поднимал эту тему на форуме, было бы интересно узнать, кто как сворачивается-разворачивается по выкл/вкл в аналогичных ситуациях.
|
|
|
|
|
Feb 13 2007, 16:08
|

Знающий
   
Группа: Свой
Сообщений: 630
Регистрация: 2-08-05
Пользователь №: 7 294

|
Цитата(Petrooo @ Feb 13 2007, 16:15)  ссори за долгое отсутствие Цитата(Dog Pawlowa @ Feb 13 2007, 10:37)  Ребят, ну давайте не пытаться быть умнее компилятора! :-) Я вот прикинул.... Я пишу программы для микропроцессоров и микроконтроллеров 22 года, из них 16 последних на ЯВУ, и ни разу не задумывался, как передаются параметры в функцию.
Пишу для микропроцессоров менее 22 лет, но вот пришлось задуматься где передаются параметры  Есть девайс (ККМ), в котором пользователь иногда запускает "критический" процесс с "критическими" секциями исполнения программы. Например печать журнала чеков. Если при печати вырубается питание, то по включении ККМ должна продолжить печать с того чека, на котором прервалась печать. Причем все накопления по предыдущим чекам не должны пропасть. Что я делаю: 1. при выключении питания по прерыванию сохраняю адрес критической секции (печать одного чека) 2. ее параметры - номер чека и прочее 3 и стек в котором лежат локальные переменные По включению девайс: 1. проходит все начальные тесты и прочее 2. смотрит была ли "свертка" 3. если была, восстанавливаю адрес верхушки стека Код asm ("MOV.W &SVERTKA+2, SP"); и его содержимое 4. перехожу по адресу Код asm ("BR &SVERTKA+4"); Теперь, полагаю, уважаемой публике стало понятно, почему собственно встал вопрос топика. Локальные переменные, которые в стеке свои значения "сохранили" от старого сеанса, а которые в регистрах - похерились! Можно, конечно, при свертке еще и регисты сохранять, но думал, что можно забороть умный копмилятор еще более умной директивой или ключевым словом, которые я не нарыл  Пока решил проблему так: чтобы меньше переделывать код тупо "умыл" компилятор, объявив Var2 8-ым байтным long long'ом (в регистры запухнуть это копмилятору оказалось слабо)! Кстати, если мне не изменяет память, я уже как то поднимал эту тему на форуме, было бы интересно узнать, кто как сворачивается-разворачивается по выкл/вкл в аналогичных ситуациях. Скажите, а как Вы успеваете сохранится? Ведь у вас термопринтер потребляет немало... Вы уверены, что Z или X отчет надо продолжать печатать с того же места, а не заново? А для того чтобы данные передавались как вам надо, может проще эти процедуры на ассемблере написать?
--------------------
летаю на пепелаце...
|
|
|
|
|
Feb 13 2007, 16:34
|
Гуру
     
Группа: Свой
Сообщений: 2 702
Регистрация: 14-07-06
Пользователь №: 18 823

|
Цитата(Petrooo @ Feb 13 2007, 16:15)  Кстати, если мне не изменяет память, я уже как то поднимал эту тему на форуме, было бы интересно узнать, кто как сворачивается-разворачивается по выкл/вкл в аналогичных ситуациях. Ну, теперь понятно 1. Использую измерение напряжения до стабилизатора, чтобы вовремя отключить все энергопотребляющие узлы, чтобы контроллер насладился сохранением статистики в ЕЕПРОМ. 2. Чтобы статистика не попортилась, делаю это только только в критических местах. 3. Реализую алгоритм прибора в виде массива функций, а текущим индексом массива является глобальная переменная "статус". 4. Не использую стек для таких функций, но, чтобы памяти хватило, использую одни и те же глобальные переменные в каждой функции, переопределяя их каждый раз в целях соответствия имени физическому смыслу (комментарии не пишу, компенсируя это именами). Собственно, все... После сброса контроллер инициализируется и сразу выходит на ту функцию, где он был. Были мысли про стек, но больше риск влететь куда-то не туда, и возникает зависимость от платформы, а я это не люблю - контроллеры приходят и уходят, а люди остаются  Да, еще... (прочитал, что написал ув. Rezident) - пп 3 и 4 нужны , если нужно быстро перезапуститься (например, помехи жуткие и проч.) Если обычный процесс выключения, пусть нештатного - можно ведь сохраниться в EEPROM без проблем - т.е. пп. 1 и 2 достаточно.
--------------------
Уходя, оставьте свет...
|
|
|
|
|
Feb 13 2007, 17:08
|
Местный
  
Группа: Участник
Сообщений: 416
Регистрация: 18-04-06
Из: Челябинск
Пользователь №: 16 219

|
Цитата(Petrooo @ Feb 12 2007, 17:31)  Добрый день, уважаемые коллеги! Компилятор размещает локальные переменные, определенные в теле функции либо в регистрах, либо в стеке. Код void Func(char Var1) { char Var2; ... Var2 = Var1; ... } Если переменная 1 или 2-х байтная, то скорее всего компилятор ее разместит в регистрах. А мне нужно, чтобы он принудительно разместил ее (Var2) в сегменте стека. А еще лучше, если сразу Var1 будет размещаться в стеке. Как мне его это заставить сделать? Попробуйте объявить ее как auto. А вообще, компилятор достаточно "умный". Он должен "увидеть" ссылку на адрес переменной и разместить ее в стеке.
|
|
|
|
|
Feb 13 2007, 17:32
|
Участник

Группа: Участник
Сообщений: 27
Регистрация: 21-10-05
Пользователь №: 9 922

|
Цитата(rezident @ Feb 13 2007, 15:30)  ИМХО проще иметь глобальную структуру глобальных переменных. Тогда критические данные можно разместить последовательно (рядом) в такой структуре. Сохранять их в таком случае проще - всегда известно где они лежат и каков размер критической секции данных. "Рубанули питание" для случая применения MSP430 звучит несколько странно. Если есть детектор "вырубания", то конденсатора на две-три сотни мкФ или ионистора (или литиевой батарейки на худой конец) вполне хватит чтобы завершить сохранение критически важных данных. Как говориться, кто в лес, а кто по дрова!  Хм, разве была речь о том, что чего там не хватит для сохранения чего то??? Агрументы самой свертки разумеется универсальны и лежат в глобальной структуре. Но вот после того как куда-то вернулись и продолжаем рабуту дальше в "штатном режиме" по функционалу, тут уже в разных функциях по разному и универсальными глобальными структурами не опишешь. Не универсальный механизм получается, бестолково. Цитата "Рубанули питание" для случая применения MSP430 звучит несколько странно. Абсолютно верно, но это только мы знаем, что проц полюбому на батарейке и что тумблером аппаратно вырубается только принтер и подсветка индикатора, а проц ушел в LPM3  Цитата(АДИКМ @ Feb 13 2007, 16:08)  Скажите, а как Вы успеваете сохранится? Ведь у вас термопринтер потребляет немало... Вы уверены, что Z или X отчет надо продолжать печатать с того же места, а не заново? Термопринтер, индикатор разумеется вырубается сразу по тумблеру. Коллега, не путайте: X/Z-отчет - это одно, а КЛ (контрольная лента) - это другое. Отчеты по свертке перепечатываются заново, а печать КЛ продолжается с того чека, где зарубились (чек перепечетывается заново). Но это уже заморочки ТУ на девайс Цитата А для того чтобы данные передавались как вам надо, может проще эти процедуры на ассемблере написать? Эк, Вы куда, коллега, хватили!
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|