複数の競合する定義が表示されているため、RISC-VでJALがどのように機能するかわかりません。たとえば、このWebサイトを参照すると、次のようになります。 https://rv8.io/isa.html
JAL rd,offset
にはオフセットとして3番目の引数がありますが、代わりにJAL rd, imm
を表示する場合があります。違いはなんですか?
JALは関数を受け取り、その出力をrdに返すことになっているようです(一部のソースがそれを同時にra
とrd
と呼んでいる理由はわかりません)。しかし、その場合、サブルーチンまたは関数は何ですか? rd
はレジスタの宛先として定義されているようで、imm
は単なる整数のようです。
本当に混乱しているので助けてください。
jal
命令ではimm
(またはimm20
)は20ビットの2進数です。
offset
は、imm
命令によるjal
の-解釈です。imm
の内容は1桁左にシフトされ、その後アドレスのサイズ(現在は32ビットまたは64ビット)に符号拡張されているため、値が-1百万(約)から+1百万の整数になります。
このoffset
整数は、jal
命令自体のアドレスに追加され、呼び出したい関数のアドレスを取得します。この新しいアドレスはPCに入力され、プログラムの実行はそのアドレスにある命令から再開されます。
同時に、jal
に続く命令のアドレスがCPUレジスタrd
に格納されます。呼び出されている関数は、おそらく後でjalr rn
命令を使用して、これを使用して戻ります。
RISC-Vハードウェアでは、32個の整数レジスタのいずれかをrd
として指定できます。レジスタ0(x0)がrd
として指定されている場合、戻りアドレスは破棄され、関数呼び出しではなく、実質的に+/1 MB goto
になります。
標準のRISC-VABI(ソフトウェア規則、ハードウェアとは関係ありません)では、通常の関数の場合、rd
はレジスタ1(x1)である必要があり、これは一般にra
(Return住所)。レジスタ5(x5)は、関数の開始時と終了時にレジスタを保存および復元するための特別な関数など、特別なランタイムライブラリ関数にも一般的に使用されます。
RISC-V命令セットのマニュアルでは、CPU設計者は、特別なハードウェア(return address stack
)を追加して、厳密にネストされたjal x1/x5,offset
と `jalr x1/x5 'のペアを他の方法よりも高速に実行することを選択できます。予想されるため、標準のABIに従うことには利点があります。ただし、他のレジスタを使用してもプログラムは正常に動作します。
機械語とアセンブリ言語を混同しているようです。
マシンコードの観点からは、命令全体、したがってそのすべてのフィールドは単なる数字です。
これらのエンコーディングは、命令セットアーキテクチャによって定義されています。ハードウェアは、そのISA仕様に従ってこれらの数値ビットフィールドを解釈するように特別に設計されています。
アセンブラ、リンカ、およびオペレーティングシステムローダーは、さまざまなフィールドの数値(または命令全体の1つの数値)の代わりに、シンボリック値を使用して命令を形成できるようにするために共謀しています。
1つのテキストがra
とrd
を参照することはあまり真剣に受け止めません。 could不一致を示しているか、命令のマシンコードフィールドを文書化する別の方法である可能性があります。
JAL命令は、レジスタとイミディエートの2つのオペランドをエンコードします。
識別されたレジスタ番号は、jal命令の場所であるリターンアドレスの場所に加えて、jal命令の長さで更新されるため、レジスタは次の値を取得します順次(アドレスによる)jalの後の命令。これは、呼び出しからの適切なリターンアドレスです。
命令のすべてのビットフィールドと同様に、イミディエートはエンコーディングです。デコードされた値は、最終的に分岐ターゲットアドレスを生成します。これは、イミディエートビットフィールドを符号付きオフセットに変換することによって計算され、jal命令のpcに追加されます。エンコードでは、18ビット(複数のビットフィールドに分散)と符号ビットが許可され、オフセットの最後のビットはエンコードされません(ブランチターゲットは常に16ビットで整列されます。つまり、最後のビットは常にゼロになるため、保存されていません)。最終的に、jalはjal命令自体から-0.5MBから+ 0.5MBに達する可能性があります。
前述のように、実行中のハードウェアは、イミディエート(サブ)フィールドをオフセットに変換し、PCに追加して、最終的なブランチ/コールターゲットを識別します。アセンブリ言語でラベルやその他の複雑な式を提供できることは、これらの言語の機能です。これらの言語の目的は、ラベルやその他の式を、プロセッサが意図した場所に移動するために必要な即時ビットフィールド定数に凝縮することです。オブジェクトコード内の再配置やロードされたコード内の修正の複雑な相互作用があり、これらの即時ビットフィールドが、ハードウェアが意図した場所に到達するための実行時の比較的単純なフィールド抽出と追加に基づいて使用できる有用なビットパターンを保持することを保証します。
関数がお互いのつま先を踏まずにお互いを呼び出すには、呼び出し元と呼び出し先のasmコードが次のすべてに同意する必要があります。
これは広く呼び出し規約と呼ばれます。これは、呼び出し先について他に何も知らない発信者、およびその逆の対話方法を指示します。これは、どのレジスタまたはスタックの場所が最初のパラメータ、2番目のパラメータを保持するか、どのレジスタまたはスタックの場所が戻りアドレスを保持するか、戻り値がどのように伝達されるか、および呼び出し元の環境のどのレジスタが保持されるかについて、ソフトウェア規則の要件を課します。呼び出しによってvs.呼び出しによって消去される可能性がある(スクラッチ)。
規則が適切に守られている場合、呼び出し元(呼び出し先の実装を知らず、パラメーターのタイプと戻り値、別名関数シグネチャーのみ)は次のことができます。