當我們寫好.c/.cpp檔案時 此時檔案還不能執行 因為他要經過以下的四步才可以執行
.c/.cpp(生成.i) 編譯(生成.s) 彙編(生成.o) 鏈結(生成.exe)
1.#define巨集替換 1.詞法分析 指令翻譯成二進位制 1.合併段和符號表
2.#include 遞迴展開 2.語法分析 2.符號解析
3.處理#if #endif等 3.語義分析 3.分配位址空間
4.新增行號和檔案表示 4.**優化 4.符號重定位
5.刪除注釋
6.保留#pragma
此時的檔案已經成.exe的elf格式了 然而現在檔案還是不可以執行的 因為此時檔案還在磁碟上 檔案要載入到記憶體上才可執行 於是還有這以下三步檔案才可以執行
執行.exe(./main)
1.建立虛擬位址空間到物理記憶體的對映(建立核心對映結構體)
2.載入指令和資料到記憶體中
此時就算虛擬空位址(本身並不存在)被惡意修改 真實物理記憶體的大小是固定的 也不會影響到其他程序了
注意:資料一般都放在堆和棧 堆和棧都有隨機的偏移 是因為防止被惡意修改 堆疊只有在執行的過程才有
dma是不過暫存器的 直接通過資料匯流排得到資料
int * p = null;
*p = 20;
此段**錯誤 因為null在保留區 保留區不允許訪問 而解引用則訪問了保留區
.data段放的是已初始化且初始化不為0的資料
.bss段放的是未初始化或初始化為0的資料
為什麼兩個段保留資料?節省的是哪塊空間?
.bss為了節省空間 .bss節省的是檔案空間(其實.bss段在檔案中不存在) 只是從section header 把.bss資訊儲存了下來
符號表l:本檔案 g:全域性
強符號:全域性已初始化的變數
弱符號:全域性未初始化的變數
強弱符號的規則:
兩個強符號重定義錯誤
一強一弱 選強符號
兩個弱符號 選資料較大的
.bss弱符號在彙編時 看不到本檔案以外存放的強符號 所以先放在common塊 鏈結完後當所有檔案都看見後 若有強符號 則用強符號位址 此時弱符號也不再common塊 在合理的位置了
引入外部符號放在und符號表中找不到 .test段對於外部變數用虛假的0位址代替真實位址針對函式用-4偏移 此時彙編完成 弱符號以及外部符號要在鏈結中處理
編譯鏈結執行原理 虛擬位址空間布局
1 早期記憶體分配機制 在早期的計算機中,要執行乙個程式,會把這些程式全都裝入記憶體,程式都是直接執行在記憶體上的,也就是說程式中訪問的記憶體位址都是實際的物理記憶體位址。當計算機同時執行多個程式時,必須保證這些程式用到的記憶體總量要小於計算機實際物理記憶體的大小。但是同時存在以下3個問題 1 程序...
程式編譯鏈結,執行原理,虛擬位址空間布局
1 預編譯過程 i 1.刪除 define文字替換 2.if endif elif 3.include遞迴展開 4.刪除注釋 5.新增行號 主要目的是為了方便除錯 6.保留 pragma 2 編譯 s 1.詞法分析 例 int 8a 10 變數不能以數字開頭 2.語法分析 根據一條表示式分析 3.語...
編譯鏈結執行原理 編譯鏈結執行過程
乙個.c cpp源程式檔案要最後變成.exe windows 或者.out linux 可執行檔案,要經過編譯和鏈結過程。四個步驟 預編譯,編譯,彙編,連線 一 預編譯 處理以 開頭的預編譯指令,比如 include,define等,規則如下 1 刪除所有的 define,並展開所有的巨集替換 文字...