2

avr-gccプログラムのmain()関数は、レジスタの状態をスタックに保存しますが、ランタイムがそれを呼び出すと、マイクロコントローラーでは何も戻らないことがわかります。これはRAMの無駄ですか?この状態の保存をどのように防ぐことができますか?

4

5 に答える 5

6

main() を再帰的に呼び出さないことをコンパイラーはどのように確認できますか?

于 2010-07-14T21:21:16.733 に答える
4

それはすべてC標準に関するものです。

ある時点でメインを終了することを禁止するものは何もありません。あなたは自分のプログラムでそれをしないかもしれませんが、他の人はそれをするかもしれません。

atexitさらに、ランタイム関数を介してクリーンアップ ハンドラを登録できます。これらの関数を適切に実行するには、レジスタの状態を定義する必要があります。これを保証する唯一の方法は、main 周辺のレジスタを保存して復元することです。

AVR についてはわかりませんが、他のマイクロコントローラーは、仕事が終わってリセットを待っているときに、低電力状態になることがあります。これを cleanup-handler から行うのは良い考えかもしれません。なぜなら、通常の方法で main を終了し、 (今のところ) kill シグナルによってプログラムが中断された場合に、このハンドラが呼び出されるからです。

于 2010-07-14T20:56:37.937 に答える
3

ほとんどの場合、mainは標準関数と同じようにコンパイルされます。Cでは、どこかから呼び出す可能性があるため、ほとんど必要です。

C ++では、mainを再帰的に呼び出すことは違法であるため、C++コンパイラはこれをさらに最適化できる可能性があることに注意してください。しかし、あなたの質問が述べたようにCでは、mainを再帰的に呼び出すことは合法であるため(悪い考えの場合)、他の関数と同じ方法でコンパイルする必要があります。

于 2010-07-16T08:22:45.587 に答える
1

この状態の保存をどのように防ぐことができますか?

できることは、独自の C-Startup ルーチンを作成することだけです。これはアセンブラをいじることを意味しますが、main() を呼び出すだけでなく、JUMP で main() に移動できます。

于 2010-08-04T19:05:04.203 に答える
1

In my tests with avr-gcc 4.3.5, it only saves registers if not optimizing much. Normal levels (-Os or -O2) cause the push instructions to be optimized away. One can further specify in a function declaration that it will not return with __attribute__((noreturn)). It is also useful to do full program optimization with -fwhole-program.

The initial code in avr-libc does use call to jump to main, because it is specified that main may return, and then jumps to exit (which is declared noreturn and thus generates no call). You could link your own variant if you think that is too much. exit() in turn simply disables interrupts and enters an infinite loop, effectively stopping your program, but not saving any power. That's four instructions and two bytes of stack memory overhead if your main() never returns or calls exit().

于 2010-08-25T04:40:01.733 に答える