你真的了解Linux下gcc編譯器的工作過程嗎?

2020-12-11 老張話IT

小豆丁:老張!老張!

老張:幹嘛?

小豆丁:咋啦?愁眉苦臉的,是不是又被媳婦給揍了?

老張:開玩笑,我在家那就是相當於老虎的存在,誰敢揍我!

媳婦:老張,你說啥?我沒聽清,你再說一遍?

老張:我是老虎,你是武松......

小豆丁:哈哈哈...哈哈哈...老張!你又慫了...

老張:要是沒事的話就趕緊給我圓潤的離開!!!

小豆丁:有事有事!嘿嘿,我想問問,啥事可執行程序啊?

老張:就是可以執行的程序。

小豆丁:額...具體說說唄...

老張:哼,不想說!

小豆丁:我錯了,老張,不該笑話你,你就跟我說說吧!

老張:看在你態度還算誠懇的態度上,就跟你說說吧!可執行程序,實際上就是計算機可以執行的指令的集合,我們在電腦上寫好的程序代碼,經過編譯器的編譯,最終形成的就是可執行程序,這樣計算機就可以按照代碼中想要表達的功能進行工作了。

小豆丁:那編譯器是怎麼把代碼編程可執行程序的啊?

老張:這個過程就有點複雜了。我們以Linux作業系統gcc編譯器為例,來看下對C程序的編譯處理過程。

小豆丁:嗯嗯,快講吧,我已經準備好記錄了!

老張:計算機只認識二進位0和1這種文件,而我們寫的C程序顯然不是二進位文件,這就需要編譯器對我們寫好的程序進行編譯,使之變成計算機可以識別的二進位文件,也就是你剛剛所問的可執行程序。從C程序文件到可執行程序,可以分為四個過程。

小豆丁:哪四個過程啊?

老張:第一個就是預處理過程,可以通過gcc編譯器配合用-E選項進行處理,比如下圖,有一個寫好的C語言程序

通過gcc -E hello.c -o hello.i指令,我們可以完成hello.c文件的預處理操作,將預處理操作之後得到的結果保存到hello.i文件中。

小豆丁:那預處理階段編譯器都做什麼工作了。

老張:這個問題問得好,我們可以打開hello.i文件,看看預處理之後的得到的內容,如下圖。

從圖中我們可以看到,代碼有原本的五六行擴充到了八百多行。這是因為在原本程序中,我們通過預處理指令#include包含了頭文件stdio.h,編譯器在預處理過程中會將包含的頭文件替換進我們的程序中,所以看到預處理後文件的代碼量增加很多。

小豆丁:那預處理階段只是進行頭文件的替換嗎?

老張:當然不是了,在預處理階段,除了頭文件的替換之外,還會進行宏替換和條件編譯的處理。

小豆丁:哦哦,我記住了,那第二個階段呢?

老張:第二個階段叫做彙編階段,我們可以通過gcc -S hello.i -o hello.s指令完成操作,將hello.i文件進行彙編處理,將處理後得到的內容存放到hello.s文件中。如下圖

小豆丁:這個階段都做了什麼工作啊?

老張:我們可以打開hello.s文件看下,發現文件內容已經不是C語言的代碼了,在這個階段,編譯器會把我們的代碼轉換成彙編指令,如下圖

小豆丁:是不是從C語言的代碼轉換成彙編指令,計算機就更容易理解和執行了?

老張:你說得對,值得表揚!

小豆丁:哈哈,本豆丁也是很聰明的,勵志要稱為一名優秀的程式設計師!

小豆丁:那第三個階段是什麼啊?

老張:第三個階段是編譯階段,在這個階段編譯器會將彙編文件轉換成二進位文件,我們把轉換後的二進位文件稱為目標文件,可以用gcc -c hello.s -o hello.o指令完成操作,具體如圖。

小豆丁:老張,這個hello.o文件我打開後怎麼看不懂啊,都是亂碼啊?

老張:看不懂是正常的,因為這是個二進位文件,已經不是我們所能理解的代碼範疇內了。

小豆丁:既然這是一個二進位文件,是不是計算機就能理解了?是不是我們就可以執行它了?

老張:還不能,雖然hello.o是一個二進位文件,但是還不能執行,我們還需要最後一步操作,叫做連結,將程序執行過程中需要用到的一些庫和運行時文件連結到hello.o上,形成最終的a.out可執行程序,才能運行。

小豆丁:哦,還要連結庫和相關文件啊,那最後一步怎麼操作啊?

