Compile幕後

習慣使用了具備強大功能的整合工具– IDE(e.g Visual Studio),執行source code(e.g .cpp)僅需點下 建置(Build) 然後,有時是只點下,就完成了許多希望程式去做的事,很方便,但也因此缺乏對於幕後工程的認識。離開了IDE,使用terminal則可以透過下面的指令完成同樣的事情:

1
2
3
$ g++ main.cpp -o main.out #編譯
$ ./main.out #執行
helloworld

編譯透過以上一行簡單的指令,將我們寫的source code編譯成執行檔(在Linux上是.out,在Windows上則是.exe),然後可以直接被電腦執行。簡單的一句指令,過程則可以分為四個步驟,分別是1. 前編譯Preprocessing, 2. 編譯compilation, 3. 組譯assembly 以及 4. 連結linking。
gcc compilation

以下用一支比helloworld更簡單的程式來呈現:

main.cpp

1
2
3
4
#define N 81
int main(){
return 0;//this is the end
}

(以下的程式皆是透過vim進行解碼)

Preprocessing: .cpp -> .ii,

處理#,刪除註解(//, /**/),加以編號。

1
2
3
4
5
6
7
8
9
10
11
$ g++ -E main.cpp -o main.ii
main.ii:
# 1 "main.cpp"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "/usr/include/stdc-predef.h" 1 3 4
# 1 "<command-line>" 2
# 1 "main.cpp"
int main(){
return 0;
}

Compilation: .ii -> .s,

將 .ii檔進行分析以及最佳化,將高階語言翻譯成assembly code。屬於程式建構過程最複雜的環節。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
main.s
$ g++ -S main.ii -o main.s
.file "main.cpp"
.text
.globl main
.type main, @function
main:
.LFB0:
.cfi_startproc
endbr64
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
movl $0, %eax
popq %rbp
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE0:
.size main, .-main
.ident "GCC: (Ubuntu 9.4.0-1ubuntu1~20.04.1) 9.4.0"
.section .note.GNU-stack,"",@progbits
.section .note.gnu.property,"a"
.align 8
.long 1f - 0f
.long 4f - 1f
.long 5
0:
.string "GNU"
1:
.align 8
.long 0xc0000002
.long 3f - 2f
2:
.long 0x3
3:
.align 8
4:

Assembly: .s -> .o,

將assembly code一一翻譯成machine code。

1
2
3
4
5
6
$ g++ -c main.s -o main.o 
^?ELF^B^A^A^@^@^@^@^@^@^@^@^@^A^@>^@^A^@^@
^@^@^@^@^@^@^@^@^@^@X^B^@^@^@^@^@^@^@^@^@^
@@^@^@^@^@^@@^@^L^@^K^@ó^O^^úUHå¸^@^@^
@^@]Ã^@GCC: (Ubuntu 9.4.0-1ubuntu1~20.04.1)
9.4.0^@^@^@^@^@^@^D^@^......

Linking: .o + static library -> .out,

將.o檔連結static library(一大堆.o檔)形成.out檔。

1
2
3
4
5
$ ld -static (一大堆.o檔) 
^?ELF^B^A^A^@^@^@^@^C^@>^@^A^@^@^@À^P^@^@^
^@^@@^@^@^@^@^@^@^@è;^@^@^@^@^@^@^@^@^@^@@
^@8^@^M^@@^@^_^@^^^@^F^@^@^@^D^@^@^@@^@^@^
@^@^@^@^@@^@^@^@^@^@^@^@@^......