1. 程式人生 > >編譯 連結 執行原理

編譯 連結 執行原理

一、

在80386之前是真實模式,80386之後是保護模式

所謂的32位、62位是指 ALU的寬度,即一次效能處理最大資料長度(位元為單位)

在Windows作業系統下4G虛擬記憶體空間是,使用者空間:核心空間是1:1

在Linux作業系統下4G虛擬記憶體空間是,使用者空間:核心空間是3:1

Linux4G記憶體分配大致如下圖

                                                                   圖1

.data 已初始化且初始化不為0的資料

.bss 未初始化或初始化為0的資料

區域性變數的普通變數是指令(.text)

二、

編譯

預編譯

生成.i檔案  命令:gcc -E main.c -o main.o

1.刪除#define

2.遞迴展開#include檔案

3.刪除#if0 #endif #elif

4.刪除註釋(//  /**/)

5.新增行,檔案表示

6.保留#pragma

編譯

生成.s檔案 命令:gcc -S main.i -o main.s

1.詞法分析

2.語法分析

3.語義分析

4.程式碼優化

彙編

可重定位,可重入

生成.o檔案或.obj檔案 gcc -c main.s -o main.o

指令程式碼翻譯成二進位制

連結

生成.exe檔案

1.合併段和符號表

2.符號解析(在符號引用的地方找到符號定義的地方(只關注全域性符號))

3.分配地址和空間

4.符號重定位

三、目標檔案的分析

可執行檔案格式,Windows下問PE格式,Linux下為ELF格式,它們都是COFF格式的變種。目標檔案就是原始碼編譯後但未進行連線的那些中間檔案,它跟可執行檔案的內容結構很相似,所以一般跟可執行檔案格式一起採用一種格式儲存。

在此,使用main.c進行分析

編譯

輸入gcc -c *.c 命令對main.c檔案進行編譯生成main.o檔案

檢視目標檔案的結構和內容:objdump -h main.o

由此可畫出ELF檔案的大致結構

我們可以發現在.bss檔案中大小為20,但我們的main.c 程式中有6個int 型的資料在.bss段中存放,缺失了一個……

這時我們檢視符號表

發現!!!缺失的那個資料  gdata3在*COM*塊中

這是因為,

在c中,有強弱符號之分

強符號:已初始化的全域性變數

弱符號:未初始化的全域性變數

規則:

1.兩強(兩個同名強):重定義

2.一強一弱:選強符號

3.兩弱:選位元組較大的

此時函式的入口地址為0x0000 0000

連結

輸入命令ld -e main -o run main.o

此時有了入口地址

gdata3此時歸屬於.bss段了

ps:

修改main.c    新增sum.c

此時gdata、sum處於*UND*塊

通過連結

四、執行原理

1.建立虛擬地址空間和實體記憶體的對映(對映結構體)

2.載入指令資料

檢視program header 段

3.第一行指令的地址寫入pc暫存器中