老張:最後一步比較簡單,用gcc hello.o指令就可以,最後會生成可執行程序a.out,這個時候就可以運行了,如下圖。

小豆丁:哦,我懂了,我們寫好的C語言程序,要經過編譯器編譯才能成為可以運行的程序,而這個編譯的過程分為四步,分別是預處理、彙編、編譯和連結,每一步都有自己的功能和作用。

老張:不錯不錯,孺子可教也。

小豆丁:謝謝老張,我走了,趕緊回去敲個代碼試試去!哈哈!

小豆丁:還有啊,沒事不用總惹你媳婦生氣了,看把你揍的!

老張:......

老張:喜歡老張的話,就關注我吧,每天分享一個IT小知識!

相關焦點

  • CMake設置arm-linux-gcc交叉編譯器
    主機:Ubuntu10.04交叉編譯器:EABI-4.3.3本文引用地址:http://www.eepw.com.cn/article/201611/319327.
  • gcc、arm-linux-gcc和arm-elf-gcc的關係?
    總的來說,如果真正了解了上面 3 個軟體包的作用,自然就明白 GCC 是如何工作的。三、交叉編譯交叉編譯(或交叉建立)是這樣一種過程,它在一種機器結構下編譯的軟體將在另一種完全不同的機器結構下執行。一個常見的例子是在 PC 機上為運行在基於 ARM、PowerPC或 MIPS 的目標機的編譯軟體。
  • c編譯器so easy,gcc c編譯器生成、使用動靜態庫
    第一章程序開發人員大多接觸過c編譯器,請注意,不要將c編譯器和編輯器弄混淆哦。本文對c編譯器的講解,同樣基於gcc c編譯器,本文主要目的在於對linux環境下gcc c編譯器生成和使用靜態庫和動態庫予以介紹。此外,本文為系列教程第一篇——基本概念篇,之後將帶來另外兩篇。
  • Linux下C編程基礎之:gcc編譯器
    gcc不僅功能強大,而且可以編譯如C、C++、ObjectC、Java、Fortran、Pascal、Modula-3和Ada等多種語言,而且gcc是一個交叉平臺編譯器,它能夠在當前CPU平臺上為多種不同體系結構的硬體平臺開發軟體,因此尤其適合在嵌入式領域的開發編譯。本章中的示例,除非特別註明,否則均採用4.x.x的gcc版本。
  • Linux GCC常用命令
    而 GCC 也不再單只是 GNU C 語言編譯器的意思了,而是變成了 GNU Compiler Collection 也即是 GNU 編譯器家族的意思了。另一方面,說到 GCC 對於作業系統平臺及硬體平臺支持,概括起來就是一句話:無所不在。
  • Linux下C應用程式開發
    本文介紹了在 Linux 下能用於 C 應用程式開發和調試的工具. 本文的主旨是介紹如何在 Linux 下使用 C 編譯器和其他 C 編程工具, 而非 C 語言編程的教程.  GNU C 編譯器  GNU C 編譯器(GCC)是一個全功能的 ANSI C 兼容編譯器. 如果你熟悉其他作業系統或硬體平臺上的一種 C 編譯器, 你將能很快地掌握 GCC. 本節將介紹如何使用 GCC 和一些 GCC 編譯器最常用的選項.
  • ARM-linux-gcc交叉編譯工具提示arm-linux-gcc can not find
    在Ubuntu12.04下安裝了arm-linux-gcc後,編譯Linux內核發現提示arm-linux-gcc can not find,查找了相關的網絡資料找到了答案
  • 方舟編譯器 Toy Runtime 可以運行 Hello World 了
    方舟編譯器 runtime 參考實現 pacific 發布了 0.1 版本,支持運行基於方舟編譯器的 Hello World 程序。發布公告介紹,pacific 開發團隊使用 QEMU 提供 AArch64 架構支持,將方舟編譯器的 Java 環境巧妙地用 GNU/Linux 的方式仿製了這套可以跑 Hello World 程序的 Toy Runtime。據了解,pacific 是目前業內首個方舟編譯器 runtime 實現,「實現了從 0 到 1 的一個跨越」。
  • 如果你想學C語言,下載哪個編譯器好?
    C語言這個東西現在用的人很少,一般都是用java的多,不過對於我來講,我一看C語言就親切,就想寫,工作上不一定能用得到,但是C語言作為作為所有高級語言的爸爸,多學一點有助於理解一些底層的東西,下面我就跟大家說一下想學C語言下載哪個編譯器好。
  • 以Linux系統上的gcc為例,解密C語言編譯背後的全過程!
    在這個網際網路時代,很多人都選擇了計算機專業,而只要是計算機專業的小夥伴,可能都會學C語言,但是大家是否都清楚C語言編譯的完整過程呢,今天我就帶著大家一起來做個解密吧。 C語言相對於彙編語言是一種高級語言,要想在系統上運行,需要通過編譯器把它轉換成機器能夠讀懂的可執行的代碼。
  • 一次搞定 Arm Linux 交叉編譯
    程序的編輯——》編譯——》運行,整個過程都是在一臺 X86 電腦上。當我們開始接觸嵌入式開發後,事情變的不一樣了,你在電腦上寫程序,在電腦上編譯出可執行文件,最後這個可執行文件需要下載到你的開發板上運行。程序最後運行的環境變了,比如你的開發板是基於 Arm 的——程序在 X86 上編輯,編譯,最終運行在另一個和 X86 完全不同的架構的 Arm 晶片上。
  • 技多不壓身——從一個編譯器的"bug"談起
    除了解決方法,我還給同事提了一條建議:仔細閱讀所有編譯選項,看看有沒有類似的強假設。但是畢竟軟體是人來寫的,有人的地方不可避免的有人為失誤(bug),很多時候會遇到像本文這樣的bug,牽涉到下一層的東西。所以,要想成為一個優秀的軟體工程師,需要對從上到下的體系結構都有一定了解。這一點,復旦計算機學院的課程設計就很好,趙一鳴院長就說,培養的學生要建立從基本電路,到製作CPU,到計算機體系結構,設計編譯器、作業系統的全方面知識體系。
  • Linux下C編程基礎之:本章小結與思考與練習
    3.8 本章小結本章是Linux中進行C語言編程的基礎,首先講解了C語言編程的關鍵點,這裡關鍵要了解編輯器、編譯連結器、調試器及項目管理工具等概念。
  • 事實證明 Linux 永遠是 number 1
    #include <stdio.h>int main() {    int linux = 701;    printf("%d", linux);    return 0;}夠簡單吧。真的嗎?
  • 最小的Linux系統製作過程詳解
    製作這樣一個小系統最大的意義在於,你可以通過製作系統了解linux的啟動過程,學會ramdisk的使用,讓你在短時間內學到更多的linux知識. 當然,你會得到很大的樂趣.這個項目只是做一個具有基本特徵的linux系統,如果你想自己做一個具有完整功能的linux,請閱讀Linux From Scratch (LFS)文檔.
  • Linux系統下多線程程序編譯makefile文件
    在Linux下,編譯一個多線程的程序命令為:本文引用地址:http://www.eepw.com.cn/article/201609/305140.htmgcc -lpthread -o file
  • (宇宙最強C/C++編譯器)樂創DIY C語言講義​——2.6 GCC的使用
    還有一個問題,GCC只是Linux作業系統下的一個編譯器,難道我們還要為了一個編譯器而放棄了人性化的Windows去安裝一個不那麼適合個人使用的Linux?因此GNU裡面有一幫人不肯放棄Windows市場這麼大的蛋糕,開發了MinGW這個軟體,其實就是Windows底下的GNU C編譯器,當然支持C++也是必須的。
  • 華為方舟編譯器深入解讀:已有45款第三方應用
    8月31日,華為方舟編譯器(OpenArkCompiler)正式開源,官網已上線,原始碼包、二進位包已提供下載,相關文檔、演示等資料也一應俱全。本次方舟編譯器開源的是編譯器框架部分源碼,包括編譯器中間表示(IR)和語言編譯實現,同時搭配編譯器其他二進位組件,實現Java程序到aarch64彙編指令的編譯過程。
  • ARM Linux根文件系統Root Filesystem的製作
    = /usr/local/arm/3.4.1/bin/arm-linux-當然CROSS_COMPILE由你自己的編譯器位置決定,然後# make menuconfig# make# make install注意配置的時候把一些uCLinux Only的東西去掉,不然會錯;配置的時候還可以修改安裝位置,默認是在Busybox下的
  • 推薦一款強大的在線編譯器
    原創不易,如果覺得文章不錯,記得分享點讚哦^_^前言今天給大家推薦一個強大的在線編譯器,滿足初學者幾乎所有的學習需求(免於折騰IDE),滿足想寫