두근두근 울렁울렁 가슴 뛰지만 무섭고도 두려워서 겁이 나지만 오늘 발견한 재미난 것 입니다 :)
발단은... 얼마 전 제가 사용하는 리눅스 배포본들 중 하나에 포함된 gcc 가 gcc-7.3.1 로 바뀌었습니다. 제가 사용하는 또 다른 배포본에서 gcc-6.4.0 으로 바뀐 뒤에도 상당히 오래동안 gcc-5.4.0 을 고집하다가 gcc-6 을 건너뛰고 gcc-7 로 가네요. 참고로, 현재 gcc 의 최신 시리즈는 8 입니다. 컴파일러가 달라졌으니 무엇이 바뀌는 것일까 궁금해졌습니다. 문서를 읽다가... 재미난 기능이 생겼더군요 :)
저는 어셈블리를 거의 모릅니다. 그렇지만 C 코드를 조금 변경하는 것이 어떤 영향을 줄까 궁금할 때 어셈블리로 출력해서 비교해보곤 해요. 예를 들어, -O0 옵션으로 최적화를 하지 않은 것과 -O2 옵션으로 최적화하는 것의 차이가 뭘까 궁금할 때 디버거까지 쓸 필요는 없겠죠. 만일, file.c 라는 C 코드를 file.s 라는 어셈블리 코드로 보고 싶다면 다음과 같은 명령을 내리면 됩니다. (최적화 옵션을 추가로 줘도 되겠죠.)
gcc -c file.c -o file.s -s -S
새로운 옵션으로
-fverbose-asm 이 생겼다네요. 예를 들어, C 코드가 아래와 같다면
int test (int n){ int i; int total = 0; for (i = 0; i < n; i++) total += i * i; return total;}다음과 같은 형식으로 변환해준다고 합니다. (이 예는 x86_64 에서 크기 최적화 옵션인 -Os 를 준 경우입니다.)
.text .globl test .type test, @@functiontest:.LFB0: .cfi_startproc# example.c:4: int total = 0; xorl %eax, %eax # <retval># example.c:6: for (i = 0; i < n; i++) xorl %edx, %edx # i.L2:# example.c:6: for (i = 0; i < n; i++) cmpl %edi, %edx # n, i jge .L5 #,# example.c:7: total += i * i; movl %edx, %ecx # i, tmp92 imull %edx, %ecx # i, tmp92# example.c:6: for (i = 0; i < n; i++) incl %edx # i# example.c:7: total += i * i; addl %ecx, %eax # tmp92, <retval> jmp .L2 #.L5:# example.c:10: } ret .cfi_endproc