第 3 回は リセット後のマイコンの動作です。
今回の場合、リセットベクタから jmp 命令で飛んできた 0x68 番地は次のような命令から始まっています。
r1 レジスタを eor(排他的論理和) でゼロクリアした後、その r1 を使って 0x3f 番地にゼロを書き込んでいますが、 0x3f 番地のレジスタははステータスレジスタです。ステータスレジスタはフラグレジスタともいわれていて、レジスタの各ビットが直前の計算の特徴(ゼロになったり、負の値になったり、桁あふれが起きたりすること)を表しています。 各ビットは分岐命令などで参照するために使われます。 C 言語でいうところの if 文の条件の真偽を判定して if に飛ぶか else に飛ぶかが決まるのは、分岐命令がステータスレジスタを参照しているからというわけです。
その後の 0x6c から 0x72 番地までの 4 つの命令はは 0x3e, 0x3d 番地にそれぞれ値 0x04, 0xFF を書いていますが、 0x3e, 0x3d 番地は 2 つともスタックポインタです。スタックポインタとはスタックのアドレスを保持しておくレジスタのことですが、なぜ 2 つもレジスタが必要かというとメモリ空間が 16bit である一方でマイコン自体は 8bit マイコンであるからです。16bit のアドレスを示すためには 8bit レジスタを 2 つ使いそぞれれでスタックポインタの上位バイトと下位バイトを分担する他ないからです。
次に気になるのはスタックポインタが 0x4ff 番地から始まる理由ですが、これはプログラムをビルドするのに使った gcc がそう決めているからです。今回のターゲットマイコンである Atmega188 は 0x4ff 番地が RAM の最終番地ですが、gcc で Atmega188 用のプログラムをビルドするときは RAM の最後からスタックを使っていくように gcc が決めているようです。 RAM の先頭の領域は静的変数が使うために割り当てられていますから、スタックを使ってもなるべく変数領域を壊さないようにするためには RAM の最後からスタックを使っていくのは当然のことといえます。malloc などで使うヒープのことは今は考えません。
この 6 つの命令でステータスレジスタとスタックポインタを初期化しました。ステータスレジスタを設定したことによりこれ以降のプログラムで分岐命令が使えるようになり、スタックポインタを設定したことによりこれ以降のプログラムでサブルーチンを call すること、つまり関数を呼ぶことができるようになりました。すこし main に近づいてきた感じがしますが、後もうちょっとつづきます。 main 関数を実行するためにまだ、やり残していることとはなんでしょうか。(次回に続きます)












最近のコメント