2016-04-25 7 views
1

私と2人の友人が非常に奇妙な問題を抱えています。私たちは小さなアセンブラ部分(プロセスを高速化するために使用されていた)の内部でアプリケーションにクラッシュを検出しました。今、私たちのmindbreakが何であるかASMの理解なぜこれはWindowsで動作しますか?

push  ebp 
mov   ebp, esp 

; do stuff here including sub and add on esp 
mov   esp,ebp 
pop   ebp 

:正しくそれはのように記述する必要がある場合には

push  ebp 
mov   ebp, esp 

; do stuff here including sub and add on esp 

pop   ebp 

:エラーがstackpointerをいじると最後にそれをリセットしないことによって引き起こされた、それはこのように見えました:なぜこれはWindowsで動作しますか?私たちはアプリケーションをクラッシュしたLinuxに移植したときにエラーを発見しました。 WindowsやAndroid(NDKを使用)では問題が発生していたため、このエラーは検出されませんでした。 Stackpointerのリカバリはありますか?スタックポインタの悪用に対する保護はありますか?

+0

は変更はありますか? 'add'sと' pop'sが 'sub'sと' push'esのバランスをとっていれば、 'esp == ebp'はすでに済んでいるので、' mov esp、ebp'を省略する必要があります)。クラッシュした場合、明らかにバランスが取れていません。 WindowsとLinuxで同じアセンブラを使用していますか?異なるアセンブラは同じソースを異なるコードにアセンブルします。 (例えばNASMでは 'mov reg、symbol'は' mov reg、imm32'ですが、MASMでは負荷です。)ABIも32bitでもわずかに違います。 –

+0

このアセンブラは別ファイルになっていますか、またはインライン化されていますか? –

+0

@PeterCordes:いいえ、バランスが取れません。 Linuxの下で私のStackpointerは完全に盗まれています – Nidhoegger

答えて

1

ebp espの使用法はスタックフレームと呼ばれ、その目的はスタックに変数を割り当てることです。その後、ret命令の前にスタックを簡単に復元することができます。 x86 CPUのすべての新しいバージョンは、代わりに出入り命令を使用してこれらの命令をまとめて圧縮することができます。

espは、push/pop/call/retを実行するときにCPUが使用する実際のスタックポインタです。 ebpはユーザが操作するベースポインタです。多かれ少なかれ、すべてのコンパイラはこれをローカルストレージのスタックポインタとして使用します。

命令が存在しない場合、CPUがpop ebpに達したときにesp!= ebpにすると、スタックは誤動作します。

+1

'-fomit-frame-pointer'はgccのデフォルトであり、少なくとも1年間は32ビットx86のclangです。それはx86-64では長年にわたってデフォルトでした。 'enter' /' leave'は80186で新しくなったので、*すべての* 32ビット対応x86 CPUは新しいものではなく、それらをサポートしています。しかし、 'enter'は使い方が遅すぎます。 'leave 'は操作の' mov esp、ebp'部分が必要な場合には使用する価値があり、そうでない場合は関数本体が 'esp'を' add'で既に復元している場合は 'pop ebp'だけ前に他のregをポップできます'ebp'。 –

0

コンパイラが窓にあなたのスタックの面倒を見るようだ:私は想像することができます
唯一の方法は次のとおりです。
のMicrosoft Visual CはB {__ stdcallの}されている機能の特殊な世話をします。コンパイル時にはパラメータの数が分かっているため、コンパイラはシンボル名自体にパラメータバイト数をエンコードします。
__stdcallの規約は主にWindows APIで使用されており、__cdeclよりも少しコンパクトです。主な違いは、任意の関数にはハードコーディングされたパラメータセットがあり、C言語のようにコールごとに変えることはできません(「可変関数」なし)。
は、以下を参照してください。
http://unixwiz.net/techtips/win32-callconv-asm.html
と: `バランスを取ることになってesp`に
https://en.wikipedia.org/wiki/X86_calling_conventions

+0

もし彼の関数が 'ret 8'か何かでargsをポップしなければ、' __stdcall'が動作する方法はありません。ここで発信者と着信者の間の不一致は、それを防ぐのではなく、破損の原因となります。私は、あなたが幸運にも壊れたコードが1つの特定のケースで動作するようになった場合でさえ、これが説明するのはもっともらしいことだとは思わない。 –

+0

はい、私は同意します、ここで呼び出し元と呼び出し先のアセンブリの不一致が破損の原因になります。 –

関連する問題