【編譯原理】預編譯、編譯、彙編與鏈接

1、前言

我們編寫的程序代碼是怎樣運行起來的?到底運行的是什麼內容?平時我們所說的編譯主要包括預編譯、編譯、彙編與鏈接,這四部分分別都幹什麼工作,主要職能有哪些。
在這裏插入圖片描述
講述編譯之前,我們先要了解程序內存。一個由c/c++編譯的程序佔用的內存,大致分爲以下幾個部分:
1、棧區(stack): 由編譯器自動分配釋放 ,存放函數的參數值,局部變量的值等。其操作方式類似於數據結構中的棧。
2、堆區(heap): 一般由程序員分配釋放, 若程序員不釋放,程序結束時可能由OS回收 。
3、全局區(靜態區)(static)
4、文字常量區:常量字符串就是放在這裏的。 程序結束後由系統釋放
5、程序代碼區:存放函數體的二進制代碼。
在這裏插入圖片描述
Windows中以2:2劃分內核、用戶空間,Linux中以1:3劃分內核、用戶空間。

2、代碼如何生成

圍繞着內存,編譯過程大概如下:
在這裏插入圖片描述

3、預編譯:i

1.#define 宏文本替換
2.#include 遞歸展開頭文件
3.#if #endif #elif 刪除預編譯指令
4.刪除註釋
5.添加行號和文本標識
6.保留 #pragma 編譯器處理

4、編譯:s

【編譯階段以一個.cpp或者.c文件爲單元編譯】
1.詞法分析
2.語法分析
3.語義分析
4.代碼優化 生成彙編代碼

[inter x86]  //彙編代碼
int a = 10;
mov dword ptr[a],0Ah //ptr[a] 對a地址解引用後得到a的內存 //0Ah 是10

5、 彙編: o

可重定位(重入)的二進制文件
Linux中ELF文件,bss段:段以符號起始,節省空間
bss段少了一個數據,和虛擬地址空間上的段不同意義。 (bss段中少的數據,位於COM塊中)
強弱符號:強符號是已初始化的全局變量,弱符號是未初始化的全局變量【C++中無強弱符號之分】

強弱符號規則:
1.兩強:重定義錯誤 //數據段不可以出現重名
2.一強一弱:選強符號作爲所有地址
3.兩弱:選字節數大的 <編譯器處理>
在彙編完成前,不清楚是否存在強符號無法判斷時,則將變量放入COM塊中。

6、 鏈接

生成.exe文件 也是ELF文件,有頭和.data、.text段等
//UND 未定義區 //找不到
1.段合併:相同段合併<一個段映射一個頁面>
合併符號表:同名查找,未找到則用本身查找的弱符號,找到則刪除弱符號改用強符號
2.符號解析(處理UND):未找到對應的符號進行報錯 合併UND
3.分配地址和空間
4.符號的重定位 //test段 <虛假地址改真實,糾正虛假偏移>
鏈接代碼:[ld -e main -o run main.o sum.o]

7、例子

【Linux】中關於預編譯、編譯、彙編、鏈接的代碼
1.[預編譯] gcc -E Aff.c -o main.i
[ls] Aff.c main.i
2.[編譯]gcc -S main.i -o main.s
[ls]Aff.c mian.i main.s
3.[彙編]gcc -C mian.s -o main.o
[ls]Aff.c mian.i main.s main.o a.out
4.[鏈接]/a.out //此時是.exe文件(可執行文件)

加入我們

在這裏插入圖片描述

發佈了164 篇原創文章 · 獲贊 85 · 訪問量 21萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章