この記事を読む前に、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のいずれもまだ私に答えていません。
使用する逆アセンブラは正しく機能しますか?