5

非常に疑わしい逆アセンブルされた C アプリケーションの MIPS コードを見ています

80019B90                 jal     loc_80032EB4

loc_80032EB4 は別の関数の本体の途中にあります。実行時にこのアドレスに他のコードがロードされていないことを特別にチェックしました。この方法でその関数を呼び出す (最初にコードを渡す) と便利です。しかし、Cでどのように行うことができますか? 別の関数に移動することはできず、通常の関数呼び出しは常に先頭に "jal" されるため、これは goto ではありません。これは手の最適化でしょうか?

アップデート:

両方の関数の簡略化されたレイアウト、呼び出し先:

sub_80032E88 (lz77_decode)
... save registers ...
80032E90                 addiu   $sp, -8
... allocate memory for decompressed data ...
80032EB0                 move    DECOMPRESSED_DATA_POINTER_A1, $v0
loc_80032EB4:
80032EB4                 lw      $t7, 0(PACKED_DATA_POINTER_A0)
... actual data decompression ...
80032F4C                 jr      $ra

発信者:

80019ACC                 addiu   $sp, -0x30
... some not related code ...
80019B88                 lw      $a1, off_80018084   // A predefined buffer is used instead of allocating it for decompressed data
80019B90                 jal     loc_80032EB4
80019B94                 move    $a0, $s0
... some other code and function epilogue ...

更新 2: これが setjmp/longjmp の使用のケースであるかどうかを確認しましたが、私のテストでは、直接のジャンプではなく、逆アセンブルされたコードで常に setjmp および longjmp 関数の呼び出しを確認できます。

更新 3: GCC 固有の機能を使用してラベル ポインターを取得し、このポインターを関数にキャストしてみました。結果は私が望むものに近いですが、exaxct アドレスで jal を使用する代わりに実行時に計算するため、逆アセンブルされたコードはまだ異なります。スコープの問題のため、コンパイラにこの値を定数として表示させることはできません。

4

1 に答える 1

2

これはゲームシステムのデータ解凍機能であるため、この機能は複数のエントリポイントを使用して手動で最適化されたアセンブリである可能性が非常に高くなります。複数のエントリポイントは一般的に使用されないため、公開されている例を見つけるのは困難です、この手法の使用の可能性を示唆するgccメーリングリストの古いスレッドを次に示します。

要点は、一方の関数F1にもう一方の関数F2のコードのサブセットであるコードがある2つの関数がある場合、 F2のコードはF1のコードに分類される可能性があるということです。あなたの場合、F2は解凍されたデータにメモリを割り当て、F1はメモリの割り当てがすでに行われていると想定します。GCC2.9xではこのようなコードを生成できないと確信しています。

この構造をアセンブラから標準Cに直接変換することはできませんgoto。これは、Cで別の関数を使用できないためですが、これはアセンブラコードでは完全に合法です。gccメーリングリストスレッドは、Cで同じアイデアを表現するためのいくつかの回避策を提案しています。

解凍のために分解されたコードを見ると、コンパイラーが生成したコードとは異なるスタイルになっている可能性があります。コンパイラがCから生成できない最初のセットビットを見つけるなど、オペコードが使用されることもあります。

于 2012-09-03T19:29:39.850 に答える