2016-08-18 7 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 = 3; 
if (argc != 0) 
    a = argc + 3; 

일명

int a = argc ? 3 + argc : 3;