1. 程式人生 > >用gcc編譯成可執行程式細節過程

用gcc編譯成可執行程式細節過程

#gcc hello.c

該命令將hello.c直接生成最終二進位制可執行程式a.out

這條命令隱含執行了(1)預處理、(2)彙編、(3)編譯並(4)連結形成最終的二進位制可執行程式。這裡未指定輸出檔案,預設輸出為a.out。

從上面我們知道GCC編譯原始碼生成最終可執行的二進位制程式,GCC後臺隱含執行了四個階段步驟。

GCC編譯C原始碼有四個步驟:

預處理-----> 編譯 ----> 彙編 ----> 連結

現在我們就用GCC的命令選項來逐個剖析GCC過程。

1)預處理(Pre-processing)

  在該階段,編譯器將C原始碼中的包含的標頭檔案如stdio.h編譯進來,使用者可以使用gcc的選項”-E”進行檢視。

用法:#gcc -E -o hello.i hello.c 

作用:將hello.c預處理輸出hello.i檔案。

2)編譯階段(Compiling)

 第二步進行的是編譯階段,在這個階段中,Gcc首先要檢查程式碼的規範性、是否有語法錯誤等,以確定程式碼的實際要做的工作,在檢查無誤後,Gcc把程式碼翻譯 成組合語言。使用者可以使用”-S”選項來進行檢視,該選項只進行編譯而不進行彙編,只生成彙編程式碼。

選項 -S

用法:[root]# gcc –S –o hello.s hello.i 

作用:將預處理輸出檔案hello.i編譯成hello.s檔案。

[[email protected]

hello-gcc]# ls

hello.c  hello.i  hello.s

3)彙編階段(Assembling)

 彙編階段是把編譯階段生成的”.s”檔案(此檔案可以是原始檔*.c或者是彙編檔案*.s,如果是原始檔,會自動編譯後再彙編)轉成二進位制目的碼.

選項 -c

用法:[root]# gcc –c –o hello.o hello.s 

作用:將彙編輸出檔案test.s編譯輸出test.o檔案。

[root]# gcc -c -o hello.o hello.s

[root]# ls

hello.c  hello.i  hello.o  hello.s

4)連結階段(Link)

  在成功編譯之後,就進入了連結階段。

無選項鍊接

用法:[root]# gcc –o hello hello.o 

作用:將編譯輸出檔案hello.o連結成最終可執行檔案hello

[root]# ls

hello.c  hello  hello.i  hello.o  hello.s

執行該可執行檔案,出現正確的結果如下。

[[email protected] Gcc]# ./hello

Hello World!

gcc doc的原版解釋:

-E                       Preprocess only; do not compile, assemble or link
-S                       Compile only; do not assemble or link
-c                       Compile and assemble, but do not link
-o <file>                Place the output into <file>

函式庫連線

重新檢視這個小程式,在這個程式中並沒有定義”printf”的函式實現,且在預編譯中包含進 的”stdio.h”中也只有該函式的宣告,而沒有定義函式的實現,那麼,是在哪裡實現”printf”函式的呢?最後的答案是:系統把這些函式實現都被 做到名為libc.so.6的庫檔案中去了,在沒有特別指定時,gcc會到系統預設的搜尋路徑”/usr/lib”下進行查詢,也就是連結到 libc.so.6庫函式中去,這樣就能實現函式”printf” 了,而這也就是連結的作用。

你可以用ldd命令檢視動態庫載入情況:

[root]# ldd hello

libc.so.6 => /lib/tls/libc.so.6 (0x42000000)

/lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0x40000000)

函式庫一般分為靜態庫和動態庫兩種。靜態庫是指編譯連結時,把庫檔案的程式碼全部加入到可執行檔案中,因此生成的檔案比較大,但在執行時也就不再需要 庫檔案了。其後綴名一般為”.a”。動態庫與之相反,在編譯連結時並沒有把庫檔案的程式碼加入到可執行檔案中,而是在程式執行時由執行時連結檔案載入庫,這 樣可以節省系統的開銷。動態庫一般字尾名為”.so”,如前面所述的libc.so.6就是動態庫。gcc在編譯時預設使用動態庫。

相關推薦

gcc編譯執行程式細節過程

#gcc hello.c 該命令將hello.c直接生成最終二進位制可執行程式a.out 這條命令隱含執行了(1)預處理、(2)彙編、(3)編譯並(4)連結形成最終的二進位制可執行程式。這裡未指定輸出檔案,預設輸出為a.out。 從上面我們知道GCC編譯原始碼生成最

【ndk】直接使用ndk提供的arm-linux-androideabi-gcc編譯android執行程式

1、背景 經常使用linux交叉工具類的朋友都知道,在已安裝交叉編譯工具鏈後要交叉編譯得到linux可執行檔案只需要執行如下類似的命令(如編譯hello.c生成hello可執行檔案): arm-linux-gcc hello.c -o hellohello.c的程式碼非常

freeze.py打包python程式執行程式(linux)

    為了將一批py程式打包成可執行程式以便釋出,之前使用過cxfreeze來完成,非常方便,只需要下載cx_freeze的rpm安裝包,安裝成功後 $cxfreeze your.py 就將py程式生成到當前目錄下面的dist資料夾裡面,也可以用 $cxfreeze –install-dir=”your/

Linux下Makefile製作動態庫和靜態庫並編譯生成執行程式

Makefile 一個工程中的原始檔不計其數,其按型別、功能、模組分別放在若干個目錄中,makefile定義了一系列的規則來指定,哪些檔案需要先編譯,哪些檔案需要後編譯,哪些檔案需要重新

