深入編譯連結和執行
阿新 • • 發佈:2019-01-07
我們先看下面這份程式碼:
我們知道我們用C/C++寫完一份程式碼後是要經過編譯和連結才能生成可執行程式(.exe),這個可執行程式檔案本身在磁碟中儲存的。那麼如果我們要執行它,就必須把它載入到記憶體中去執行。CPU訪問記憶體的速度要比訪問磁碟的速度快得多。
那麼需要把什麼東西載入到記憶體中去呢?
1、指令 2、資料
那麼我們必須知道我們編寫的程式中哪些是指令,哪些又是資料?
指令和資料又是怎麼儲存在記憶體中的呢?
計算機硬體CPU,記憶體,I/0都可以使用不同商家的硬體,作業系統為了遮蔽底層這些硬體的差異,使我們呼叫程式的時候能夠使用統一的介面,如圖:
為了遮蔽I/O的差異,使用VFS,遮蔽記憶體與I/O,使用虛擬地址空間,遮蔽CPU和I/0,使用了資源排程的最小單位,程序。
那麼我們的程式載入到記憶體其實是在虛擬地址空間裡,也就是虛擬記憶體裡,作業系統提供給我們實體記憶體的管理方法,虛擬記憶體。
虛擬記憶體有多大呢?跟CPU的位數有關,如果是32位的,虛擬記憶體就是2^32,4G的大小
那麼虛擬地址空間是怎麼存放資料的呢?
.txt 放指令
.data 放資料 (初始化且不為0的資料)
.bss 放資料 (未初始化和初始化為0的資料)
那麼我們上面寫的程式哪個是指令,哪個是資料?
額,指令和資料為什麼分開放?資料段為什麼要分成.data和.bss?這樣存放節省了誰的空間,虛擬地址空間還是檔案空間
程式的編譯過程是怎樣的?
二進位制可重定位目標檔案的格式是什麼呢?
我們在Linux下看一下:
.obj裡面有段 .text .data 16進位制下位元組數為C ,程式中gdata1,gdata4,d都屬於.data段,合起來12個位元組 .bss 16進位制下位元組數為14,程式中按照我們之前說的,應該有6個數據,合起來是24個,可是.bss段只有20個位元組,那麼6箇中哪個不是儲存在.data塊呢? .comment .note.GUN-stack .
我們讀取.obj發現有一個檔案頭:裡面包含了在哪種機器上執行,入口地址(entry point address)為0x0,我們說過0地址是不可訪問的,那麼.obj檔案是不能執行的。
我麼再看一下.obj檔案的格式:
relocatable 是一個可重定位檔案,並不是可執行檔案。 我們再來看看:
size of this header: 52(bytes) 檔案頭的大小是52位元組
我們在段資訊的那張圖裡知道:
#include<stdio.h>
int gdata1=10;
int gdata2=0;
int gdata3;
static int gdata4=11;
static int gdata5=0;
static int gdata6;
int main()
{
int a=12;
int b=0;
int c;
static int d=13;
static int e=0;
static int f;
return 0;
}
額,程式碼中有全域性變數,靜態全域性變數,區域性變數,靜態區域性變數
gdata1,gdata2,gdata3,gdata4,gdata5,gdata6的作用域都是從程式開始到結束,a,b,c,d,e,f的作用域是在程式碼塊中,d,e,f一直佔用記憶體,直到程式結束。二進位制可重定位目標檔案的格式是什麼呢?
.obj裡面有段 .text .data 16進位制下位元組數為C ,程式中gdata1,gdata4,d都屬於.data段,合起來12個位元組 .bss 16進位制下位元組數為14,程式中按照我們之前說的,應該有6個數據,合起來是24個,可是.bss段只有20個位元組,那麼6箇中哪個不是儲存在.data塊呢? .comment .note.GUN-stack .
我們讀取.obj發現有一個檔案頭:裡面包含了在哪種機器上執行,入口地址(entry point address)為0x0,我們說過0地址是不可訪問的,那麼.obj檔案是不能執行的。
我麼再看一下.obj檔案的格式:
relocatable 是一個可重定位檔案,並不是可執行檔案。 我們再來看看:
size of this header: 52(bytes) 檔案頭的大小是52位元組
我們在段資訊的那張圖裡知道:
VMA虛擬記憶體地址,LMA載入記憶體地址,都是0,那麼說明在編譯階段是不會給程式分配記憶體的。
再來看File off 偏移量:
那麼.data塊下面根本不是.bss段,而是.comment段,那麼.bss段是節省了檔案的空間。
檢視其他的段:
檢視段的內容:
.data段是不是有10,11,13,.obj檔案的格式就是這樣了。
Start of section headers: 204 bytes 16進位制是CC
我們段表的第一條資訊,就是starting at offset 0xcc,說明.obj檔案先找檔案頭,在檔案頭裡找到段頭的偏移地址,就能找到.bss裡面的資料了。