代碼、數(shù)據(jù)段(精)_第1頁
代碼、數(shù)據(jù)段(精)_第2頁
免費預覽已結束,剩余2頁可下載查看

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

1、我一直對代碼是如何由多個源文件經(jīng)過編譯、鏈接并最終生成可執(zhí)行文件,再到被處理器執(zhí)行這一過程感到困惑和迷茫。直到最近在閱讀Cortex-M3權威指南Cn時,我想我可能預見到這其中的奧妙了,然而我還不確 定。在經(jīng)過查閱大部分相關資料以及對源代碼的反復調試后,最終了解了這其中的內幕。于是我便產生了一種要將其寫岀來的沖動,然而這些東西對于那些大蝦們是不屑一顧的,但也是他們不愿慷慨相授的。這些知識在網(wǎng)上也是可以查到的,但那要費相當大的周折,也很少有人將其整理岀一個清晰的線條。本打算寫成一個手冊,那就需要很大的工作量了,而且時間也不允許我這么做,于是將其中一部分核心的東西寫在這里。一個目的是讓自己從新梳理

2、一下整個流程,第二個目的就是希望有識之士一起交流。由于里面會涉及很多專業(yè)術語,所以我可以先在這里聲明一下,哪些人適合閱讀這批那文章。如果你是一個嵌入式開發(fā)者,或者電子工程師,或者你曾獨立地開發(fā)過一些小的軟件,對操作系統(tǒng)也有一些了解,但你還不了解代碼是如何被處理器執(zhí)行的,那么你是一個合適的讀者。如果你說你只用C語言寫過類似在屏幕上輸出一個Helloword!的字符串那樣的程序,并且你也不是我上面提到的那些人,我想你不適合在讀下去了。但是如果你很無聊,亦或是你有一些其它的癖好,或者你從未懷疑過自己的智商,那我將不打算攔著你。你喜歡就好。我還是要像很多人那樣,不厭其煩地列岀一堆參考書籍,這是對原著的

3、尊重。本文參考了以下手冊, 如有不一致的地方,請以原文為準。連接器與加載器、Cortex-M3權威指南Cn、stm3210 x參考手冊、Cortex-M3技術參考手冊.、EWARM_AssemblerReference、EWARM_CompilerReference、EWARM_xlink其中后三個手冊是在網(wǎng)上找不到的,原因很簡單,因為這三個手冊被包含在IAR EWAR軟件包中,它們都是英文原版的,并未有好事者將其翻譯為中文。如果你已經(jīng)準備好了,那么我們開始先了解一下讓人瘋狂的處理器。雖然處理器的制作工藝極其復 雜,然而它的工作確極其的簡單。處理器就是在不停地將數(shù)據(jù)移來移去,變來變去。因此我們

4、的工作就是告訴 處理器你要的數(shù)據(jù)在哪里,你要怎樣操作這些數(shù)據(jù)。當然這是一種相當通俗的說法,實際上要比這復雜得多, 我在后面會介紹一下Cortex-M3核執(zhí)行指令的細節(jié)。雖然Cortex-M3核是為嵌入式片上系統(tǒng)所設計的,但它已經(jīng)非常接近通用處理器了,通用處理器就是PC機上的CPU因此以Cortex-M3核來解釋本文所要探討的問題已經(jīng)足夠了。要清楚的知道代碼是如何運行的,一個很重要的問題就不能被回避,那就是程序是如何存儲的。程序是如何存儲的?程序是由可執(zhí)行代碼和數(shù)據(jù)構成的,理解這一點是很了不起的。但是代碼和數(shù)據(jù)卻是分開存儲的,為 了詳細了解程序在存儲器內的分布情況,我將一個由IAR EWAR軟件

