プロが教えるわが家の防犯対策術!

 ルネサスHEWのサンプル・プログラムを見ると、I/Oの初期化、Bセクションのクリア、DセクションからRセクションへのコピーなどを行ってから、main関数に飛んでいます。

 これらの初期化はメイン関数の中で行うべきだと思っているのですが、どうなんでしょう。

 パソコンでexeファイルを実行した場合、mainに飛ぶと思っているのですが、初期化プログラムに飛んでからmainに飛ぶのでしょうか。

 宜しくお願いします。

A 回答 (9件)

>今までの回答から、パソコンにおいてユーザーが作るのはmein以降と思ったのですが、今回の回答ではスタートアップルーチンもユーザが作ると思うのですが。



昔は全部自分で書いてましたが(スタートアップの簡単なサンプルみたいな物は開発キットに付属してました)、HEWなど統合環境ではマイコンの種類に合わせてHEWがスタートアップを用意してくれますね。
ただ、それを無視して自分のスタートアップを書く事も可能だと思いますが書く必要があるのは疑問です。別に任せても問題ないのでは?

環境によりますが、組み込み系ならスタートアップは自分で用意する場合も多々あります。HEWやWinアプリなどの統合環境やCコンパイラなどは自動的にスタートアップを用意してくれます。
例えばH8でもHEWを使わずにgccを使うならスタートアップを用意する必要がありますね。
http://tokyo-ct.net/usr/kosaka/for_students/H8/3 …
    • good
    • 0
この回答へのお礼

 何度も回答有り難う御座います。

 いろいろと有り難う御座います。

 C言語で出来ないスタックポインタの設定などはスタートアップで行うにしても、C言語で出来る事はmain関数の中で行った方が良いんじゃないかなと思っています。

 サンプルを見ると私の考えと違うので、一般的にはどのように行われているのかと思い質問しました。

 みなさんの回答を見て、参考になりました。有り難う御座いました。

お礼日時:2009/10/27 12:06

回答者の中にもよく分かっていない人がいつようですが....



まず、リセットがかかったときにどのアドレスからプログラムを実行するかはCPUによって異なります.
HEWということですが、H8やSHであれば0番地にリセットベクタを格納しますので、そのアドレスから実行されることになります。M16CやM32Cであれば、アドレス空間の最後にリセットベクタを格納します。MIPSなんかは0xbfc00000番地から実行します。このように、CPUによって事情が異なります。

次に、スタートアップの話ですが、Cの規格では、プログラム開始位置が実行される時点では、静的記憶域期間を持つオブジェクトの初期化が完了していなければなりません。これはフリースタンディング環境(OSのない環境)でも同じです。ですので、スタートアップでそうした初期化を行います。
スタートアップでは、静的なオブジェクトの初期化以外に、DRAMやキャッシュの初期化など、ハードウェアの初期化も行います。スタートアップは処理系の一部ですので、そうした処理を書くのは処理系を構築する作業になります。
モニタプログラムなどが存在するシステムでは、こうした処理をモニタがやってくれることもありますが、ハードウェアが変わるたびにスタートアップを書き換える必要がありますので、誰がやるかは別として、ポーティングは組込みでは必須の作業となります。
    • good
    • 0
この回答へのお礼

 いつも回答有り難う御座います。

>Cの規格では、プログラム開始位置が実行される時点では、静的記憶域期間を持つオブジェクトの初期化が完了していなければなりません。

 そのような規格が有るのなら、納得出来ます。

 I/Oの初期化はどうでしょう。組み込みプログラムの説明によると、「ノイズによってI/0の設定が変わるおそれがある。信頼性を上げるため、定期的に再設定した方が良い。」となっています。

 I/Oの初期化は、main関数の中で行うのがスマートかなと思うのですが。

お礼日時:2009/10/27 11:47

>C言語では初期値を持たない変数をゼロクリアする約束が有りますが、それはOSが行ってくれて、プログラム開発者は意識しなくていいのでしょうか。


それは言語毎のお約束で、OSがやるべきことではありません。スタートアップルーチンの役割です。
セクションをメモリ空間に展開するのはOSの役割ですが、OSの無い組み込み環境ならスタートアップルーチンやブートローダがその役目を負う必要があります。

