あなたの質問にどのようにつながっているかを理解するために十分な情報がスクリーンショットにあるとは思いません。しかし、一般的なジャンプテーブル...
Cでは、関数の配列を考え、関数の配列内の各要素を初期化しています。ある時点で、コードは決定を下し、インデックスを使用して1つを選択しますそれらの機能のうちの1つ。あなたがケースステートメントを述べたように、そのように実装することはできますが、それはルールではなく例外になります。すべてはスイッチで使用される変数とcaseステートメントの要素のサイズ/幅/性質に依存します。
あなたはレジスタを理解したり、レジスタで数学をやったり、レジスタに物事を保存したりするためにアセンブリを取り上げています。プログラムカウンタは多くの命令で別のレジスタとして使うことができます。それで、あなたは次に実行される命令を変更します。
switch(bob&3)
{
case 0: ted(); break;
case 1: joe(); break;
case 2: jim(); bob=2; break;
case 3: tim(); bob=7; break;
}
あなたが(おそらくないでしょう)んですができるか:
casetable:
.word a
.word b
.word c
.word d
caseentry:
ldr r1,=bob
ldr r0,[r1]
ldr r2,=casetable
and r0,#3
ldr pc,[r2,r0,lsl #2]
a:
bl ted
b caseend
b:
bl joe
b caseend
c:
bl jim
mov r0,#2
ldr r1,=bob
str r0,[r1]
b caseend
d:
bl tim
mov r0,#7
ldr r1,=bob
str r0,[r1]
b caseend
caseend:
だから4つの単語は、ラベルcasetable後:アドレスです
は、case文の例を試すことができますcase0はそれぞれのケースに対して開始され、case0はaで始まります。case1コードはb:で始まります。私たちがする必要があるのは、switchステートメントで使用される変数をとり、テーブル内の項目のアドレスを数学的に計算することです。次に、テーブルからプログラムカウンタにアドレスをロードする必要があります。プログラムカウンタへの書き込みは、ジャンプの実行と同じです。
このように、Cサンプルは意図的に作成されました。まず、bob変数の内容をr0にロードします。そしてそれは3です。ジャンプテーブルの項目は32ビットのアドレス、すなわち4バイトですので、テーブルのオフセットを得るためにr0の4倍にする必要があります。 2の左シフトは4の乗算と同じです。ジャンプテーブルのベースアドレスにr0 < < 2を追加する必要があります。したがって、本質的に我々はaddress_of(casetable)+((bob & 3)< <を計算している)2)その計算されたアドレスのメモリを読み込み、その値をプログラムカウンタにロードする。
アーム付き
使用すると、1つの命令でこれの多くを行うことができます(これが腕だった言及した):レジスタPCに
ldr pc,[r2,r0,lsl #2]
負荷、メモリ位置の内容[R2 +(R0 < < 2) ]。 r2はcasetableのアドレス、r0はbob & 3です。
基本的にジャンプテーブルは、アドレステーブルへのオフセットを数学的に計算することになります。アドレスのテーブルは、上記の例のbobがその変数である場合に、数学演算で使用されるパラメータの1つに応じてジャンプ/分岐するアドレスです。そして、アドレスa、b、c、dは、bobの内容に基づいて選択したいアドレスの選択肢です。何千もの楽しい方法がありますが、実行時に分岐するアドレスを計算し、そのアドレスを特定のプロセッサに実行させる方法でプログラムカウンタに送ります本質的にジャンプ。計算する方法を読んで、私の例ではジャンプのようになり、おそらく簡単に
注別、:
mov r3,r0,lsl #2
add r3,r2
bx r3
親指は、多くの場合、レジスタとBX命令を使用してサポートするコアは、通常、あなたはリターンにBX LRを参照してください分岐リンク(サブルーチン)からの呼び出し。 bx lrはpc = lrを意味します。 bx r3はpc = r3を意味します。
私が質問したことが欲しいと思っていますが、私が質問を誤解している場合は、詳しく説明してください。
編集:
あなたのスクリーンショットのコードを見てください。
cmp r0,#4
addls pc,pc,r0,lsl #2
任意の数学は、(低いか同じ場合ADDLS追加)プログラムカウンタ自体に基づいて、新しいプログラムカウンタ値(ジャンプテーブルは、プログラムカウンタに格納されている計算である)プラスオフセットR0の4倍を計算します。アーム・プロセッサーの場合、実行時にプログラム・カウンターは2命令先です。したがって、コードと私の例の一部をそれらの二行混合:時間のADDLで
cmp r0,#4
addls pc,pc,r0,lsl #2
ldr pc,=a
ldr pc,=b
ldr pc,=c
ldr pc,=d
...
、プログラムカウンタがLDRのPC、= B命令のアドレスが含まれて実行されます。したがって、r0が0を含む場合、0 < < 2 = 0の場合、pcプラス0はldr pc、= b命令に分岐し、その命令はb:ラベルに分岐します。 add0の時にr0に1が入っていたら、次にldr pc、= c命令を実行します。このようにしてテーブルを深く作ることができます。また、addは条件付きであるため、条件が発生しない場合はaddlsの後にその最初の命令を実行しますので、テーブルを分岐する無条件分岐であるか、逆方向にループを分岐するかあなたが最初のジャンプに落ちるようなノップ、または私が上でやったことは、他の場所へのブランチを持つことです。そこで何が起きているのかを理解するには、可能なジャンプテーブルの宛先が何であるかを把握するためにaddlsに続く命令の例を挙げる必要があります。
ありがとうございます!これはすべて今、特にADDLSが「それ以下であれば追加してください」と説明してくれてありがとう、感謝しています。 – Coutts