逆アセンブラは正しく機能していますか?

今日、IA-32命令のデコード/逆アセンブルの興味深い複雑さについてお話したいと思います。



この記事を読む前に、IA-32コマンドの一般的な構造と既存のプレフィックスについて説明している記事「IA-32コマンドシステムのプレフィックス」を参照することをお勧めします。 この記事では、必須のプレフィックスとそれらに関連するいくつかのニュアンスについて詳しく説明します。



それはすべて、デコーダーを作成するために設計された言語-GDSLについての記事を読むことから始まりました 。 この記事では、私がすでに知っているいくつかの例と、今まで聞いたことのない新機能を紹介します。 それは私が今あなたに話すのは彼らについてです。



MULSS



MULSD



、およびMULPD



(ベクトル乗算命令)などの一部の命令には、同じオペコード0x0f 0x59



がありますが、必須のプレフィックスは異なります(それぞれ0x66



および0x66



)。 問題は、命令コードに複数のそのような接頭辞が同時に存在する場合、どうなるのでしょうか? おそらく、最後のプレフィックスに従って、これがどのような命令であるかを判断する方が論理的でしょう。 しかし、これは常にそうではありません! 最後のプレフィックスが0xf2



または0xf3



である場合、必須と見なされますが、 0x66



は、プレフィックス0xf2



および0xf3



この命令のエンコーディングにない場合にのみ必須です。 これらの命令の正しい逆アセンブラ出力の例は、表にあります。



命令コード 取扱説明書 必須プレフィックス
66 f3 f2 0f 59 ff



MULSD xmm7, xmm7



f2



66 f2 f3 0f 59 ff



MULSS xmm7, xmm7



f3



66 0f 59 ff



MULPD xmm7, xmm7



66



f2 66 0f 59 ff



MULSD xmm7, xmm7



f2



0f 59 ff



MULPS xmm7, xmm7



-





ある時点で、これらのステートメントの正確性を疑っていましたが、残念ながら、 ドキュメントはこの問題についてあいまいな考えを示しています。 その後、実際のプロセッサでテストを実施することが決定され、そのように動作することが判明しました。 このチェックは、アセンブラーインサートを使用して実行されました。 テストの1つの例を以下に示します。



 #include <stdio.h> int main() { double a[2] = {2, 2}, b[2] = {0, 0}; __asm__ __volatile__ ( // Copy data from a to xmm7 register "movupd %1, %%xmm7\n" //"mulsd %%xmm7, %%xmm7\n" ".byte 0xf2, 0x66, 0x0f, 0x59, 0xff\n" // Copy data from xmm7 register to b "movupd %%xmm7, %0\n" :"=m"(*b) :"m"(*a) : ); printf("%lf %lf\n", b[0], b[1]); return 0; }
      
      







コンパイルして実行すると、次のように表示されます。



 $ gcc -O0 -Wall mulsd.c $ ./a.out 4.000000 2.000000
      
      







つまり、ベクトルの最初の要素のみが乗算され、2番目の要素は変更されないままで、これはMULSD



ではなくMULPD



命令に対応します。



この例では、既知のパッケージに含まれるいくつかの逆アセンブラーがテストされました。 これらの製品の開発者にすぐに報告された彼らのタスクに対処した人はほとんどいませんでした。 結果の概要を以下に示します。



製品バージョン 結果 私が報告したエラー
ウインドリバーシミック4.8 成功 -
XED 成功 -
objdump、2.23 間違い 16083
GNU GDB 7.5 間違い 16089
nasm、2.09 間違い 3392269
ODA、0.2.0 間違い メール対応
objconv、2.31 間違い メール対応
IDA、6.4(評価版) 間違い メール対応
llvm-objdump、3.2 間違い 17697


gdbとobjdumpはbinutilsの一部であり、逆アセンブルには同じライブラリを使用することに注意してください。 ODA開発者の1人であるAnthony DeRosaは、私のエラーメッセージに応じて、binutilsの一部であるlibopcodesライブラリを使用していると言いました。 つまり、1箇所で修正を行うと、少なくとも3つの製品を一度に修正する必要がありますが、残念ながら、binutilsのいずれもまだ私に答えていません。



使用する逆アセンブラは正しく機能しますか?



All Articles