Windows実行ファイル「EXE」の謎に迫る
http://codezine.jp/article/corner/61
    • good
    • 0
この回答へのお礼

 再度回答有り難う御座います。

 「http://codezine.jp/article/corner/61​」は参考になりました。

 今までの回答を見て、スタートアップルーチンはOSの役目だと思いました。
 OSでないとすると、Cコンパイラが自動的に作ってくれる物なのでしょうか。初期値を持たない変数をゼロクリアするスタートアップルーチンはコンパイラが自動的に生成出来るしょうが、I/Oの初期化はユーザが作らないと無理だと思います。

 今までの回答から、パソコンにおいてユーザーが作るのはmein以降と思ったのですが、今回の回答ではスタートアップルーチンもユーザが作ると思うのですが。

お礼日時:2009/10/26 17:42

main() は、「ユーザーが書いたプログラム


のうち、一番最初に実行されるもの」です。
これ以前の処理は、その環境(OS とか)に
応じて、処理系が勝手にプログラムをくっつ
けます。
これが、スタートアップとか呼ばれるものに
なります。

例えば、Cでは、「初期値が省略されたグロー
バル変数は暗黙のうちに、0 で初期化される」
という決まりがあります。
これを実現するためには、main() より先に、
「グローバル変数をゼロで初期化する」プログ
ラムが動作しなければなりません。

そして、そのプログラムは(暗黙の初期化なので
)ユーザーが書いたものではありません。
こういうものが、main() の実行前に行われます。

Hew が main() の実行前に行っている初期化は
「RAM 領域全体を一括してゼロクリアする」と
言うレベルの初期化です。
(上で書いたような、グローバル変数の暗黙の
初期化もこのあたりで実現できる)

一方でC言語で、「実装している RAM領域全
体」を、知る方法はありません。
C言語(というか、ユーザーの書いたプログラ
ム)では、「使うつもりの変数を、適切に初期
化する」ということを行うべきです。

これが、main() の実行に先立って、暗黙のう
ちに実行される初期化と、ユーザーが書く初
期化の違いです。

さて、CPUは、リセットされると、その
CPUに決まった方法で、プログラムの実行
を開始します。
(必ずしも、ゼロ番地から実行を開始するわ
けではありません)

この位置には、スタートアップルーチンが来る
ケースが多いです。
ユーザーが書く main() は、スタートアップ
が終了した後に呼び出されるプログラムに過
ぎません。

なお、パソコンのOSでもこのあたりの事情は
同じです。
実行ファイルは、「ローダ」というプログラム
でメモリに展開されて、必要な前処理がなされ、
それが終わった後に、ユーザープログラムの
実行開始点である main() などが呼び出され
ます。
    • good
    • 0
この回答へのお礼

 早速の回答有り難う御座います。

 みなさんの回答から、main関数の前にデータ領域の初期化がC言語の規格だと分かりました。

>Hew が main() の実行前に行っている初期化は「RAM 領域全体を一括してゼロクリアする」と言うレベルの初期化です。

 HEWのサンプルプログラムは、BセクションのゼロクリアとDセクションからRセクションのコピーを行っています。

お礼日時:2009/10/26 19:18

#3です。



組込みのmain関数は、パソコンのOSと同じと例えれば分かり易いかな?
どちらも必要な手続きをしないと、いきなり実行は不可という意味で同じです。
    • good
    • 0
この回答へのお礼

 再度回答有り難う御座います。

お礼日時:2009/10/26 16:15

基本的に、Cのmain()関数の前に、スタートアップルーチンが走ります。



ルネサスHEWがなにかは、存じませんが、スタートアップルーチンで、どこまでやるかは、その言語処理系(OS)で、決まります。
    • good
    • 0
この回答へのお礼

 早速の回答有り難う御座います。

 みなさんの回答を見て、組み込みマイコンの場合スタートアップルーチンがOSに相当するらしいと分かって来ました。

お礼日時:2009/10/26 15:54

どんなCPUでも、ブート後は0番地から実行を開始するのをご存じですか?


