KOZOS (14)

リンカスクリプトを見ていくつか気になったソレをメモ。

  • マニュアルによればモード 5 (内蔵 ROM 有効拡張 16M バイトモード) らしい
  • stack がてっぺんから下におりてくるのはどこでも同じなのだろうか
  • リンカスクリプトで定義してあるシンボルは extern で外部参照できる
    • 初期処理でコピーしたり 0 初期化してたり
    • 当たり前だけど自分でヤるあたりにちょっとしたふふふ感あり

実行開始時に初期化される静的な変数については以下の操作が必要との事。

  • 初期値は ROM に保存されていて h8write で転送する時に ROM に書く
  • 起動 (電源投入) 時、プログラムの先頭付近で ROM な領域の変数の初期値を RAM にコピィする
  • 変数の領域は RAM に置く

これ、非常に面白い。上記箇条書きの最後の処理が main.c の以下の部分にあたる模様。

static int init(void)
{
  /* 以下はリンカ・スクリプトで定義してあるシンボル */
  extern int erodata, data_start, edata, bss_start, ebss;

  /*
   * データ領域とBSS領域を初期化する.この処理以降でないと,
   * グローバル変数が初期化されていないので注意.
   */
  memcpy(&data_start, &erodata, (long)&edata - (long)&data_start);
  memset(&bss_start, 0, (long)&ebss - (long)&bss_start);

下の memset は bss な領域にばくっと 0 をコピィしてるのですが面白いのはその上の部分。ちなみにリンカスクリプトの該当部分が以下です。

	.rodata : {
		_rodata_start = . ;
		*(.strings)
		*(.rodata)
		*(.rodata.*)
		_erodata = . ;
	} > rom

	.data : {
		_data_start = . ;
		*(.data)
		_edata = . ;
	} > data AT> rom

&erodata なアドレスは &data_start な ROM のアドレスと等価との事。テキストにはリンカスクリプトの以下な部分の記述の解説があります。

	} > data AT> rom

.data な領域は RAM に配置された data な領域に配置されるけど、ロードされるのは rom だからね、という指定らしい。リンクは RAM でロードは ROM と。
で、memcpy でロードされたナニから RAM な領域にこちらもばくっとコピィしてるのですね。誰が考えだしたのかは分かりませんが凄いなぁ。

スタックポインタ

現状、リンカスクリプトの以下の記述が何を意味するかはあまり解説されてませんが

	stack(rw)	: o = 0xffff00, l = 0x000000 /* end of RAM */
}

SECTIONS
{
/* 中略 */
	} > data AT> rom

	. = ALIGN(4);
	_end = . ;

	.stack : {
		_stack = .;
	} > stack

即値を sp に代入するのではなくて、_stack なナニを代入する方法に修正してます。

_start:
	mov.l	#_stack,sp

しかしこの bss の 0 初期化とかデータセグメントの初期化とかスタックポインタの設定とかそれぞれのメモリ上の場所指定、などとゆーあたりもきっちり指示さしあげないといけない、というのはある意味凄い。
逆に言えば自動でそうなってる、というのは幸せなのだなぁ、と。

とりあえず

この時点で、エントリ投入。続きは別エントリで。