들어가는말
cc main.c
./a.out
Shell
복사
컴파일하면 자동으로 실행파일을 만들어주는건 우리는 이미 잘 알고 있다. 어셈블리어로 작성해서 기계어로 변환된다고 어디선가 들어본거 같은데, c 로만 작성했지 어셈블리어를 한번도 보지 못했다. 어셈블리어는 조상님이 변환해준것일까?
어셈블리어를 보지 못한것은 똑똑한 컴파일러님이 알아서 C → 어셈블리어 → 기계어 로 중간 에셈블리어 단계를 알아서 해준것이다.
컴파일러를 믿지 못하고 C → 어셈블리어로 만들고 고쳐진 어셈블리어 → 기계어로 컴파일하고 싶은 경우가 있을 수 있다. (예를 들어, 극한으로 성능을 끌어올리기위해 어셈블리 최적화까지 진행해야할 경우….)
예시코드
// main.c
#include <unistd.h>
int main(void)
{
write(1, "Hello World", 11);
return (0);
}
C
복사
이런 코드를 cc -S main.c 로 컴파일해보면, 아래와 같이 main.s파일이 얻어진다.
이 mian.s를 수정한뒤에 cc main.s하면 어셈블리수준까지 최적화된 실행파일을 얻어낼 수 있다!(내가 컴파일러보다 최적화를 잘한다면..)
// main.s
.section __TEXT,__text,regular,pure_instructions
.build_version macos, 12, 0 sdk_version 13, 1
.globl _main ; -- Begin function main
.p2align 2
_main: ; @main
.cfi_startproc
; %bb.0:
sub sp, sp, #32
stp x29, x30, [sp, #16] ; 16-byte Folded Spill
add x29, sp, #16
.cfi_def_cfa w29, 16
.cfi_offset w30, -8
.cfi_offset w29, -16
mov w8, #0
str w8, [sp, #8] ; 4-byte Folded Spill
stur wzr, [x29, #-4]
mov w0, #1
adrp x1, l_.str@PAGE
add x1, x1, l_.str@PAGEOFF
mov x2, #11
bl _write
ldr w0, [sp, #8] ; 4-byte Folded Reload
ldp x29, x30, [sp, #16] ; 16-byte Folded Reload
add sp, sp, #32
ret
.cfi_endproc
; -- End function
.section __TEXT,__cstring,cstring_literals
l_.str: ; @.str
.asciz "Hello World"
.subsections_via_symbols
Assembly
복사
-S는 어셈블러호출전까지만 넓은 의미의 컴파일을 진행해준다. 자세한 내용는 man cc 를 참고!