加載地址、運行地址

轉載地址:http://blog.csdn.net/ce123_zhouwei/article/details/6990100

          在連接目標代碼時,會提到運行地址和加載地址。這兩者有什麼區別呢?

     加載時地址就是程序放置的地址,運行地址就是程序定位的絕對地址,也即在編譯連接時定位的地址如果程序是在flash裏運行,則運行地址和加載地址是相同的。如果程序是在ram裏運行,但程序是存儲在flash裏,則運行地址指向ram,而加載地址是指向flash。代碼一般是燒寫在NAND裏面,比如S3C2440 如果開機從NAND啓動 其開始的4K代碼會被COPY到2440內部的4KRAM 用於對關鍵硬件的初始化 這時候內部RAM被映射爲0x0地址。如果從NOR啓動,因爲NOR支持片上運行,代碼可以直接在NOR上運行 此時NOR便被映射成0x0,S3C2440 內部的4KRAM便被映射到了0x40000000處。

           下面我們看看鏈接文件。           

           對於.lds文件,它定義了整個程序編譯之後的連接過程,決定了一個可執行程序的各個段的存儲位置。先看一下GNU官方網站上對.lds文件形式的完整描述:

  1. SECTIONS {  
  2. ...  
  3. secname start BLOCK(align) (NOLOAD) : AT ( ldadr )  
  4.   { contents } >region :phdr =fill  
  5. ...  
  6. }  

secname和contents是必須的,其他的都是可選的。下面看看幾個常用的:

1secname:段名

2contents:決定哪些內容放在本段,可以是整個目標文件,也可以是目標文件中的某段(代碼段、數據段等)

3start:本段連接(運行)的地址,如果沒有使用ATldadr),本段存儲的地址也是start。GNU網站上說start可以用任意一種描述地址的符號來描述。

4ATldadr):定義本段存儲(加載)的地址

看一個簡單的例子:

  1. <span style="font-size:18px;">/* nand.lds */  
  2. SECTIONS {   
  3.     firtst 0x00000000 : { head.o init.o }   
  4.     second 0x30000000 : AT(4096) { main.o }   
  5. }</span>  

           以上,head.o放在0x00000000地址開始處,init.o放在head.o後面,他們的運行地址也是0x00000000,即連接和存儲地址相同(沒有AT指定);main.o放在40960x1000,是AT指定的,存儲地址)開始處,但是它的運行地址在0x30000000,運行之前需要從0x1000(加載處)複製到0x30000000(運行處),此過程也就用到了讀取Nand flash。這就是存儲地址和連接(運行)地址的不同,稱爲加載時域和運行時域,可以在.lds連接腳本文件中分別指定。

         編寫好的.lds文件,在用arm-linux-ld連接命令時帶-Tfilename來調用執行,如arm-linux-ld –Tnand.lds x.o y.o –o xy.o。也用-Ttext參數直接指定連接地址,如arm-linux-ld –Ttext 0x30000000 x.o y.o –o xy.o

總之:

         連接地址<==>運行地址
         存儲地址<==>加載地址

既然程序有了兩種地址,就涉及到一些跳轉指令的區別,下面就來具體看看這些跳轉指令。

ARM彙編中,常有兩種跳轉方法:b跳轉指令、ldr指令向PC賦值。

(1 b step1 :b跳轉指令是相對跳轉,依賴當前PC的值,偏移量是通過該指令本身的bit[23:0]算出來的,這使得使用b指令的程序不依賴於要跳到的代碼的位置,只看指令本身。

(2 ldr pc, =step1 :該指令是從內存中的某個位置(step1)讀出數據並賦給PC,同樣依賴當前PC的值,但是偏移量是那個位置(step1)的連接地址(運行時的地址),所以可以用它實現從FlashRAM的程序跳轉。

         加載時域與運行時域:可以這麼理解,加載時域涉及到存儲地址;運行時域涉及到連接地址(連接地址開始作用的時間是在使用僞指令ldr(adr、adrl)pc,=某符號或是某立即數時)。可執行程序在被下載到相應存儲器件裏時,它的存儲地址可以通過oflash來選擇;而當運行該程序時,一開始時PC寄存器的值是指向存儲空間的起始地址(起始地址由oflash決定)的,但在遇到僞指令ldr(adr、adrl)pc,=某符號或是某立即數(位置無關相對跳轉指令B與BL不影響運行地址)後,程序運行時的絕對地址(即PC寄存器的值)就發生了改變,它是以連接地址(由arm-linux-ld之-T選項設定)爲基址,指令所在位置爲相對地址共同組成的總之:運行地址=-T指定的連接地址+相對偏移地址;存儲地址=由oflash指定某存儲器件的起始地址+由鏈接文件中AT指定的加載地址




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章