日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > windows >内容正文

windows

关于嵌入式系统内存地址空间的一些疑问(.text、.data、.bass、堆\栈空间)

發布時間:2024/10/14 windows 69 豆豆
生活随笔 收集整理的這篇文章主要介紹了 关于嵌入式系统内存地址空间的一些疑问(.text、.data、.bass、堆\栈空间) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

深入淺出了解(.text、.data、.bss、堆空間、棧空間)的含義

接下來所說的是嵌入式系統的內存地址空間的布局,簡單的說就是我們寫好的代碼,在編譯過程種中,把代碼里不同的變量、函數相應的保存在每個段中(.text、.data、.bss),至于堆空間、棧空間是代碼在芯片上運行時才存在的。

  • .text:代碼段。包含了操作系統和應用程序的所有代碼。
  • .data:數據段。存放了操作系統和應用程序當中所有帶有初始值的全局變量。
  • .bss:bss段。存放了操作系統和應用程序當中所有未帶初始化的全局變量。
  • 堆空間:動態分配的內存空間。在系統運行時,可以通過malloc/free之類的函數來申請或者釋放一段連續的內存空間
  • 棧空間:保存運行上下文以及函數調用時的局部變量和形參。
  • 那么問題1,什么樣的數據會保存在.text段里?.data段?.bss段?棧空間?堆空間?

    答:下面舉例說明:

    unsigned char gvCh;//全局變量,沒有初值,放在.bss段中 unsigned short gvShort;// 全局變量,沒有初值,放在.bss段中 unsigned int gvInt = 0x12345678;//全局變量,有初值,放在.data段中 unsigned long gvLong = 0x87654321; //全局變量,有初值,放在.data段中int main(void)//main函數在經過編譯以后得到的機器代碼,存放在.text代碼段當中 {unsigned char arry[10],*p;//局部變量,存放在棧當中p = malloc(10*sizeof(char));//p指針變量指向的空間,存放在堆當中while(1); }

    補充:上面定義的全局變量沒有在代碼上引用,這里只是舉例,如果在實際應用中,它們會被編譯器優化掉,那么它們根本就不會占用內存空間。

    問題2,上面的例子可能只是給你解開了一部分疑惑,如果用上變量修飾詞static、const,那么它們又是怎么存儲的呢?

    答:下面舉例說明:

    static unsigned char gvCh;//全局變量,只能在本文件內引用,沒有初值,放在.bss段中 const unsigned short gvShort;//全局變量,不可修改(只讀),放在.data段中。實際不會定義無初值的const變量 static unsigned int gvInt = 0x12345678;//全局變量,只能在本文件內引用,有初值,放在.data段中 const unsigned long gvLong = 0x87654321;//全局變量,不可修改(只讀),放在.data段中。int main(void) {static unsigned char lvCh;//加上static的局部變量,只能在本函數內引用,函數結束回時不會消失,沒有初值,放在.bss段中const unsigned short lvShort;//加上const的局部變量,不可修改(只讀),放在.data段中。實際不會定義無初值的const變量static unsigned int lvInt = 0x12345678;//加上static的局部變量,只能在本函數內引用,函數結束回時不會消失,有初值,放在.data段中const unsigned long lvLong = 0x87654321//加上const局部變量,不可修改(只讀),放在.data段中while(1); }

    總結,如果變量加上const,不管是全局變量還是局部變量,不管有沒有初值,都保存在.data段。如果變量加上static,不會影響變量所保存的段,static的作用是改變變量的作用域。

    問題3,我們了解完怎么樣的變量該保存到什么段,或許還會有疑惑,.data段的數據和.bss段的數據有什么區別?把數據這么區分出來的作用是什么?

    答:原因其實很簡單,就是為了節省編譯出來的bin文件占用的內存大小。.data段變量的值會記錄在bin二進制文件中,而.bss記錄的是變量的起始地址和大小,在程序運行時初始化為零。下舉例說明:

    unsigned char gvCh_init[3] = {1,2,3}; //.data段,如果數組增大100字節,那么bin文件大小會也會隨之增大 unsigned char gvCh_no_init[3];//.bss段,如果數組增大為100字節,那么bin文件大小不會發生變化,在bin文件里只是記錄這個數組的起始地址和大小,當程序運行時自動把它的值清零。

    問題4,unsigned chat gvCh[100] ={0};算不算給數組gvCh設置了初值而被保存在.data段,將占用bin文件大小?

    答:在IAR編譯器里,unsigned chat gvCh[100] ={0}等同于unsigned chat gvCh[100],保存于.bss段。

    問題5,我們知道在芯片上有ROM存儲器和RAM存儲器,在程序bin文件燒錄到芯片上時,不同的段會如何存在于在ROM和RAM里呢?

    答:沒有一一對應的關系。因為我可以把bin文件燒錄到flash(ROM)里面運行,也可以把它燒錄到RAM里面運行(調試時會這么做)。

    通常地,我們會把編譯好的程序燒錄到flash(ROM)里面去,芯片掉電時不會消失;對于RAM存儲器來說,只有芯片上電代碼運行起來,才會被分配使用(棧/堆就是在RAM開辟的)。

    問題6,代碼中的變量會以什么樣的規則存在于ROM存儲器和RAM存儲器里?

    答:主要根據變量在運行時是否可修改,下面舉例說明:

    unsigned char gvCh;可讀寫,存放在RAM(無初始值,.bss段) unsigned int gvInt = 0x12345678;//可讀寫,存放在RAM(有初始值,.data段) const unsigned long gvLong = 0x87654321; //只讀,存放在ROMint main1(void)//main函數在經過編譯以后得到的機器代碼,不可修改,存放ROM {unsigned char arry[10],*p;//可讀寫,存放在棧當中,也就是在RAM中p = malloc(10*sizeof(char));//p指針變量指向的空間,存放在堆當中,也就是在RAM中while(1); }

    有初始值、并且可讀寫的全局變量gvInt存放在RAM,但我們知道在RAM的數據掉電會丟失,其實它的初始值0x12345678一開始保存在flash(ROM)里,在芯片上電時,會將初始值復制到RAM里的gvInt變量(它所在RAM的地址在編譯后已經確定)。可能我們會疑惑,自己的代碼明明沒有寫給gvInt變量賦值的過程,這一部分代碼并不需要我們做。芯片上電就會進入Reset_Handler中斷,打開.s啟動文件,我們可以發現在Reset_Handler中斷里,調用了SystemInit函數,然后再調用了_main(IAR編譯器的話是__iar_program_start)函數,在_main函數會進行RW data的復制,和.bss段的初始化,以及C庫函數的初始化(比如malloc函數需要初始化才能使用),進而調用main函數進入我們的代碼區域。

    ?

    總結

    以上是生活随笔為你收集整理的关于嵌入式系统内存地址空间的一些疑问(.text、.data、.bass、堆\栈空间)的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。