Почему avr-gcc пытается сохранить состояние регистра при вызове main ()? - PullRequest
2 голосов
/ 15 июля 2010

Функция main () в программе avr-gcc сохраняет состояние регистра в стеке, но когда среда выполнения вызывает его, я понимаю, что на микроконтроллере возвращать нечего.Это пустая трата оперативной памяти?Как предотвратить сохранение этого состояния?

Ответы [ 5 ]

6 голосов
/ 15 июля 2010

Как компилятор может быть уверен, что вы не собираетесь рекурсивно вызывать main ()?

4 голосов
/ 15 июля 2010

Все дело в стандарте C.

Ничто не запрещает вам выходить из основного режима.Вы можете не делать этого в своей программе, но другие могут делать это.

Кроме того, вы можете зарегистрировать обработчики очистки с помощью функции atexit времени выполнения.Этим функциям требуется определенное состояние регистра для правильного выполнения, и единственный способ гарантировать это - сохранить и восстановить регистры вокруг main.

Это может быть даже полезно сделать: я не знаю оAVR, но другие микроконтроллеры могут переходить в состояние низкого энергопотребления, когда они закончили свою работу и ожидали сброса.Делать это из обработчика очистки может быть хорошей идеей, потому что этот обработчик вызывается, если вы выходите из main обычным способом и (насколько я сейчас), если ваша программа прерывается с помощью сигнала kill.

3 голосов
/ 16 июля 2010

Скорее всего, main просто скомпилирован так же, как и стандартная функция.В C это в значительной степени необходимо, потому что вы можете вызывать его откуда-то.

Обратите внимание, что в C ++ рекурсивно вызывать main, поэтому компилятор c ++ мог бы оптимизировать это больше.Но в C, как указано в вашем вопросе, законно (если это плохая идея) вызывать main рекурсивно, поэтому ее нужно компилировать так же, как и любую другую функцию.

1 голос
/ 25 августа 2010

В моих тестах с avr-gcc 4.3.5 он только сохраняет регистры, если не сильно оптимизирует. Нормальные уровни (-Os или -O2) приводят к оптимизации инструкций нажатия. Далее можно указать в объявлении функции, что оно не вернется с __attribute__((noreturn)). Также полезно провести полную оптимизацию программы с -fwhole-program.

Исходный код в avr-libc использует call для перехода к main, поскольку указано, что main может возвратиться, а затем переходит к выходу (который объявлен как noreturn и, следовательно, не генерирует вызов). Вы можете связать свой вариант, если считаете, что это слишком много. exit (), в свою очередь, просто отключает прерывания и входит в бесконечный цикл, эффективно останавливая вашу программу, но не экономя энергию. Это четыре инструкции и два байта служебной памяти стека, если ваш main () никогда не возвращается или не вызывает exit ().

1 голос
/ 04 августа 2010

Как предотвратить сохранение этого состояния?

Единственное, что вы можете сделать, это написать собственную подпрограмму C-Startup. Это означает, что нужно возиться с ассемблером, но затем вы можете перейти к main (), а не просто вызывать его.

...