弱いバインディング
m68kにはhardware_init_hookというシステム依存部で定義する関数があり、リセット直後にCPU依存部から呼ばれます。この関数は名前のとおりハードウェアの初期化をおこなうフック関数です。フックと言うことは、ない場合もあります。m68kのstart.Sは以下のようなコードでこの関数を呼び出します。
/* * hardware_init_hook の呼出し(0 でない場合) * * ターゲットハードウェアに依存して必要な初期化処理がある場合 * は,hardware_init_hook という関数を用意する. */ move.l #hardware_init_hook, %a0 cmp.l #0, %a0 jbeq start_1 jsr (%a0)
「hardware_init_hookが0でない場合」は、これを呼びます。hardware_init_hookが未定義ならばリンクエラーになりそうなものです。そうならないのは、ldリンカースクリプトに次のような宣言があるためです。
PROVIDE (hardware_init_hook = 0) ;
これはhardware_init_hookに0を代入しなさいというリンカー・スクリプトの命令です。それだけなら何でもありませんが、provide命令で代入された値は、ソースコード内に実シンボルが定義されている場合、そちらの値で置き換えられます。ですから、未定義だと0、定義済みだとその値をプログラム中で使うことが出来るのです。
VisualDSP++の場合、リンカーにこのような機能はありません。しかし、アセンブリ言語にこのような機能があります。たとえば次のプログラムで、
.extern foo; .weak bar; _main; p0.L = lo(foo); p0.H = hi(foo); p1.L = lo(bar); p1.H = hi(bar);
fooが外部のプログラムで未定義の場合、リンカーがエラーを出力して終了します。しかし、barが未定義の場合はエラーは出力されず、プログラムにはbarの値として0が渡されることになります。これはgnu ldのprovide()と同じ動作です。
hardware_init_hookのほか、software_init_hook、software_term_hook関数がありますが、これらも同様の仕掛けで実装します。