[PYTHON]_ELVE_Python原始碼檔案編譯執行檔案(支援macOS High Sierra和window 10)

#0x01 背景 這兩天寫了一個抽獎的Python指令碼,要生成可執行檔案,總不能一直在sublime上執行吧,或者執行前先安裝Python,所以就查了一下怎麼生成可執行檔案,本篇包括mac下和win下,經本人測試,mac下生成.app(mac下的可執行檔案為.app字尾)較win下容易一些。 我用的Py

使用EXE4J將Java程式打包執行程式(.exe檔案)教程

作者:翁鬆秀 使用EXE4J將Java程式打包成可執行程式(.exe檔案)教程 [TOC] 由於公司需要做一個對資料庫伺服器的監控程式,用的swing來實現的一個java桌面應用程式,所以需要將做好的監控程式打包成.exe檔案,以便監控人員配置監控資訊。所以研究了一下如何

Linux(CentOS)下把python指令碼轉化執行程式

1. pyinstaller安裝pyinstaller:tarjvxf pyinstaller-1.5.tar.bz2./Configure.py打包程式:先執行:./Makespec.py–onefile yourprogram.py預設會在當前目錄下生成一個spec檔案。

關於python使用pyrex編譯執行檔案的問題

    轉自我在百度的blog: http://hi.baidu.com/python23/    這個問題是相當有意義的,如果有了比較好的方法,python完全可以用來開發商業軟體,而不用擔心原始碼洩露。     前兩天我在網上看了看,有很多的人在問這個問題。大部分的人都在

NDK編譯C執行程式

現有這樣一個helloworld.c的原始檔,如下: #include <stdio.h> int main(){ printf("Hello world!\n"); } 如何將它進行編譯,並在Android上執行?這就是本文的目標。 原理 (如果只想

Linux中將c檔案編譯執行檔案的方法

c檔案:project.c 方法一 //預編譯,生成已編譯通過的C原始程式 *.i  gcc -E project.c -o project.i //編譯,生成組合語言原始程式 *.s  gcc -S project.i -o project.s //連結,生成可執行程

Java Swing 專案編譯exe執行程式(一)

初始工作:新建資料夾,把jdk拷貝進去(使用者機不一定安裝java環境,所以我們要把jdk一塊打包) 一、選擇專案右鍵匯出 二、選擇java - JAR file - next 三、選擇匯出路徑 四、下一步 五、選擇Swing程式,入口frame 六、點選Fin

IDEA打執行jar包時遇到的問題

用IDEA打成可執行jar包,在命令列下執行遇到的問題 1、jar包中提示沒有主清單屬性 2、丟擲異常ClassNotFoundException,如圖 可能的原因及解決: 1、未設定jar包執行的main方法。用解壓軟體開啟jar包,開啟檔案/META-INF/MA

Linux載入啟動執行程式過程(二)直譯器完成動態連結

接著上一篇部落格。前面的工作都是在核心完成的,接下來會回到使用者空間。第一步,直譯器(也可以叫動態連結器)首先檢查可執行程式所依賴的共享庫,並在需要的時候對其進行載入。ELF 檔案有一個特別的節區: .dynamic,它存放了和動態連結相關的很多資訊,例如動態連結器通過它找到

Pyinstaller把Python3.7程式打包執行檔案exe

1、通過pip3 install pyinstaller 安裝成功 2、然後執行命令,首先:需要切換到程式所在的目錄 執行命令 pyinstaller -F -w <檔名.py>,-F代表生成可執行檔案,-w代表需要控制檯,不需要就不用加。 3、等執行結束後,會在程式所在的資料夾生成三個資料

Linux GCC生成執行程式的4個步驟——預處理、編譯、彙編、連結

一,預編譯 操作步驟:gcc -E hello.c -o hello.i 主要作用: 處理關於 “#” 的指令 【1】刪除#define,展開所有巨集定義。例#define portnumber 3333 【2】處理條件預編譯 #if, #ifdef, #if, #elif,#e

Pyinstaller把Python3程式打包執行檔案exe

自己開發一些小工具,但是又懶得去配置環境,索性想著把py程式碼編譯可執行檔案exe 百度了很多,發現了很多牛人的無私奉獻,在此也分享下自己的心得體會。 Windows7 64位作業系統 Python3.3 32位 首先安裝PIP。 pip 是一個安裝Python包的工具

Python:Python程式呼叫C/C++編譯執行檔案

[TODO] 用python程式呼叫C/C++編譯的可執行檔案 ************************華麗的分割線************************ step1:cppexec.cpp #include <iostream> int ad

Pyinstaller把Python3.4程式打包執行檔案exe

最近在學Python語言,照著書上一個用Pygame的例子寫了一個遊戲程式,想把它打包出來,在網上找了很多帖子,但在實際過程中還是遇到了很多問題,所以做個筆記,備忘: Windows7 64位作業系統 Python3.4 64位 pygame1.9.3 64

在window下android-ndk編譯android下執行程式的方法。

環境,win7,與android-ndk-r13b-windows-x86_64,把android-ndk-r13b-windows-x86_64解壓在目當中就可,不用安裝 1,只用gcc工具 D:\android-ndk\android-ndk-r13b\toolcha

py2exe將python檔案轉換exe執行程式

然後用pip install 命令安裝py2exe模組,如果你用的python是2.X,那還需要先安裝pip,這裡就不贅述了。 安裝完成後可在python的IDLE中import py2exe,如果不報錯則說明你安裝成功了: 2、然後將下面程式碼儲存為py_to_exe.py檔案: