久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费

專注電子技術學習與研究
當前位置:單片機教程網 >> MCU設計實例 >> 瀏覽文章

代碼是如何跑起來的?

作者:佚名   來源:本站原創   點擊數:  更新時間:2011年07月13日   【字體:

如果你已經準備好了,那么我們開始先了解一下讓人瘋狂的處理器。雖然處理器的制作工藝極其復雜,然而它的工作確極其的簡單。處理器就是在不停地將數據移來移去,變來變去。因此我們的工作就是告訴處理器你要的數據在哪里,你要怎樣操作這些數據。當然這是一種相當通俗的說法,實際上要比這復雜得多,我在后面會介紹一下Cortex-M3核執行指令的細節。雖然Cortex-M3核是為嵌入式片上系統所設計的,但它已經非常接近通用處理器了,通用處理器就是PC機上的CPU。因此以Cortex-M3核來解釋本文所要探討的問題已經足夠了。要清楚的知道代碼是如何運行的,一個很重要的問題就不能被回避,那就是程序是如何存儲的。

程序是如何存儲的?
    程序是由可執行代碼和數據構成的,理解這一點是很了不起的。但是代碼和數據卻是分開存儲的,為了詳細了解程序在存儲器內的分布情況,我將一個由IAR EWARM軟件生成的存儲器鏡像文件的最后一部分列在這里,以供講解用,在后面的敘述中我將用Flash代替存儲器這個稱呼,因為大量的單片機存儲器都是基于Flash技術的。因此當你看到Flash時,你要知道這是在說存儲器。



引用圖片


 上面那張圖片向你展示了,你的程序是如何在Flash內部分布的。但是有的讀者并不清楚那張圖里所提供的信息,下面將敘述理解上面那張圖所必須掌握的。

SEGMENT

    SEGMENT的中文意思是段。就像我在開始所敘述的那樣,代碼與數據是分開存儲的,它們被安排到不同的Flash空間內,這些不同的Flash空間就是這里的段。因此你很自然的就會想到,段應該包括代碼段與數據段,就是CODE  SEGMENT和DATA   SEGMENT。沒錯,就像你想的那樣,代碼段用來存儲代碼,而數據段用來存儲數據。為了讓代碼更加的安全以保證不會因非法操作而改變代碼,通常要為段設置一些訪問規則,這些規則構成了段的屬性。例如,代碼段都是可執行的,只讀不可修改的。而數據段是不可執行的,可讀可修改的。如果試圖將數據段的數據作為代碼來執行,將會引起故障。當你了解的更深入時,你就會理解這樣做的重要性。然而為了更有效的管理數據和代碼,實際中對代碼段與數據段做了更為細致的劃分,這就是你為什么會看到上圖中SEGMENT下面會有諸如INTVEC、ICODE和CODE等這么多段名字的原因。當你清楚了程序是按照段來存儲的,那么對于上圖中的那個表我想你已經有了一個大致的認識,但是你還不清楚,為什么會有那么多的段。因此下一步的工作,就是我們一起來分析那些段。

這些段都是干什么的?
  
    這一節的內容是和編程息息相關的,你會在這里看到你所寫的代碼最終被存儲到了Flash的什么地方,當你理解了這節所介紹到的內容,你就會發現,指導你編寫正確代碼的原則會變得越來越少。我們關注的仍然是上面那個表,其中各個字段的含義如下:

SEGMENT           ——段的名稱

START ADDRES      ——段的起始地址,十六進制表示

END ADDRES        ——段的結束地址,十六進制表示

SIZE              ——段的大小,以字節為單位,十六進制表示

ALIGN             ——段的對齊長度,是2的ALIGN次冪。這里ALIGN都是2,就是說所有的段都是4個字節對齊的。

    其中有兩個字段SPACE和TYPE沒有說到,這兩個字段和我們要討論的無關,另一點就是我確實記不清楚了,因此也不敢胡亂的瞎寫!

    我們先看數據段,第一個數據段是DATA_ID,這個段的起始地址是0x080017E0,結束地址是0x080018A0,長度為0x18個字節,注意這里的數據都是十六進制的。如果你使用C語言定義了一個全局變量a,并且為他賦了一個初值,就像下面這樣:

int a = 8;

那么這個變量a就會被分配到DATA_ID段。又或者你定義了一個局部靜態變量,并且也要賦初值,像這樣:

void t(void)
{
    static int b = 5;
}

    那么這個局部靜態變量b也會被分配到DATA_ID段。因此DATA_ID段是為具有整個程序生命周期并初始化的數據分配的空間,記住,一定是初始化的整個程序生命周期的變量。例如像下面的這兩個變量c和d就不會被分配到DATA_ID段,而是被分配到了DATA_Z段,因為這兩個變量沒有被初始化。
int c;
void t(void)
{
    static int d;
}
    這樣你也知道了,具有整個程序生命周期且沒有被初始化的變量被分配到DATA_Z段,在C語言中,這樣的變量是被編譯器初始化為0的,因此DATA_Z中的Z是Zero的第一個字母,而DATA_ID中的I你可以理解為Init的第一個字母,因此DATA_ID段是初始化的數據段,而DATA_Z段是零初始化的數據段。

int m = 0;

    這個m是被分配到DATA_ID段的,雖然它是被初始化為0,但它是我們手動初始化的。

    我們再看DATA_C段,這是一個很容易理解的數據段,它是用來分配被標記為const類型的數據,就像下面這樣的數據。

const int n = 8;

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

關閉窗口

相關文章

主站蜘蛛池模板: 久久久久久久久国产精品 | 久久久久久亚洲欧洲 | 免费在线日韩 | 国产成人91视频 | 一级黄色夫妻生活 | 亚洲精品91 | 欧美性猛交一区二区三区精品 | 亚洲乱码国产乱码精品精98午夜 | 视频二区 | 四虎影院在线免费观看 | 欧美一级小视频 | 一区二区三区日韩精品 | 亚洲国产精品一区二区三区 | 91一区| 国产乱码一二三区精品 | 韩日在线观看视频 | 亚洲精品一区二区三区在线观看 | a级片在线观看 | 孰女乱色一区二区三区 | 久草青青 | 久久久久成人精品免费播放动漫 | 久久免费看 | 久久伊人精品 | 日韩电影免费在线观看中文字幕 | 国产成人一区二区三区久久久 | 日本三级电影在线观看视频 | 桃花av在线 | 精品一区二区三区在线视频 | 蜜桃视频在线观看免费视频网站www | 免费看片在线播放 | 国产精品久久久久久亚洲调教 | 狠狠操天天干 | 精品国产乱码久久久久久88av | 久久国产精品色av免费观看 | 91精品国产乱码久久久久久久久 | 黄色激情毛片 | 国产精品一区视频 | 国产伊人精品 | 午夜视频在线播放 | 精品国产乱码久久久久久牛牛 | 精品国产一区二区三区性色av |