アセンブリ コードの無条件ジャンプに続く命令は、新しい基本ブロックの開始を構成しますか? 命令が実行可能ファイルのどのブランチのターゲットでもないとしましょう。
2 に答える
計算された分岐、および条件付き分岐が常にまたはまったくたどられない可能性があるため、基本ブロックを構成するものを完全に決定することは不可能です。代わりに、基本ブロックは次の 2 つの仮定を使用して推定されます。
- 計算された分岐は、何らかの理由で基本ブロックの開始位置にのみ移動するため、ターゲットを知る必要はありません。
- 条件付き分岐は、たどることも、たどらないこともできます。
ウィキペディアの定義を使用すると、基本ブロックは最初にのみ入り、最後に出ることができ、最初から最後まで 1 つのパスしかありません。したがって、条件付きジャンプ命令は 2 つのパスを作成するため、基本ブロックの最後でなければなりません。計算された分岐も、多くの異なるパスを生成できるため、終わりです。
無条件ジャンプが基本ブロックの終わりであるかどうかは、わずかに異なる定義を使用して議論できます。ブロック内のすべてのコードがメモリ内でシーケンシャルでなければならない場合、無条件ジャンプは、その後の命令に移動しない限り、常に最後になります。それ以外の場合は、非ジャンプ命令と同じ規則に従います。
他のすべての命令では、その後に実行される命令が基本ブロックの開始である場合、それは 1 つの終了でなければなりません。
ブロックの最も簡単な開始点は、プログラムのエントリ ポイントです。さらに、条件付きジャンプのターゲットである命令は、ジャンプ命令の後に実行される場合と実行されない場合があるため、ブロックの開始です。命令が無条件ジャンプのターゲットであり、基本ブロックがメモリ内で連続している必要がある場合、それはブロックの開始です。それ以外の場合、それが 2 つ以上の無条件ジャンプのターゲットである場合、または 1 つのターゲットであり、その前の命令が無条件ジャンプではない場合、ブロックには複数のパスがあるため、ブロックの開始になります。
無条件ジャンプの後の命令が他のジャンプのターゲットでない場合でも、基本ブロックの開始としてラベル付けされる可能性があります。これは、その存在が、計算された分岐がそれをターゲットにする可能性があることを示唆しているためです。
基本ブロックの開始に関するこれらの規則は、本質的に「基本ブロックの終了後に実行される命令が基本ブロックの開始である」に単純化されます。
より小さなブロックを生成する場合もありますが、一般的には適切な、はるかに単純な方法は、すべてのジャンプがブロックの終わりであり、その後の命令がブロックの開始であり、すべてのジャンプのターゲットがブロックの開始であるというものです。その前の指示は 1 つの終わりです。
利用可能な高レベルのコードがあれば、それを使用してブロック境界をより正確に決定できます。たとえば、コンパイラによって生成された計算された分岐には、多くの場合、可能なターゲットの既知のセットがあります。次の C コードを検討してください。
int i, j, k;
switch(i) {
case 0:
j++;
// Flow into the next case
case 1:
k++;
}
計算された分岐を使用した、このコードの可能な疑似アセンブリを次に示します。
jump *(i+jumpTable)
add 1, j
add 1, k
ジャンプ テーブルは追加命令の 1 つをターゲットにするため、これらは両方とも基本ブロックの開始です。ただし、これはアセンブリからは判断できないため、最初の仮定が使用されます。最初の追加は、ジャンプの後に来るため、基本ブロックの開始です。ただし、2 番目の追加を対象とする既知の分岐がないため、この分析では基本ブロックの開始とは見なされません。