組込みのスタートアップルーチンは、パソコンのBIOSに相当すると言えば分かりやすいかな?
パソコンだって、いきなりOSは走らない(走れない)でしょ?

>パソコンでexeファイルを実行した場合、mainに飛ぶと思っているのですが、初期化プログラムに飛んでからmainに飛ぶのでしょうか。

既に動作中のOS上で実行するアプリケーションと組込プログラムは、実行開始時点の状態が全く異なります。
比較する事自体ナンセンス。
    • good
    • 0
この回答へのお礼

 早速の回答有り難う御座います。

>どんなCPUでも、ブート後は0番地から実行を開始するのをご存じですか?

 最後のアドレスにベクタアドレスが書いて有るCPUも有ったような気がします。68000だったかな。

>組込みのスタートアップルーチンは、パソコンのBIOSに相当すると言えば分>かりやすいかな?
>パソコンだって、いきなりOSは走らない(走れない)でしょ?

 OSがBIOSを呼ぶと思っているのですが、そうでは無いのですか?

>既に動作中のOS上で実行するアプリケーションと組込プログラムは、実行開>始時点の状態が全く異なります。比較する事自体ナンセンス。

 組み込みモニタでプログラムをロードしたり実行したりします。このモニタが、パソコンのOSに相当するのでは?

お礼日時:2009/10/26 15:34

この辺の意識は「組み込み」な人とそうでない人の間には差があるかもしれない.


順番を変えますが, 「パソコンでexeファイルを実行した場合」には, 「カーネルから直接 main関数が実行される」ことはありません. なぜなら, main関数の実行の前後に「定型的にしなければならないこと」があるからです. 例えば main関数の開始直後から printf が使えるわけですが, そのためには構造体 FILE を適切に初期化する必要があります. しかし, そんなことを毎回 main に書かせる (あるいは初期化ルーチンを main から呼び出させる) よりも, 「main の前後にしなければならないこと」を行うルーチンを作り, そこから main を呼び出す形にした方が便利です. つまり, 処理系の作成者においては「どんなプログラムでも必ず実行される」ことを前提にできますし, プログラムの作成者にもそのような「プログラム本体とは直接関係ないこと」を書かなくて済むからです.
一方, 組み込み方面だとおそらく意識は違うと思います. つまり「自分の書いたことだけを実行し, 書いていないことは実行しない」のが動作として正しい, という考え方があると思います. そう考えれば「これらの初期化はメイン関数の中で行うべき」というのは正論です. これに対し, 「定型的に行うことをいちいち書くのは面倒」あるいは「書き忘れると痛いのでいや」というのももちろん 1つの考え方たり得ます. そして, そう考えれば「初期化を行ってから改めて main に飛ぶ」ということも十分な意味があります.
    • good
    • 0
この回答へのお礼

 早速の回答有り難う御座います。

 C言語では初期値を持たない変数をゼロクリアする約束が有りますが、それはOSが行ってくれて、プログラム開発者は意識しなくていいのでしょうか。

 exeファイルに何か情報が書いてあり、OSがそれを見てゼロクリアしてくれるのでしょうか。

お礼日時:2009/10/26 15:22

>これらの初期化はメイン関数の中で行うべきだと思っているのですが、どうなんでしょう。


スタートアップルーチンで初期化しなければならない物は、スタートアップルーチンで初期化すべきです。特にセクション関係はアセンブラで無いと記述できないのでは?

>パソコンでexeファイルを実行した場合、mainに飛ぶと思っているのですが、初期化プログラムに飛んでからmainに飛ぶのでしょうか。
パソコンのexeもスタートアップルーチン経由でmainに飛びます。
    • good
    • 0
この回答へのお礼

 早速の回答有り難う御座います。

>特にセクション関係はアセンブラで無いと記述できないのでは?

 普通はそうだと思いますが、HEWでは __sectop, __secend と言う演算子が用意されています。

>パソコンのexeもスタートアップルーチン経由でmainに飛びます。

 そうですか。例えば編集するテキスト名を指定してエディタを起動した場合、main(int argc, char *argv[]) のパラメータにテキスト名を入れ、エディタソフトのmainを呼ぶと思ったのですが違うのですね。

お礼日時:2009/10/26 15:04

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!