運行可執行文件exe之前發生了什麼

目錄

1,編寫源文件

2,預編譯

3,編譯

4,彙編

5,鏈接

 



 

1,編寫源文件

源代碼:

#include <Windows.h>
int main()
{   
    MessageBoxA(NULL,"Hello World","the first system32",0);
    return 0;
}

源文件另存爲HelloWorld.cpp,位置在C:\

2,預編譯

預編譯輸入命令(如果發現“ 'g++' 不是內部或外部命令,也不是可運行的程序或批處理文件”的問題,看我另一篇文章

g++ -o HelloWorld.i -E HelloWorld.cpp

  該命令表示編譯環節的第一步,也就是預編譯!當然,這一步也可以被稱爲“編譯預處理”!而這個 HelloWorld.i 即是預編譯過後的文件!

序號 主要行爲
1. 展開所有的宏定義,消除“#define”
2. 處理所有的預編譯指令,比如#if、#ifdef等
3. 處理#include預編譯指令,將包含文件插入到該預編譯的位置
4. 刪除所有的註釋“/**/”、"//"等
5. 添加行號和文件名標識,以便於編譯時編譯器產生調試用的行號信息以及錯誤提醒
6. 保留所有的#program編譯指令,原因是編譯器要使用它們

3,編譯

編譯請輸入命令

g++ -o HelloWorld.s -S HelloWorld.i

  該命令表示編譯過程,也就是生成相應的彙編文件 HelloWorld.s 。

主要行爲 具體描述
詞法分析 將源代碼文件的字符序列劃分爲一系列的記號,一般詞法分析產生的記號有:標識符、關鍵字、數字、字符串、特殊符號(加號、等號);在識別記號的同時也將標識符放好符號表、將數字、字符放入到文字表等;有一個lex程序可以實現詞法掃描,會按照之前定義好的詞法規則將輸入的字符串分割成記號,所以編譯器不需要獨立的詞法掃描器
語法分析 語法分析器將對產生的記號進行語法分析,產生語法樹----就是以表達式尾節點的樹,一步步判斷如何執行表達式操作;如果存在括號不匹配或者表達式錯誤,編譯器就會報告語法分析階段的錯誤;相同的存在一個yacc程序可以根據用戶輸入的語法規則生成語法樹;
語義分析 由語法階段完成分析的並沒有賦予表達式或者其他實際的意義,比如乘法、加法、減法,必須經過語義階段才能賦予其真正的意義;
代碼優化 將代碼進行優化處理
符號彙總 彙總所有符號

補充說明:其中語義分析又可以分爲“靜態語義分析”和“動態語義分析”兩種。

語義分析 簡單說明
靜態語義分析 通常在編譯器就可以確定的語義,主要包括“聲明”、“類型的匹配”以及“類型的轉換”
動態語義分析 只能在運行期才能確定的語義

4,彙編

彙編請輸入命令

g++ -o HelloWorld.o -C HelloWorld.s

  該命令表示對 HelloWorld.s 文件進行彙編處理,生成對應的可重定位的二進制文件 HelloWorld.o ,也就是我們所熟知的機器語言對應的文件。

5,鏈接

鏈接請輸入命令

g++ HelloWorld.cpp -o HelloWorld.exe

  通過調用鏈接器ld來鏈接程序運行需要的一大堆目標文件,以及所依賴的其它庫文件,最後生成可執行文件., 鏈接的主要內容是把各個模塊之間相互引用的部分處理好,使得各個模塊之間能夠正確地銜接。

需要指出:鏈接分爲“靜態鏈接”和“動態鏈接”。

鏈接類型 具體說明
靜態鏈接 指在編譯階段直接把靜態庫加入到可執行文件中去,這樣可執行文件會比較大
動態鏈接 指鏈接階段僅僅只加入一些描述信息,而程序執行時再從系統中把相應動態庫加載到內存中去

結果:

需要補充:

庫文件類型 特點
靜態庫文件 是一個二進制文件,存放的功能函數實現,在文件編譯時要訪問文件,編譯之後靜態庫文件可以刪除
動態庫文件 是一個二進制文件,存放的功能函數實現,在文件執行時要訪問文件,編譯時不需要動態庫文件

額外說明:

操作系統 動態庫文件後綴名
linux .so
window .dll

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章