5、生成的存儲器鏡像文件的最后一部分列START ADDRES段的起始地址,十六進制表示在這里,以供講解用,在后面的敘述中我將用Flash代替存儲器這個稱呼,因為大量的單片機存儲器都是基于Flash技術的。因此當你看到Flash時,你要知道這是在說存儲器。(原文件名:b_large_Z39A_358d0001842f5c44.jpg引用圖片上面那張圖片向你展示了,你的程序是如何在 信息,下面將敘述理解上面那張圖所必須掌握的SEGMENTSEGMEN的中文意思是段。 就像我在開始所敘述的那樣, 代碼與數(shù)據(jù)是分開存儲的, 它們被安排到不 同的Flash空間內,這些不同的Flash空間就是這里的段。因此

6、你很自然的就會想到,段應該包括代碼段與數(shù) 據(jù)段,就是CODE SEGMEN和DATASEGMENT沒錯,就像你想的那樣,代碼段用來存儲代碼,而數(shù)據(jù)段用來存儲數(shù)據(jù)。為了讓代碼更加的安全以保證不會因非法操作而改變代碼,通常要為段設置一些訪問規(guī)則, 這些規(guī)則構成了段的屬性。例如,代碼段都是可執(zhí)行的,只讀不可修改的。而數(shù)據(jù)段是不可執(zhí)行的,可讀可修 改的。如果試圖將數(shù)據(jù)段的數(shù)據(jù)作為代碼來執(zhí)行,將會引起故障。當你了解的更深入時,你就會理解這樣做的 重要性。然而為了更有效的管理數(shù)據(jù)和代碼,實際中對代碼段與數(shù)據(jù)段做了更為細致的劃分,這就是你為什么 會看到上圖中SEGMENT面會有諸如INTVEC ICODE和

7、COD等這么多段名字的原因。當你清楚了程序是按照 段來存儲的,那么對于上圖中的那個表我想你已經(jīng)有了一個大致的認識,但是你還不清楚,為什么會有那么多的段。因此下一步的工作,就是我們一起來分析那些段。這些段都是干什么的?這一節(jié)的內容是和編程息息相關的,你會在這里看到你所寫的代碼最終被存儲到了Flash的什么地方,當你理解了這節(jié)所介紹到的內容,你就會發(fā)現(xiàn),指導你編寫正確代碼的原則會變得越來越少。我們關注的 仍然是上面那個表,其中各個字段的含義如下:段的名稱吉y工、3!:2 2:fi.ttMMK SMnitf0l-:4301l*:-ttKLla UttL W traiw卅泊卅泊1給給i 星帖星帖0;護

8、脫護脫-2BCODCE*1HFlash內部分布的。但是有的讀者并不清楚那張圖里所提供的SEGMENTMlTH;MlMStlEND ADDRES段的結束地址,十六進制表示staticint d;段的對齊長度,是2的ALIGN次冪。這里ALIGN都是2,就是說所有其中有兩個字段SPACE和TYPE沒有說到,這兩個字段和我們要討論的無關,另一點就是我確實記不 清楚了,因此也不敢胡亂的瞎寫!我們先看數(shù)據(jù)段,第一個數(shù)據(jù)段是DATA_ID,這個段的起始地址是0X080017E0,結束地址是0X080018A0,長度為0 x18個字節(jié),注意這里的數(shù)據(jù)都是十六進制的。如果你使用C語言定義了一個全局變量a,并且

9、為他賦了一個初值,就像下面這樣:int a = 8;那么這個變量a就會被分配到DATA_ID段。又或者你定義了一個局部靜態(tài)變量,并且也要賦初值,像這樣:void t(voidstatic int b = 5;那么這個局部靜態(tài)變量b也會被分配到DATA_ID段。因此DATA_ID段是為具有整個程序生命周期并初始化的數(shù)據(jù)分配的空間,記住,一定是初始化的整個程序生命周期的變量。例如像下面的這兩個變量c和d就不會被分配到DATA_ID段,而是被分配到了DATA_Z段,因為這兩個變量沒有被初始化。int c;void t(void這樣你也知道了,具有整個程序生命周期且沒有被初始化的變量被分配到DATA_

10、Z段,在C語言中,這樣的變量是被編譯器初始化為0的,因此DATA_Z中的Z是Zero的第一個字母,而DATA_ID中的I你可以理解為Init的第一個字母,因此DATA_ID段是初始化的數(shù)據(jù)段,而DATA_Z段是零初始化的數(shù)據(jù)段。SIZE段的大小,以字節(jié)為單位,十六進制表示ALIGN的段都是4個字節(jié)對齊的int m = 0;這個m是被分配到DATA_ID段的,雖然它是被初始化為0,但它是我們手動初始化的我們再看DATA_C段,這是一個很容易理解的數(shù)據(jù)段,它是用來分配被標記為const類型的數(shù)據(jù),就像下面這樣的數(shù)據(jù)。const int n = 8;還有一個DATA_I段,細心的讀者會發(fā)現(xiàn),這個段的

11、起始地址一下子變大了很多,事實上從0 x20000000開始是RAM的起始地址,而0 x08000000對應的是flash的起始地址,因此上面兩個個數(shù)據(jù)段DATA_ID段和DATA_C段都是在Flash內,而DATA_I段和DATA_Z段是在RAM中分配的。如果你在仔細一點會發(fā)現(xiàn)DATA_I段與DATA_ID段的大小是一樣的,這是偶然還是它們之間有著某種聯(lián)系,事實上是DATA_I段是DATA_ID段的副本,它們是一樣的,不過一個在Flash內,一個在RAM內。因為程序最終是在RAM內執(zhí)行的,所以必須將這些數(shù)據(jù)復制到RAM內。而DATA_C段是為常量分配的,是不變化的,所以在RAM內沒有對應的空間。而DATA_Z段是零初始化的數(shù)據(jù)段,既然知道了這一點,就沒有必要在Flash內分配這些數(shù)據(jù)了,F(xiàn)lash內只存儲零初始化數(shù)據(jù)所需要的空間,在程序運行時再到RAM中去分配,因此DATA_Z段是被分配到RAM內的。最后一個CSTACK段也是在RAM內,這個段是為棧使用的,局部非靜態(tài)變量和子函數(shù)返回地址還有發(fā) 生中斷時的現(xiàn)場保護,都要使用棧,如果你使用過匯編,你就會對這些非常清楚。由于局部非靜態(tài)變量是在棧 內分配的,所以它的值是不確定的,使用時最好先初始化。

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經(jīng)權益所有人同意不得將文件中的內容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
  • 6. 下載文件中如有侵權或不適當內容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論