2010-12-20 11 views
5

最適化を有効にしてCまたはC++コードをコンパイルすると、d GCCは関数を16バイト境界(IA-32上)に揃えます。関数が16全くランダムであるように思えませんいくつかのバイト、とバイト、GCCパッド、それをより短い場合:GCC関数のパディング値

19: c3      ret 
1a: 8d b6 00 00 00 00  lea 0x0(%esi),%esi 

常に8d b6 00 00 00 00 ...または8d 74 26 00のいずれかのようです。

関数の埋め込みバイトは意味を持ちますか?

+0

私はGCCが関数整列用の埋め込みに0を使用していたのですが、おそらくあまり役​​に立たないソースを指摘することはできません... – William

答えて

6

パッディングはgccではなくアセンブラで作成されます。それは単に.alignディレクティブ(または同等のもの)を見るだけで、埋め込まれるスペースが関数内(関数のループのアライメント)や関数間にあるかどうかわからないため、NOPを挿入する必要があります。現代のx86アセンブラは、可能な限り多くのサイクルを費やす意図で、可能な限り最大のNOPオペコードを使用します。

個人的には、私は最適化技術としてのアラインメントに非常に懐疑的です。私はそれがずっと助けているのを見たことはありませんし、総コードサイズ(とキャッシュ利用率)を大幅に上げることによって間違いなく傷つけることがあります。 -Os最適化レベルを使用している場合、デフォルトではオフになっていますので、何も心配はありません。そうしないと、適切な-fオプションですべてのアラインメントを無効にすることができます。

+0

それは正しいように見えます。 '-S'出力にはパディングno-opsがありません。 –

2

命令lea 0x0(%esi),%esiだけ%esi%esiの値をロードする - それは、それが実行されるなら、それは効果がないであろうことを意味する無操作(又はNOP)、ません。

これは単なる命令で、6バイトのNOPです。 8d 74 26 00は同じ命令のちょうど4バイト符号化です。

+0

しかし、それは到達可能な命令ではありません( 'ret'の後にあります) 、 それは...ですか? –

+0

@Alex B:直接には到達できません(ただし、ジャンプすることはできます)。関数内で実行可能なパディングを生成する理由がしばしばあります。そのため、GCCは関数の最後に同じパディングアルゴリズムを再利用する可能性が高いです。 – caf

1

アセンブラでは、最初に.alignディレクティブが表示されます。このアドレスが関数本体内にあるかどうかわからないので、NULL 0x00バイトを出力することはできず、NOP0x90)を生成する必要があります。しかしながら

lea esi,[esi+0x0] ; does nothing, psuedocode: ESI = ESI + 0 

このコードは、(例えば、ループアライメント)機能本体内に収まるように起こった場合、leaバージョンははるかになり

nop 
nop 
nop 
nop 
nop 
nop 

よりも少ないクロックサイクルで実行します速く、まだ "何もしていない"。

関連する問題