程序篇 程式編譯鏈結的過程

2021-09-26 00:07:22 字數 1573 閱讀 3162

乙個原始檔生成最終的可執行檔案的過程可以分為四步:

預編譯編譯

彙編鏈結

如下圖執行過程:

使用gcc命令不跟任何的選項的話,會預設執行預編譯、編譯、彙編、鏈結這整個過程,就會得到乙個可執行檔案,預設為a.out

1.預編譯

gcc -e   hello.c/ *-o  hello.i */    

-e::提示編譯器只執行完預編譯處理就停下來,對應生成乙個 .i檔案

編譯gcc  -s  hello.i  /* -o   hello.s*/  生成彙編指令**

-s:提示編譯器執行完編譯就停下,後續不再進行

彙編gcc   -c  hello.s /* -o  hello.o*/  生成可重定位的二進位制檔案

-c:提示編譯器執行完彙編就停下,後續不再進行。

鏈結gcc  -o  hello  hello.o  生成最終的可執行檔案(hello)

四步分別完成的工作:

一、預編譯階段:  .i 檔案

刪除所有的「#define」,並且展開所有的巨集定義。(做文字替換 ,m10)

處理所有的條件預編譯指令 例如「#if」、「#ifdef」、「#endif」等。

處理「#include」預編譯指令,將被包含的檔案插入到該預編譯指令的位置。(這個過程是遞迴展開的,因為被包含的檔案可能還包含了其他檔案。)

刪除所有的注釋 「//」「/* */」

新增行號和檔案標示名,以便於編譯器產生除錯用的符號資訊及編譯時產生編譯錯誤和警告的時候能夠顯示行號;

保留所有的 #program 編譯器指令,因為編譯器需要它們。

此處引用別人乙個舉例說明:

二、.編譯階段:  .s檔案

詞法分析、語法分析、語義分析、**優化、彙總符號、

編譯過程是整個程式構建的核心部分,編譯成功,會將源**由文字形式轉換為機器語言,編譯過程就是把預處理的檔案進行上述一系列操作最終生成相應的彙編**檔案。

三、 彙編階段

將彙編指令翻譯成二進位制格式,生成各個section,生成符號表

彙編過程呼叫彙編器 as 來完成,是用於 將彙編**轉換成機器可以執行的指令,每一條彙編**都對應著一條機器指令。

四、 鏈結階段

鏈結的主要內容就是把各個模組之間相互引用的部分 正確的銜接起來。他的工作就是把一些指令對其他符號位址的引用加以修正。主要包括位址和空間分配、符號決議、重定位。

合併各個section,調整section的起始位移和段大小

合併符號表,進行符號解析

符號重定位

最基本的鏈結叫做靜態鏈結,就是把每個模組的源**檔案編譯成目標檔案(linux下:.o /windows下:.obj),然後將目標檔案和庫(庫其實就是一組目標檔案的包)一起鏈結形成最終的可執行檔案。

objdump: 檢視目標檔案 或者可執行的目標檔案的構成

readelf : 顯示乙個或者多個elf檔案格式的目標檔案的資訊

ldd :  檢視可執行程式用到哪些共享庫

nm : 檢視程式中函式 和變數的邏輯位址

程式編譯,鏈結過程

c語言的編譯鏈結過程要把我們編寫的乙個c程式 源 轉換成可以在硬體上執行的程式 可執行 需要進行編譯和鏈結。編譯就是把文字形式源 翻譯為機器語言形式的目標檔案的過程。鏈結是把目標檔案 作業系統的啟動 和用到的庫檔案進行組織形成最終生成可載入 可執行 的過程。過程 如下 預處理器 將.c 檔案轉化成 ...

程式的編譯鏈結過程

一段源 到可執行性程式需要經歷預處理 編譯彙編和鏈結等步驟,接下來詳細介紹這些過程 假設檔案main.czhong有如下 include int main 1 巨集定義指令 2 條件編譯 3 標頭檔案包含指令 4 特殊符號處理 不能在標頭檔案中定義全域性變數,因為在標頭檔案中定義全域性變數將會使所有...

程序虛擬位址空間 程式編譯鏈結過程

1.程式編譯 鏈結 執行的過程。1 預編譯階段 生成 i檔案。處理源 檔案,即以 開始的預編譯指令。有展開巨集 去注釋 新增行號 保留所有 pragma編譯指令。2 編譯階段 生成 s檔案 詞法分析 源程式被輸入到掃瞄器,掃瞄器將源 的字串行分割成一系列的記號 識別符號 關鍵字 字面量 數字 字串等...