2016-08-18 10 views
2

コンパイラの出力を-O3オプションの有無と比較しようとしましたが、最適化されたコードの動作方法を追うことができません。最適化を有効にしたアセンブリコードの読み込み

は、ここでCコードです:

#include <stdio.h> 
#include <limits.h> 

int main(int argc, char *argv[]) { 
    int a = 3; 
    int b = argc; 

    while (b) { 
     ++a; 
     --b; 
    } 

    printf("%d\n", a); 

    return 0; 
} 

そして、これは、最適化することなく、objdumpは出力されます。 preety簡単なルックス:

000000000040052d <main>: 
    #include <stdio.h> 
    #include <limits.h> 

int main(int argc, char *argv[]) { 
    40052d:  55      push %rbp 
    40052e:  48 89 e5    mov %rsp,%rbp 
    400531:  48 83 ec 20    sub $0x20,%rsp 
    400535:  89 7d ec    mov %edi,-0x14(%rbp) 
    400538:  48 89 75 e0    mov %rsi,-0x20(%rbp) 
    int a = 3; 
    40053c:  c7 45 f8 03 00 00 00 movl $0x3,-0x8(%rbp) 
    int b = argc; 
    400543:  8b 45 ec    mov -0x14(%rbp),%eax 
    400546:  89 45 fc    mov %eax,-0x4(%rbp) 

    while (b) { 
    400549:  eb 08     jmp 400553 <main+0x26> 
     ++a; 
    40054b:  83 45 f8 01    addl $0x1,-0x8(%rbp) 
     --b; 
    40054f:  83 6d fc 01    subl $0x1,-0x4(%rbp) 

int main(int argc, char *argv[]) { 
    int a = 3; 
    int b = argc; 

    while (b) { 
    400553:  83 7d fc 00    cmpl $0x0,-0x4(%rbp) 
    400557:  75 f2     jne 40054b <main+0x1e> 
     ++a; 
     --b; 
    } 

    printf("%d\n", a); 
    400559:  8b 45 f8    mov -0x8(%rbp),%eax 
    40055c:  89 c6     mov %eax,%esi 
    40055e:  bf 04 06 40 00   mov $0x400604,%edi 
    400563:  b8 00 00 00 00   mov $0x0,%eax 
    400568:  e8 a3 fe ff ff   callq 400410 <[email protected]> 

    return 0; 
    40056d:  b8 00 00 00 00   mov $0x0,%eax 
} 

しかし、gccのに-O3オプションを追加した後、私はこれだ:

0000000000400470 <main>: 
#include <stdio.h> 
#include <limits.h> 

int main(int argc, char *argv[]) { 
    400470:  8d 47 03    lea 0x3(%rdi),%eax 
    400473:  48 83 ec 08    sub $0x8,%rsp 
    400477:  ba 03 00 00 00   mov $0x3,%edx 
    40047c:  85 ff     test %edi,%edi 
} 

__fortify_function int 
printf (const char *__restrict __fmt, ...) 
{ 
    return __printf_chk (__USE_FORTIFY_LEVEL - 1, __fmt, __va_arg_pack()); 
    40047e:  be 14 06 40 00   mov $0x400614,%esi 
    400483:  bf 01 00 00 00   mov $0x1,%edi 
    400488:  0f 45 d0    cmovne %eax,%edx 
    40048b:  31 c0     xor %eax,%eax 
    40048d:  e8 ce ff ff ff   callq 400460 <[email protected]> 
    } 

    printf("%d\n", a); 

    return 0; 
} 
    400492:  31 c0     xor %eax,%eax 
    400494:  48 83 c4 08    add $0x8,%rsp 
    400498:  c3      retq 

私はスタックと操作以外の任意のジャンプ、または任意の有効なアドオン、サブ手順を参照することはできませんが。誰かが私にこれを説明することはできますか? GCCはループが何をするか把握することができますので

おかげで

答えて

3

あなたのコードは、printf("%d\n", 3 + argc)に最適化されています。

3 + argcは、最初のlea 0x3(%rdi),%eaxです。


実際、gccがかなりループを解決しません

テスト/ CMOVのものがやっているように見える:

int a = argc ? 3 + argc : 3; 
別名

int a = 3; 
if (argc != 0) 
    a = argc + 3; 

関連する問題