索引
前言
在STM32等Cortex-M內核的MCU學習開中,常用的IDE——Keil5
中使用的是ARMCC
,也是一個C語言編譯器。GCC
,GNU Compiler Collection
,同ARMCC
是差不多的一個東西,但是GCC
是自由免費的。
程序編譯過程
gcc
編譯程序很簡單,執行gcc -o helloworld helloworld.c
就可以直接編譯生成可執行文件helloworld
,這個過程也屏蔽了很多步驟,整個編譯過程做了一下工作。
1、預處理
主要是處理C程序中帶"#"的語句,像#include
、#define
、#if
等等這些預處理指令。它們不是C程序本身的組成部分,但卻是必不可少的一部分,有這些預處理語言寫起程序菜更方便。預處理後將程序處理爲後綴命爲.i
的文件。
獲得預處理文件:
gcc -o -E helloworld.i helloworld.c
2、編譯
預處理階段生成的.i文件還不能給程序運行,所以代碼還要繼續處理,到這個階段就是編譯,將.i文件
的代碼編譯處理成彙編文件(.s)
。GCC
生成的就是x86架構
的彙編文件。GCC for ARM
生成的是ARM架構的彙編文件。不同平臺的彙編指令集不一樣,所以相應的平臺使用相應的GCC
。
獲得彙編文件:
gcc -o helloworld.s helloworld.i -S
3、彙編
彙編文件的指令是和處理器指令 一一對應的,這個階段,彙編器會將彙編文件翻譯成可重定位的elf格式可重定位程序文件,即.o文件
可重定位文件:
程序已經包含了能讓處理器運行的指令,但是程序中的全局符號(函數和變量
)位置還沒確定。嗶哩嗶哩這麼多,簡單地說可重定位文件就是就是函數和變量入口地址還沒確定的文件。沒確定那肯定就不能運行。
獲得elf可重定位文件:
gcc -o helloworld.o helloworld.s -c
4、鏈接
如上所說,經過彙編的文件還不能運行。還需要最後這一步:鏈接
,將所有.o文件
鏈接成可執行程序。
鏈接的作用:
- 重定位
- 合併相同權限的段
elf可重定位的程序文件中是按照段(section)
存放程序的,如存放運行的代碼.text
段、存放初始化了的全局變量、靜態局部變量的.data
段,未初始化的全局變量、靜態局部變量的.bss段
等。
執行readelf helloworld.o -S
查看程序段分佈。
GCC常用編譯選項
-o
輸出指定文件名
- gcc -o helloworld helloworld.c
-E
輸出預處理後的代碼文件
- gcc -o helloworld.i helloworld.c -E
-S
輸出編譯生成的彙編文件
- gcc -o helloworld.s helloworld.c -S
-c
輸出鏈接後的可重定位文件
- gcc -o helloworld.o helloworld.c -c
-I
指定頭文件路徑
- gcc -o helloworld helloworld.c -I<include_path>
-g
編譯結果中加入調試信息
- gcc -o helloworld helloworld.c -g
-L
制定庫文件路徑
- gcc -o helloworld helloworld.c -L<lib_path>
-O
制定代碼優化等級,等級越高優化程度越高
- -O0
- -O1
- -O2
- -O3
-static
編譯時使用靜態鏈接庫文件
- gcc -o helloworld helloworld.c -<lib_name> -static
-Wall
輸出警告信息
- gcc -o helloworld helloworld.c -Wall