0

GNU アセンブラ用の x64 アセンブリを書いています。.seh_ * ディレクティブについて調べてみましたが、それらに関する情報があまり見つかりません。ドキュメントはそれらgasについてまったく言及していません。

しかし、私が理解しているように、SEH アンワインド操作中にコードがスタックにある可能性がある場合は、これらを使用することが期待されています。また、私のコードは操作をスタックし、他の関数を呼び出すため、SEH の可能性があるため、これらを使用する必要があります。

ほとんどの場合、私はそれが正しいと思います:

.seh_proc FCT
FCT:

push %rbp
.seh_pushreg    %rbp

mov  %rsp, %rbp
.seh_setframe   %rbp, 0

push %r14
.seh_pushreg %r14

lea -(iOffset + iBytes)(%rsp), %rsp
.seh_stackalloc iOffset + iBytes

andq $-16, %rsp <---- But what about this?

.seh_endprologue

etc...

しかし、はっきりしない点が 1 つあります。私はこの指示を持っています:

andq $-16, %rsp

スタックアライメントを実行していることをSEHに伝えるにはどうすればよいですか?これにより、スタックが 15 バイト (ほとんどありません) から 8 バイト (非常に可能性が高い)、0 バイト (確かに可能) に調整される可能性があります。実際の金額は実行時まで決定されない可能性があるため、行き詰まっています。

.seh 命令をスキップできると思いますが、そこで 8 バイトのスタックが予約された場合、アンワインドを破棄した可能性がありますね。それはここでの目的全体を無効にしませんか?

または、アライメントを省略できます。しかし、他の関数 (memcpy など) を呼び出した場合、スタックを整列する必要はありませんか? MSによると:

スタックは、プロローグ内を除いて、常に 16 バイトでアラインされた状態に維持されます。

たぶん、これで自分のやり方を「推論」できますか?私を呼んだ人が正しいことをした場合 (もし...)、彼がしたときにスタックが整列していたcallので、今では 8 バイト (戻りアドレス) とプロローグで行ったことは何でもずれています。私はこれに頼ることができますか?壊れやすいようです。

私は他のコードを調べてみましたが、私が見ているものを信頼できるかどうかはわかりません. .seh_ gas* の誤用によるエラーを報告しているとは思えません。おそらく、実際の例外が発生しているときに問題が発生するだけです (常にそうであるとは限りません)。

これをやるなら、ちゃんとやりたい。スタックの配置は一般的なことのように思われるので、誰かがここで解決策を持っている必要があります. 私はそれを見ていません。

4

1 に答える 1

0

gcc によって出力されたコードを見ると、答えはわかっていると思います。私は「理由」アプローチで正しい軌道に乗っていました。

関数が呼び出されると、スタックは ( によりcall) 一時的に整列されなくなりますが、 を介してほぼ即座に再整列されpushq %rbpます。その後、スタックへの調整 (ローカル変数または呼び出された関数へのパラメーター用のスタック スペースなど) は、常に 16 の倍数を使用して行われます。次までcall

これはandq $-16, %rsp、スタックの整列に while を使用できることを意味しますが、プロローグを正しく記述すれば、その必要はないはずです。

注意: リーフ関数 (つまり、他の関数を呼び出さない関数) は、スタックを調整する必要はありません ( https://msdn.microsoft.com/en-us/library/67fa79wz.aspx )。

于 2016-07-04T22:31:18.903 に答える