アーロンアダムスアセンブリコードを勉強しています。ドキュメント here (セクション-[2.b.i Getting EIP)を見つけることができます。
EIPを取得することが目標であることを理解しています。
私はFPU環境が以下のように見えることを知っています:
struct _fpstate_32 {
/* Legacy FPU environment: */
__u32 cw;
__u32 sw;
__u32 tag;
__u32 ipoff;
__u32 cssel;
__u32 dataoff;
__u32 datasel;
そしてipoff
にはEIPが含まれています。
つまり、fnstenv [esp-12]
はcw
、sw
、tag
とipoff
をスタックに入れ、pop ecx
を使用してECXでEIPを取得できます。
しかし、私はfldz
の目的を理解していません。
fldz
"+0.0をFPUレジスタスタックにプッシュします"。 FPUに2つ目のスタックがあるということですか?そして、なぜこれを行う必要があるのですか?
私が理解しているところによると、あなたが言及したEIP
の値(ipoff
)は、実際にはLast instruction pointer
レジスタから取得した値です。
したがって、fnstenv [esp-12]
を呼び出すと、スタックにプッシュされる値は、lastフローティングであるため、fldz
命令へのポインターになります。 fnstenv
を呼び出す前に実行されるポイント命令。
それがなければ、fnstenv
が返す値は何でもかまいません。
参照: https://home.deec.uc.pt/~jlobo/tc/artofasm/ch14/ch143.htm
命令およびデータポインタレジスタには、最後に実行された浮動小数点命令に関する特定の状態情報が含まれています。