C/C++ プログラムをリンクするときには、リンカの起動方法に関係なく次の特別な
要件があります。作業すべき事項は次のとおりです。
❏ コンパイラのランタイムサポート・ライブラリを組み込む。
❏ 初期化のタイプを指定する。
❏ プログラムをメモリに割り当てる方法を決定する。
ここでは、上記の要件を制御する方法を説明し、リンカ・コマンド・ファイルの例 を示します。
リンカの操作方法の詳細は、『TMS320C28x アセンブリ言語ツール ユーザーズ・マ ニュアル』の「リンカの説明」の章を参照してください。
4.3.1 ランタイムサポート・ライブラリのリンク方法
ブートストラップ・ルーチン(boot.obj オブジェクト・モジュール)と呼ばれるプロ グラムを初期化および実行するコードと、すべての C/C++ プログラムをリンクする 必要があります。このランタイム・ライブラリには、標準の C/C++ 関数、および本 コンパイラが C/C++ 環境を管理するために使用する関数も組み込まれています。使 用する C28x ランタイムサポート・ライブラリを指定するには、-l リンカ・オプショ ンを指定する必要があります。また、-l オプションはリンカに対して、アーカイブ・
パスやオブジェクト・ファイルを検索する際に -I オプションに注目し、次に C_DIR または C2000_C_DIR 環境変数に注目するように指示します。-l リンカ・オプション を指定するには、次のようにコマンド行に入力します。
一般に、ライブラリはコマンド行の最後のファイル名として指定する必要がありま す。リンカは、コマンド行でファイルが指定された順に未解決の参照をライブラリ 内で検索するからです。ライブラリの後にオブジェクト・ファイルがある場合は、そ れらのオブジェクト・ファイルからライブラリへの参照は解決されません。-x リン カ・オプションを指定すると、参照が解決されるまですべてのライブラリの再読み
cl2000 -v28 -z {-c | -cr} filenames -l libraryname
リンク・プロセスの制御方法
4.3.2 実行時の初期化
ブートストラップ・ルーチンと呼ばれるプログラムを初期化および実行するための コードを、すべての C/C++ プログラムとリンクする必要があります。ブートストラッ プ・ルーチンは、以下のタスクを実行します。
1) ステータス・レジスタおよびコンフィギュレーション・レジスタを設定します。
2) スタックおよび 2 次システム・スタックを設定します。
3) .cinit ランタイム初期化テーブルを処理し、グローバル変数を自動的に初期化し ます(-c オプションを指定している場合)。
4) すべてのグローバル・オブジェクト・コンストラクタを呼び出します(.pinit)。
5) main を呼び出します。
6) main が戻ったときに exit を呼び出します。
rts2800.lib の boot.obj にあるブートストラップ・ルーチンの例は、_c_int00 です。エ
ントリ・ポイントは、通常ブートストラップ・ルーチンの開始アドレスに設定され ます。
ライブラリに含まれている追加のランタイムサポート関数については、第 8 章「ラ ンタイムサポート関数」で説明しています。これらの関数には、ANSI/ISO C 標準ラ ンタイムサポートが含まれています。
注: _c_int00 シンボル
-c または -cr リンカ・オプションを指定する場合、_c_int00 はプログラムのエント リ・ポイントとして自動的に定義されます。
4.3.3 割り込みベクタによる初期化
プログラムがリセットから実行を開始する場合、_c_int00 への分岐にリセット・ベク タを設定する必要があります。これにより、boot.obj はライブラリからロードされ、
プ ロ グ ラ ム は 正 し く 初 期 化 さ れ ま す。割 り 込 み ベ ク ト ル の 例 は、rts2800.lib の
vectors.obj にあります。 C28x の場合、ベクトルの最初の数行は次のとおりです。
.def _Reset .red _c_int00
_Reset: .ivec _c_int00, USE_RETA"
リンク・プロセスの制御方法
4.3.4 グローバル・オブジェクト・コンストラクタ
コンストラクタとデストラクタを備えたグローバル C++ 変数は、コンストラクタを プログラムの初期化時に呼び出し、デストラクタをプログラムの終了処理中に呼び 出す必要があります。C/C++ コンパイラは、スタートアップ時に呼び出されるコン ストラクタのテーブルを作成します。
このテーブルは .pinit という名前付きセクションに含まれています。コンストラクタ は、テーブル内に配置されている順に起動されます。
グローバル・コンストラクタは、他のグローバル変数の初期化後、または main() が 呼び出される前に呼び出されます。グローバル・デストラクタは、atexit() を通じて 登録された関数と同様に、exit() の間に起動されます。
7.8.4 項「初期化テーブル」(7-42 ページ)では、.pinit テーブルのフォーマットにつ いて説明しています。
4.3.5 初期化のタイプの指定方法
C/C++ コンパイラは、グローバル変数を自動的に初期化するためにデータ・テーブ ルを作成します。7.8.4 項「初期化テーブル」(7-42 ページ)では、これらのテーブ ルのフォーマットについて説明しています。これらのテーブルは .cinit という名前付 きセクションに含まれています。初期化テーブルは、次のどちらかの方法で使用さ れます。
❏ 実行時に変数を自動初期化します。グローバル変数は実行時に初期化されます。
-c リンカ・オプションを指定してください(7.8.5 項「実行時の変数の自動初期
化」(7-45 ページ)を参照)。
❏ ロード時に変数を自動初期化します。グローバル変数はロード時に初期化されま す。-cr リンカ・オプションを指定してください(7.8.6 項「ロード時の変数の自 動初期化」(7-46 ページ)を参照)。
C/C++ プログラムをリンクするときには、-c と -cr のどちらかのオプションを指定す
る必要があります。これらのオプションはリンカに対して、自動初期化を実行時に 行うかロード時に行うかを選択するように指示します。プログラムをコンパイルし
リンク・プロセスの制御方法
❏ ロード時に自動初期化を行うと(-cr リンカ・オプション)、次のことが行われま す。
■ リンカは cinit シンボルを -1 に設定します。これは初期化テーブルがメモリ 内に存在しないことを示します。したがって実行時に初期化は行われませ ん。
■ STYP_COPY フラグが .cinit セクション・ヘッダ内に設定されます。
STYP_COPY は、ローダに対して自動初期化を直接実行し、.cinit セクション
をメモリにロードしないように指示する特別な属性です。リンカは、メモリ 内に .cinit セクション用のスペースを割り当てません。
❏ 実行時に自動初期化を行うと(-c リンカ・オプション)、リンカは、.cinit セク ションの開始アドレスとしてシンボル cinit を定義します。ブート・ルーチンは、
このシンボルを自動初期化用の開始点として使用します。
4.3.6 セクションをメモリ内のどこに配置するかを指定する方法
コンパイラは、コードとデータが入った再配置可能ブロックを作成します。これら のブロックはセクションと呼ばれ、さまざまなシステム構成に整合するように、さ まざまな方法でメモリ内に割り当てられます。
コンパイラが作成するセクションには、初期化されたセクションと初期化されない セクションという 2 種類の基本セクションがあります。表 4-1 に、コンパイラが作 成したセクション、およびリンクの目的でそのセクションに課せられているメモリ 上の制約事項を示します。
注: far リンクの問題
C で far と宣言されているオブジェクト、またはラージ・メモリ・モデルのオブ
ジェクトは .ebss/.econst セクションに配置されます。これは .bss/.cons セクションに 配置される near オブジェクトとは別のものです。
表 4-1. コンパイラが作成するセクション (a) 初期化されたセクション
名前 内容 制約事項
.cinit 明示的に初期化されるグローバル変数と
静的変数のテーブル
プログラム
.const 明示的に初期化されるグローバル変数と
静的定数変数および文字列リテラル
下位 64K データ
.econst far 定数変数 データ内の任意の場所
リンク・プロセスの制御方法
表 4-1. コンパイラが作成するセクション(続き)
(b) 初期化されないセクション
C/C++ ランタイム環境は、far_malloc ルーチンを提供することで、システム・ヒープ
(.esysmem セ ク シ ョ ン)を far メ モ リ へ 配 置 で き ま す。malloc ル ー チ ン お よ び far_malloc ルーチンの詳細は、8.5 節「ランタイムサポート関数およびマクロのまと め」(8-31 ページ)を参照してください。
プログラムをリンクする場合、セクションをメモリ内のどこに割り当てるかを指定 する必要があります。一般に、初期化されたセクションは ROM または RAM 内にリ ンクされ、初期化されないセクションは RAM 内にリンクされます。コンパイラが 作成した初期化されたセクションと初期化されないセクションは、.text を除き、内 部プログラム・メモリに割り当てることはできません。コンパイラがこれらのセク ションをどのように使用するかについては、7.1.1 項「セクション」(7-3 ページ)を 参照してください。
リンカは、セクションを割り当てるための MEMORY 疑似命令と SECTIONS 疑似命 令を備えています。メモリへのセクション割り当て方法の詳細は、『TMS320C28x ア センブリ言語ツールユーザーズ・マニュアル』の「リンカの説明」の章を参照して ください。
4.3.7 リンカ・コマンド・ファイルの例
例 4-1 に、C/C++ プログラムをリンクする典型的なリンカ・コマンド・ファイルを 示します。この例のコマンド・ファイルは lnk.cmd という名前です。この例では、3
名前 内容 制約事項
.bss グローバル変数および静的変数 下位 64K データ
.ebss far グローバル変数 / 静的変数 データ内の任意の場所
.stack スタック空間 下位 64K データ
.sysmem malloc 関数用のメモリ 下位 64K データ
.esysmem far_malloc 関数用のメモリ データ内の任意の場所