アセンブリにいくつかのビットを含む Windows Phone プロジェクトを構築しています。アセンブリ ファイルは ARM モード ( CODE32
) で、Thumb にコンパイルされていることがわかっている C 関数にジャンプしようとします。コードは次のようになります。
ldr r12, [pFunc]
mov pc, r12
pFunc
dcd My_C_Function
これが奇妙なことです。スニペットの at の値pFunc
は、関数サンク + 1 のポインターです。つまり、ジャンプ ターゲットが Thumb であり、ジャンプ命令が BX であるかのように、0 番目のビットが設定されます。しかし、サンクは明らかにARMです!サンクは、関数本体のアドレスに 1 を加えたものをロードし、それに BX を実行して、モードを適切に切り替えます。
そのアドレスに BX しようとすると、モードが切り替わり、Thumb モードで ARM コードを実行しようとするのは得策ではないため、クラッシュする可能性があります。そのアドレスに (現在のコードがそうであるように) 単純にジャンプしようとすると、PC がアラインされなくなるため、クラッシュする可能性があります。
理論的には、手動で 0 番目のビットをクリーンアップしてからジャンプすることもできますが、私の考えには誤りがあるはずです。サンクは C コンパイラによって生成されます。C コンパイラは、サンクが ARM コードであることを認識しています。pFunc の下のアドレスは、モジュール間の呼び出しであるため、リンカによって生成されます。したがって、下位ビットはリンカによってそこに配置されます。それらのサンクが ARM であることをリンカが認識しないのはなぜですか?
説明をお願いします。
現在、WP8 デバイスを持っていないため、実際のハードウェアで試すことはできません。生成されたコードをじっと見つめることは、私が持っている唯一のデバッグ手法です:(
編集:しかし、それらのサンクがARMではなくThumb-2の場合はどうなりますか? Thumb-2 は、一部の 32 ビット コマンド IIRC をサポートしています。それらのエンコーディングは ARM モードと同じですか? とにかく、Thumb-2 はどのようにコマンドをデコードするのでしょうか?