引言在日常的學(xué)習(xí)和工作中, 我們常常使用IDE(集成開發(fā)環(huán)境,Integrated Development Environment)進(jìn)行開發(fā),比如嵌入式經(jīng)常用到的Keil, IAR等等。當(dāng)我們編寫一段代碼后,只需要輕輕一點(diǎn)IDE中編譯按鈕,工具就會(huì)自動(dòng)幫我們生成可執(zhí)行文件 。IDE的“智能化”在背后幫我們做了很多工作,從一個(gè).c源文件是如何一步一步生成可執(zhí)行文件的呢? 今天我們就分析下背后的原理和過程。 編譯過程分析我們還是以最經(jīng)典的HelloWorld為例子,這里用C語言來編寫: #include <stdio.h>int main(void){ printf('Hello World .\n'); return 0;} 編譯過程可以分四個(gè)階段:
使用-E參數(shù)來生成.i文件,具體指令:
我們用vi打開HelloWorld.i文件查看下內(nèi)容: 從內(nèi)容我們可以看出,短短的幾行HelloWorld.c在預(yù)處理后卻是高達(dá)800多行代碼,其中前面的800多行都stdio.h的內(nèi)容,全都包含進(jìn)來了,只有最后的幾行代碼才是我們寫的~ 相信這么大家都理解預(yù)處理的作用了吧。 2. 編譯: (.i—>.s)轉(zhuǎn)換為匯編語言文件 這個(gè)階段編譯器主要做詞法分析,語法分析,語義分析等,檢查無錯(cuò)誤后,把代碼翻譯成匯編語言。 使用-S參數(shù)來生成.s文件,具體指令: gcc -S HelloWorld.i -o HelloWorld.s 我們用vi打開HelloWorld.s文件查看下內(nèi)容: 可以看到.s文件的內(nèi)容都是一些匯編指令,與我們的預(yù)想是一致的。 3. 匯編:(.s—>.o) 得到目標(biāo)文件(在Windows中.obj文件格式,linux中.o文件) 我們知道在計(jì)算器中只認(rèn)識(shí)機(jī)器語言,即0或1,因此在上一步編譯得到的匯編文件(匯編本質(zhì)就是機(jī)器指令的助記符,什么是助記符呢? 比如機(jī)器碼1000010000101111,用asd來代替,相信大家更傾向于記asd,而不是一大串二進(jìn)制碼吧~~) ,而匯編就是將匯編代碼轉(zhuǎn)為機(jī)器代碼,本質(zhì)就是一種翻譯的過程。 使用-c參數(shù)來生成.o文件,具體指令:
可以看到成功生成了HelloWorld.o文件, 上面說過匯編就是翻譯匯編指令為機(jī)器指令, 因此.o內(nèi)容都是二進(jìn)制(0和1),故我們將不打開看拉~ 4. 鏈接:到了最后一步,并是將之前得到的各個(gè)機(jī)器代碼和庫文件(當(dāng)然也是機(jī)器代碼)按照一定規(guī)則合并成一個(gè)可執(zhí)行的文件。 在gcc編譯工具鏈中使用ld命令進(jìn)行鏈接,考慮到鏈接時(shí)需要提供鏈接規(guī)則或指定腳本配置,這里為了簡(jiǎn)化學(xué)習(xí),我們可以直接使用gcc工具鏈提供的默認(rèn)規(guī)則,直接調(diào)用gcc來鏈接即刻。 gcc HelloWorld.o -o HelloWorld.exe 其中-o是指定生成可執(zhí)行文件名(隨意,如果不指定默認(rèn)生成名a.out), 我們來執(zhí)行下: 成功打印了“Hello world.”信息 總結(jié)好了,經(jīng)過上面所述,相信大家都能清楚從一個(gè)源文件編譯生成可執(zhí)行文件的過程拉: 源文件(.c, .cpp) ---> 預(yù)處理(.i) ---> 編譯(.s) ---> 匯編(.o) ---> 鏈接(elf或.exe可執(zhí)行文件)。 好啦,今天的分析到此,對(duì)嵌入式,物聯(lián)網(wǎng)感興趣的小伙伴,記得點(diǎn)擊收藏,轉(zhuǎn)發(fā),關(guān)注,不迷路~ |
|