2015-11-23 3 views
9

main(ubuntu 14.04を実行している)64ビットマシンでgcc -g -o program -m32 program.cを使ってコンパイルされた(単純なおもちゃプログラムの)プロローグの中で、解体以下:main()のプロローグでスタックポインタを整列させる目的は何ですか?

dump of assembler code for function main: 
    0x08048e24 <+0>: push %ebp 
    0x08048e25 <+1>: mov %esp,%ebp 
    0x08048e27 <+3>: and $0xfffffff0,%esp 
    ... 

> < 3で命令の目的は何ですか? つまり、$espは16桁のアドレスを指している必要がありますか?

答えて

9

システムV AMD64 ABI(x86-64 ABI)には、16バイトのスタックアライメントが必要です。 doubleには8バイトのアライメントが必要であり、SSE拡張には16バイトのアライメントが必要です。 -mpreferred-stack-boundaryオプションのそのドキュメントの

gccdocumentationポイントを:num個のバイト境界に上げ2に整列スタック境界を維持する

-mpreferredスタック境界 = NUM​​

試み。 -mpreferred-stack-boundaryが指定されていない場合、デフォルトは4(16バイトまたは128ビット)です。

警告:-mpreferredスタック境界、無効SSE拡張とx86-64のアーキテクチャ用のコードを生成する場合 = 3は、8バイト境界に整列され、スタック境界を維持するために使用することができます。 x86-64 ABIは16バイトのスタックアライメントを必要とするため、ABIは互換性がなく、スタック領域が重要な制限である制御された環境で使用することを意図しています。このオプションは、16バイトのスタックアライメント(標準ライブラリの関数など)でコンパイルされた関数が、整列されていないスタックで呼び出されると、間違ったコードになります。この場合、SSE命令は、不整合なメモリアクセストラップにつながる可能性があります。また、可変長引数は、16バイトの整列したオブジェクト(x87 long doubleと__int128を含む)に対して正しく処理されず、結果が正しくありません。ライブラリを含め、すべてのモジュールを-mpreferred-stack-boundary = 3でビルドする必要があります。これには、システムライブラリと起動モジュールが含まれます。

+1

-m32フラグを指定してコンパイルすると、それは保持されますか? – Bush

+0

@Bush私はSSEのために '-m32'で16バイトを使うと思います。 – ouah

+0

まあ、すべてのx86-64 ABIがそうしているわけではないので、人々がx86-64 ABIだけを偽装していると私はいつも少し苛立ちます。この場合、Ubuntuの文脈では、どのABIが意味されているかははっきりしていますが、必ずしもそうであるとは限りません。 –

関連する問題