編譯地址與運行地址

(1)什麼是編譯地址
  32位的處理器,它的每一條指令是4個字節,以4個字節存儲順序,進行順序執行,CPU是順序執行的,只要沒發生什麼跳轉,它會順序進行執行行, 編譯器會對每一條指令分配一個編譯地址,這是編譯器分配的,在編譯過程中分配的地址,我們稱之爲編譯地址。
  uboot裏面,在include/configs目錄下有相應平臺的頭文件,比如我使用的是飛思卡爾的cpu(IMX6SL),對應的頭文件是include/configs/mx6slevk.h,裏面的宏定義:#define CONFIG_SYS_TEXT_BASE 0x87800000用來告訴編譯器編譯地址的起始地址。
  在uboot的Makefile文件中使用-Ttext將這個地址傳進去,LDFLAGS_u-boot += -Ttext $(CONFIG_SYS_TEXT_BASE)。下面解釋一下-Ttext這個參數的作用。
  首先來看具體的兩條命令

編譯  $(CC) $(CFLAGS) -DKERNEL_START=$(TEXT_START) -c mbr_start.S -o $(OBJDIR)/mbr_start.o
鏈接  $(LD) -Ttext=0x7c00 -o $(OBJDIR)/mbr $(OBJDIR)/mbr_start.o $(OBJDIR)/mbr.o

  第一行編譯mbr_start.S並傳入參數KERNEL_START,生成目標文件mbr_start.o;第二行,連接mbr_start.o和mbr.o生成mbr,並將程序重定向到0x7c00處。即,-Ttext是連接時將初始地址重定向爲0x7c00(若不註明此,則程序的起始地址爲0)。比如,在mbr_start.S文件中函數inb()的編譯完成後在mbr_start.o中的偏移地址是0x006b,則在連接時指定-Ttext=0x7c00,連接之後其地址爲0x7c6b, 其他函數調用此函數時,也就會調用地址0x7c6b,而不會是0x006b。
  
(2)什麼是運行地址
  是指程序指令真正運行的地址,是由用戶指定的,用戶將二進制程序燒錄到哪裏,哪裏就是運行的地址。比如有一個指令的編譯地址是0x5,實際運行的地址是0x200,如果用戶將指令燒到0x200上,那麼這條指令的運行地址就是0x200。
  
(3)當編譯地址和運行地址不同的時候會出現什麼結果?
  結果是不能跳轉,編譯後會產生跳轉地址,如果實際地址和編譯後產生的地址不相等,那麼就不能跳轉,所以都希望把編譯地址和實際運行地址放在一起的。但是彙編代碼因爲不需要做C語言到彙編的轉換,可以人爲的去寫地址,所以直接寫的就是他的運行地址這就是爲什麼任何bootloader剛開始會有一段彙編代碼。
  
(4)爲什麼要分配編譯地址?
  比如在函數a中定義了函數b,當執行到函數b時要進行指令跳轉,要跳轉到b函數所對應的起始地址上去,編譯時,編譯器給每條指令都分配了編譯地址,如果編譯器已經給分配了地址就可以直接進行跳轉,查找b函數跳轉指令所對應的表,進行直接跳轉,因爲有個編譯地址和指令對應的一個表,如果沒有分配,編譯器就查找不到這個跳轉地址,要進行計算,非常麻煩。

發佈了57 篇原創文章 · 獲贊 80 · 訪問量 23萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章