2

アセンブリにいくつかのビットを含む 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 はどのようにコマンドをデコードするのでしょうか?

4

3 に答える 3

2

逆アセンブラー (具体的には IDA Demo) は、いくつかのコマンドを 1 行にまとめて誤解を招きました。完全な 32 ビット定数をレジスタに割り当てることを意図したシーケンスから1mov行を作成しました。mov-orr-orrやっぱりサンクは親指でした。リンカーは設計どおりに機能します。

それ以外の点では、IDA は優れています。ARM に関するこの特定の動作については頭の片隅で知っていましたが、今回はそれが誤りでした。

助けようとしたすべての人に私の悪い、感謝と賛成票を投じます。

于 2013-08-16T18:42:00.490 に答える
2

あなたの手に有効な/本当の問題があるかもしれません。Afaik Windows Phone 環境はThumb-2 のみである必要があるため、使用しているリンカーは ARM モードへの呼び出しを処理できない可能性があります。アセンブリと C を混在させる場合の考慮事項については、同じリンクを参照してください。

これが Linux / ELF に関する質問であった場合、私は別の回答をしたでしょう。

pFunc の下のアドレスは、モジュール間の呼び出しであるため、リンカによって生成されます。したがって、下位ビットはリンカによってそこに配置されます。

pFuncによって生成されcompilerlinker呼び出しの静的な再配置のために既に完全に解決されているロード可能なイメージを構築しているときに修正されます。すべてのポータブル オブジェクト ファイルには関数モードに関するテーブルが含まれている必要があります。これにより、後でリンカーがそれらを処理し、それに応じて再配置と呼び出しシーケンスの更新を行うことができます。

これがファイル経由でどのように行われるかについては、ARM アーキテクチャの ELF - 4.6 再配置を参照してくださいELF

于 2013-08-16T07:23:28.080 に答える