日本-日本語 |
|
|
|
OpenVMS マニュアル |
|
HP OpenVMS MACRO コンパイラ
|
目次 | 索引 |
3.4 イメージの動的な再配置 |
OpenVMS VAX システムでは,位置独立コード (PIC) をあるアドレス範囲から別のアドレス範囲にコピーすることができ,アセンブルと実行も正常に行われます。ソース・コード・ラベルを使用してコピーされるある範囲のコードが含まれているコードを, OpenVMS Alpha または OpenVMS I64 用にコンパイルすると, 2 つの理由で動作しません。まず,コンパイルされたコードは,ソース・コードと同じ順序でない可能性があるためです。 2 番目に, OpenVMS Alpha では,外部参照を行うためにはリンケージ・セクションが必要だという点です。リンケージ・セクションは別の psect にあるだけでなく,リンカやイメージ・アクティベータによって設定された絶対アドレスも含まれています。 OpenVMS I64 では,コードは,リンカおよびイメージ・アクティベータによって構築されたグローバル・リージョンの一部を必要とします。
コードを複製するか,あるアドレス範囲から別のアドレス範囲へのコードのコピーを除去します。
3.5 静的なデータの上書き
VAX MACRO アセンブラでは,初期化済みの静的な記憶域を自由に上書きすることができます。それには,通常は ".=" 構文を使用して現在のロケーション・カウンタを変更します。
これに対し,MACRO コンパイラでは, .ASCII データ以外の既存のデータ項目が部分的に上書きされないように,上書きが制限されています。以下のものは上書きできません。
可能であれば,以下のいずれかの正しい形式にコードを変更してください。
LAB1: .WORD 1 .WORD 2 .=LAB1 .WORD 128 |
DATA: .ascii /abcdefg/ .=data .ascii /z/ ; change "a" to "z" .=data .byte 0 ; change "z" to 0 .=data+4 .ascii /xyz/ ; change "efg" to "xyz" |
新しいデータは,以前の .ASCII 文字列の範囲内に完全に収まっている必要があります。次の例は無効です。
DATA: .ascii /abcdefg/ .=data+4 .ascii /lmnop/ ; exceeds end of previous .ASCII |
他の種類の指示文 (.LONG など) を使用した部分的な上書きはできません。
外部シンボルを使用した静的な初期化のうち,いくつかの形式は使用できません。
可能であれば,使用可能な形式のいずれかにコードを変更してください。そのためには,多くの場合, $xxxDEF マクロを使用して追加のシンボルを定義します。 OpenVMS Alpha システムと OpenVMS I64 システムでは,コンパイラは次の形式の式をサポートしています。
<symbol1 +/- offset1> OPR <symbol2 +/- offset2> |
ここで,OPR には以下のものが入ります。
+ 加算
- 減算
* 乗算
/ 除算
@ 算術シフト
& 論理積
! 論理和
\ 排他的論理和
symbol1 と symbol2 (どちらもオプション) は,外部の値または別の psect 内のラベルで, offset1 と offset2 には式を指定できますが,コンパイル時に定数になる必要があります。
OpenVMS I64 システムでは, ELF オブジェクト・ファイル形式の制限により, symbol1 または symbol2 がリンカでルーチンのアドレスに解決される際,減算しか行うことができません。
コンパイラは,次の形式の式をサポートしていません。
<symbol1> OPR <symbol2> |
静的な初期化の式をこの形式に変形できない場合は,コンパイラは不正な静的な初期化を報告します。演算子の優先順位が正しくなるように,括弧を使用してください。
3.7 転送ベクタ
VAX MACRO コード中に .TRANSFER 指示文があると, /noflag=directives を指定していないかぎり,コンパイラはエラーとして出力します。このオプションを指定するとメッセージは出力されませんが, .TRANSFER 指示文は無視されます。
OpenVMS VAX システムでは, VAX MACRO ソース・コード中で転送ベクタを明示的に定義することにより,共用可能イメージ中の再配置可能なコード用にユニバーサル・エントリ・ポイントを作成できます。 OpenVMS Alpha システムと OpenVMS I64 システムでは, リンカ・オプション・ファイル内でユニバーサル・エントリ・ポイントのシンボル値を宣言することで作成します。リンカは,共用可能イメージ内にシンボル・ベクタ・テーブルを作成します。これにより外部イメージは,再配置可能なユニバーサル・プロシージャ・エントリ・ポイントとストレージ・アドレスを見つけることができます。
VAX MACRO のソースから転送ベクタを削除する必要があります。コンパイラが生成したオブジェクト・ファイルをリンクする際に, SYMBOL_VECTOR 文が記述されているリンカ・オプション・ファイルを指定する必要があります。 SYMBOL_VECTOR 文の中で,どこからでも参照可能な,再配置可能なシンボル (プロシージャ・エントリ・ポイントまたはデータアドレス) を記述し,それぞれに対して DATA と PROCEDURE のどちらかを指定します。
リンカは,リンカ・オプション・ファイルにシンボルを記述した順序でシンボル・ベクタを作成します。このシンボルの順序を,後の共用可能イメージの作成まで保持する必要があります。すなわち,シンボル・リストの最後にエントリを追加したり,エントリを削除することはできますが,現行のエントリは,リスト中で同じ順序を保つ必要があります。転送ベクタについての詳細は, OpenVMS Linker Utility Manual を参照してください。
3.8 算術例外
OpenVMS Alpha システムでは,算術例外の処理は OpenVMS VAX システムと違っており,互換性がありません。 OpenVMS VAX システム用に設計された,算術例外を処理する例外ハンドラでは,期待しているシグナル名と OpenVMS Alpha システムで実際に発生するシグナル名を対応付けることができません。
OpenVMS VAX システムでは,算術例外が同期的に報告されることがアーキテクチャによって保証されますが, OpenVMS Alpha システムでは,算術例外は非同期に報告されます。 OpenVMS VAX システムでは,VAX 算術命令で例外 (オーバフローなど) が発生するとすぐに例外ハンドラに入り,以降の命令は実行されません。例外ハンドラに対して報告されるプログラム・カウンタ (PC) は,失敗した算術命令のプログラム・カウンタとなります。これによりアプリケーション・プログラムは,メイン・シーケンスを再開して失敗した演算をエミュレートしたり,同等の演算や代わりとなる演算と置き換えるといったことが可能になります。
OpenVMS Alpha システムでは,例外の原因となった命令の先にあるいくつかの命令 (分岐やジャンプを含む) が実行される可能性があります。これらの命令は,失敗した命令が使用していた元のオペランドを上書きすることがあるため,例外の解釈や修正に不可欠な情報が失われます。例外ハンドラに報告される PC は,失敗した命令の PC ではなく,いくらか先にある命令の PC になります。アプリケーションの例外ハンドラに例外が報告されたときに,ハンドラが入力データを修正したり,命令を再実行することはできません。
算術例外の報告におけるこの基本的な違いにより, OpenVMS Alpha オペレーティング・システムでは,新たに単一の条件コード SS$_HPARITH が定義されており,すべての算術例外を示します。 SS$_HPARITH の例外シグナル配列については, Migrating to an OpenVMS AXP System: Recompiling and Relinking Applications を参照してください。1
アプリケーションの条件処理ルーチンが,発生した算術例外の数をカウントしているだけの場合や,算術例外が発生したら強制終了する場合は, Alpha で例外が非同期に報告されることによる影響はありません。これらの条件処理ルーチンに条件コード SS$_HPARITH のテストを追加するだけで済みます。 VAX の算術例外は OpenVMS Alpha では返されません (トランスレートされた VAX イメージからの例外を除く)。例外の原因となった演算を再実行しようとしている場合は,コードを書き換えるか,算術例外が正確に報告されるようにするためのコンパイラ修飾子または指示文を使用します。ただし,この機能を利用するためには,コンパイラはそれぞれの算術命令を使用した後に命令パイプラインから命令を取り除く必要があるため,性能に大きく影響します。
EVAX_TRAPB ビルトインを使用すると,それまでのすべてのトラップがシグナル通知されます。このビルトインは性能への影響があるため,分離する必要がある算術命令の後でのみ使用してください。
1 このマニュアルはアーカイブ扱いになっています。このマニュアルの保守は行われておらず, OpenVMS ドキュメント・セットにも含まれていません。ただし,http://www.hp.com/go/openvms/doc からオンラインで参照することができます。 |
ページ・サイズへの依存をコーディングする方法を標準化し,将来の変更を容易にするために,一連のマクロが開発されました。これらのマクロについては
付録 D で説明しています。
通常,ページは次のようにロックされます。
OpenVMS Alpha システムでは,コードのページをメモリにロックする必要があるだけでなく,コードのリンケージ・セクションもロックする必要があります。この制約とその他の制約により, OpenVMS Alpha システムには LOCK_SYSTEM_PAGES,UNLOCK_SYSTEM_PAGES, PMLREQ,および PMLEND マクロがありません。
OpenVMS I64 システムでは, OpenVMS Alpha システムで発生した問題を避けるため,パラメータが参照しているイメージ全体をロックするように $LKWSET が変更されました。これにより正しい動作が保証されますが,性能が低下するおそれがあります。詳細は, OpenVMS V8.2 リリース・ノート[翻訳版] を参照してください。
コードの変更を最低限にするため,どちらのケースもいくつかの新しいマクロで対処します。
イメージの初期化時に行われるロックダウンに対しては, 3 つのマクロが提供されています。そのうちの 2 つのマクロは「開始」マーカと「終了」マーカとして機能し,ロックするコードを区切ります。残りの初期化マクロは,記述子を作成し,$LKWSET を呼び出します。
未熟なプログラマのロックダウンやその他のオンザフライのロックダウンが行われていたコードをロックまたはアンロックするために,さらに 2 つのマクロが提供されています。この項で説明したアーキテクチャ上の理由から,これらのマクロはシステム・サービス呼び出し $LKWSET および $ULWSET も使用してページのロックとアンロックを行います。
ワーキング・セットにページをロックする必要があるユーザは,すでに特権コードを実行しているはずなので,これらのマクロは LIB.MLB にあります。
OpenVMS Alpha と OpenVMS I64 のアーキテクチャによるページのロックへの影響
OpenVMS Alpha システムと OpenVMS I64 システムでのワーキング・セットへのページのロックは, OpenVMS VAX システムよりもはるかに複雑です。これには以下の理由があります。
OpenVMS Alpha または OpenVMS I64 でページをワーキング・セットにロックする唯一の方法は,システム・サービス $LKWSET を呼び出すことです。
プログラム・セクション (psect) を使用したコードの線引き
ここで示すマクロでは, psect を使用して,ロックするコードのセクションを囲みます。マクロは 3 つの psect を作成し,順番に名前を付け,以下のように使用します。
すべての psect の属性が同じだとすると,リンカはイメージ内に順番に psect を格納します。同じことが,2 番目の $LKWSET 呼び出しを必要とするリンケージ・セクションにも行われる必要があります。
イメージ内のさまざまな場所にあるロック対象のすべてのコードは同じ psect に格納されるため,この psect を使用した方法では,いずれかの要求元がいずれかのセクションをロックすると,ロック可能なすべてのコードがロックされるという副作用があります。多くの場合,これは利点となります。 OpenVMS Alpha や OpenVMS I64 のページは 8KB 以上であるため,ほとんどの要求元はページレットまたはそれより小さな領域をロックします。そのため,ほとんどの時間,ロック対象のすべてのコードが単一のページに納まります。
イメージ初期化時のロックダウンでは,以下の 3 つのマクロを使用します。
マクロ $LOCKED_PAGE_START と $LOCKED_PAGE_END は,ロックするコード・セグメントの先頭と終わりをマークします。これらのマクロで線引きされたコードには,ルーチン全体が含まれている必要があります。実行がいずれかのマクロを超えたり,ロックされたコードから外に分岐したり,外からロックされたコードの中に分岐することはできません。ロックされたコード・セクションの中に分岐した場合や,ロックされたコード・セクションから外に分岐しようとした場合,またはマクロを超えて実行しようとした場合は,コンパイラから次のエラー・メッセージが出力されます。
3.9 ページ・サイズ
3.10 ワーキング・セットへのページのロック
注意
これら 2 つの方法 (イメージの初期化時に行われるロックダウンとオンザフライのロックダウン) を 1 つのイメージで組み合わせて使用することはできません。オンザフライのロックダウンで実行される $ULWSET サービスは,初期化時にロックされたセクションをアンロックすることもできます。イメージ全体に対してどちらかの方法を選択する必要があります。異なるソース言語からコンパイルされたモジュールが含まれるイメージでは,特に注意してください。
注意
IPL を,ページ・フォルトが発生しない 2 よりも上げることでコードをロックする場合は,その範囲内のコードが実行時ライブラリ・ルーチンやその他のプロシージャを呼び出さないことを確認してください。 VAX MACRO コンパイラは,特定の VAX 命令をエミュレートするためのルーチンの呼び出しを生成します。これらのマクロを使用するイメージは,これらのルーチンの参照がページング不可のエグゼクティブ・イメージ内のコードで解決されるように,システム・ベース・イメージとリンクする必要があります。
%AMAC-E-MULTLKSEC, Routines which share code must use the same linkage psect. |
$LOCKED_PAGE_END にはオプションのパラメータ LINK_SECT があります。これは,ルーチンを実行した後で戻るリンケージ psect を指定するために使用します。これは,$LOCKED_PAGE_START マクロが実行されたときの実際のリンケージ psect が,デフォルトのリンケージ psect ($LINKAGE) でなかった場合にだけ使用します。
マクロ $LOCK_PAGE_INIT は, $LOCKED_PAGE_START と $LOCKED_PAGE_END を使用してロック対象の領域を線引きしているイメージの初期化ルーチンで実行する必要があります。このマクロは必要な psect を作成し,$LKWSET を呼び出してコードとリンケージ・セクションをワーキング・セット内にロックします。 R0 と R1 の内容は,このマクロによって壊れます。
$LOCK_PAGE_INIT には,オプションのパラメータ ERROR があります。これは,いずれかの $LKWSET の呼び出しが失敗した場合に分岐するエラー・アドレスです。このアドレスに到達した場合,R0 には失敗した呼び出しの状態が設定され, R1 は,コードをロックするための呼び出しに失敗した場合は 0,その呼び出しは成功したものの,リンケージ・セクションをロックするための呼び出しが失敗した場合は 1 となります。
psect を使用してロックするコードを識別しているため, $LOCK_PAGE_INIT マクロは,$LOCKED_PAGE_START マクロおよび $LOCKED_PAGE_END マクロで線引きされたコードと同じモジュールにある必要はありません。 $LOCK_PAGE_INIT を実行すると,イメージ全体の線引きされたコードがすべてロックされます。
表 3-1 に,これらのマクロを使用するために必要なコードの変更を示します。線引きするラベルは, $LOCKED_PAGE_START マクロと $LOCKED_PAGE_END マクロに置き換えられています。記述子は削除され,初期化コード中の $LKWSET の呼び出しは $LOCK_PAGE_INIT に置き換えられています。
コード・セクション | VAX システム | Alpha システム |
---|---|---|
データ宣言 |
LOCK_DESCRIPTOR: |
なし。記述子はすべて削除します。 |
初期化 |
$LKWSET_S LOCK_DESCRIPTOR |
$LOCK_PAGE_INIT ERROR |
メイン・コード |
LOCK_START: |
$LOCKED_PAGE_START |
目次 | 索引 |
|