1. 程式人生 > >計算機中地址和記憶體大小的計算和編譯出來的資料段

計算機中地址和記憶體大小的計算和編譯出來的資料段

由地址計算記憶體大小(消除模糊認知)  

  在計算機中一個地址代表一個位元組的記憶體的位置,即這個byte的門牌號,所以如果給出地址空間的起始地址是可以計算出記憶體大小的,比如STM32中Flash可程式設計的地址是從0x0800 0000開始到0x0801FFFF結束的所以記憶體大小的計算過程如下:

地址差 = 結束地址 - 開始地址  =  0x0001FFFF;他們可以表示的Byte的個數是N = 0x0001 FFFF + 1即0x00020000將N變換為十進位制是131072。

記憶體大小 = N/1024(KB) = 131072 /1024 =  128Kb此時說明這個晶片的Flash大小是128Kb的。

程式編譯過程中的各個資料段

bss段:
  bss段(bss segment)通常是指用來存放程式中未初始化的全域性變數的一塊記憶體區域。

  bss是英文Block Started by Symbol(符號塊)的簡稱。

  bss段屬於靜態記憶體分配。

data段:
  資料段(data segment)通常是指用來存放程式中已初始化的全域性變數的一塊記憶體區域。資料段屬於靜態記憶體分配。

text段:
  程式碼段(code segment/text segment)通常是指用來存放程式執行程式碼的一塊記憶體區域。這部分割槽域的大小在程式執行前就已經確定,並且記憶體區域通常屬於只讀(某些架構也允許程式碼段為可寫,即允許修改程式)。在程式碼段中,也有可能包含一些只讀的常數變數,例如字串常量等。

堆(heap):
  堆是用於存放程序執行中被動態分配的記憶體段,它的大小並不固定,可動態擴張或縮減。當程序呼叫malloc等函式分配記憶體時,新分配的記憶體就被動態新增到堆上(堆被擴張);當利用free等函式釋放記憶體時,被釋放的記憶體從堆中被剔除(堆被縮減)。

棧(stack):
   棧又稱堆疊,是使用者存放程式臨時建立的區域性變數,也就是說我們函式括弧“{}”中定義的變數(但不包括static宣告的變數,static意味著在資料段中存放變數)。除此以外,在函式被呼叫時,其引數也會被壓入發起呼叫的程序棧中,並且待到呼叫結束後,函式的返回值也會被存放回棧中。由於棧的先進先出(FIFO)特點,所以棧特別方便用來儲存/恢復呼叫現場。從這個意義上講,我們可以把堆疊看成一個寄存、交換臨時資料的記憶體區。

 

  一個程式本質上都是由 bss段、data段、text段三個組成的。這樣的概念,不知道最初來源於哪裡的規定,但在當前的計算機程式設計中是很重要的一個基本概念。而且在嵌入式系統的設計中也非常重要,牽涉到嵌入式系統執行時的記憶體大小分配,儲存單元佔用空間大小的問題。在採用段式記憶體管理的架構中(比如intel的80x86系統),bss段通常是指用來存放程式中未初始化的全域性變數的一塊記憶體區域,一般在初始化時bss 段部分將會清零。bss段屬於靜態記憶體分配,即程式一開始就將其清零了。比如,在C語言之類的程式編譯完成之後,已初始化的全域性變數儲存在.data 段中,未初始化的全域性變數儲存在.bss 段中。text和data段都在可執行檔案中(在嵌入式系統裡一般是固化在映象檔案中),由系統從可執行檔案中載入;而bss段不在可執行檔案中,由系統初始化。

【例】
兩個小程式如下:

程式1:

int ar[30000];

void main()
{
    ......
}

程式2:

int ar[300000] = {1, 2, 3, 4, 5, 6 };
void main()
{
    ......
}

 

程式2編譯之後所得的.exe檔案比程式1的要大得多。

使用了/FAs編譯選項來查看了一下其各自的.asm,
發現在程式1.asm中ar的定義如下:

_BSS SEGMENT
    [email protected]@3PAHA DD 0493e0H DUP (?) ; ar
_BSS ENDS

而在程式2.asm中,ar被定義為:

_DATA SEGMENT
    [email protected]@3PAHA DD 01H ; ar
    DD 02H
    DD 03H
    ORG $+1199988
_DATA ENDS

區別是一個位於.bss段,而另一個位於.data段,兩者的區別在於:

全域性的未初始化變數存在於.bss段中,具體體現為一個佔位符;
全域性的已初始化變數存於.data段中;
而函式內的自動變數都在棧上分配空間;
.bss是不佔用.exe檔案空間的,其內容由作業系統初始化(清零);
.data卻需要佔用,其內容由程式初始化。因此造成了上述情況。
bss段(未手動初始化的資料)並不給該段的資料分配空間,只是記錄資料所需空間的大小;
bss段的大小從可執行檔案中得到 ,然後連結器得到這個大小的記憶體塊,緊跟在資料段後面。
data段(已手動初始化的資料)則為資料分配空間,資料儲存在目標檔案中;
data段包含經過初始化的全域性變數以及它們的值。當這個記憶體區進入程式的地址空間後全部清零。包含data段和bss段的整個區段此時通常稱為資料區。

參考部落格:https://www.cnblogs.com/yanghong-hnu/p/4705755.html