2016-12-23 13 views
1

私は最近、危険なプログラムを悪用し、x86-64アーキテクチャのgccのバージョンの違いについて興味深いものを見つけました。この改善の原因と利点は、gccバージョン> 4.9.0とgccバージョン<4.9?

  1. getsの不法使用方法はこちら問題ではありません。

  2. getsを他の機能に置き換えると、問題は変わりません。

    #include <stdio.h> 
    int main() 
    { 
        char buf[16]; 
        gets(buf); 
        return 0; 
    } 
    

    は、Iフラグ-m32 -fno-stack-protector -z execstack -gでプログラムを分解しgcc.godbolt.orgを使用:


このは、私が使用するソースコードです。バージョンとの逆アセンブルコードで

gcc> = 4.9.0

lea  ecx, [esp+4]   # begin of main 
and  esp, -16 
push DWORD PTR [ecx-4]  # push esp 
push ebp 
mov  ebp, esp 
/* between these comment is not related to the question 
push ecx 
sub  esp, 20 
sub  esp, 12 
lea  eax, [ebp-24] 
push eax 
call gets 
add  esp, 16 
mov  eax, 0 
*/ 
mov  ebp, esp    
mov  ecx, DWORD PTR [ebp-4] # ecx = saved esp 
leave 
lea  esp, [ecx-4] 
ret        # end of main 

しかし、gccの< 4.9.0だけのバージョンと:

push ebp      # begin of main 
mov  ebp, esp 
/* between these comment is not related to the question 
and  esp, -16 
sub  esp, 32 
lea  eax, [esp+16] 
mov  DWORD PTR [esp], eax 
call gets 
mov  eax, 0 
*/ 
leave 
ret        # end of main 

私の質問は:カウ分解されたコードとそのメリットについてのこの相違点は何ですか?このテクニックの名前はありますか?

+1

注:[gets()を使用しないでください。危険です](http://stackoverflow.com/q/1694036/2173917)。代わりに['fgets()'](https://linux.die.net/man/3/fgets)を使用してください。 –

+1

これは最適化の結果です –

+2

異なるコンパイラ構成。 'gcc -v'を使用して設定を比較する – LPs

答えて

0

私は、実際の値なしで確かに言うことはできません。

and  esp, 0xXX    # XX is a number 

が、これは、ABIが必要とするよりも大きな値にスタックを整列するために多くの余分なコードのように見えます。

編集値は-16です。これは32ビットの0xFFFFFFF0または64ビットの0xFFFFFFFFFFFFFFF0です。したがって、これは実際には16バイトにスタックアライメントされている可能性が高いため、SSE命令を使用する可能性があります。コメントに記載されているように、> = 4.9.0バージョンには、スタックポインタだけではなくフレームポインタも整列するため、より多くのコードがあります。

+0

申し訳ありませんが、 '-16'を' 0xXX'に置き換えたのは間違いです。本当にごめんなさい ! – lzutao

+0

@ lzutao次にスタックアライメントコードです。 – Olivier

+0

ありがとうございます。しかし、gccバージョンとのデータアライメントもあります。<** 4.9.0 ** – lzutao

関連する問題