隨便找個IAR或者其他編譯器生成的map文件。我們不難發現程序就是 .txt, .bss, .data等段的集合。
再仔細一看,BL _main,_main是一個地址,.data段也有地址。這些地址是如何來的呢?
編譯器地址空間:
編譯器按照一定的地址空間來編譯程序,最終的程序就是指令和地址的集合,這個地址空間就是編譯器地址空間。
CPU統一尋址空間:
CPU按照統一編址的地址去訪問相關數據或者硬件。
編譯地址空間和物理地址空間要對上號才能正確運行。爲什麼呢?
如:BL _main(0x800000000). 這條是編譯器編譯出來指令,就是跳轉到0x80000000,
假如執行完上述指令,cpu pc指針指向0x80000000,而該處沒有指令,而是一個寄存器的地址,那麼程序是沒有辦法執行的下去的。
如何實現編譯地址空間和物理地址空間要對上號?
通過兩種方法來實現
1:一種是編譯時確定,就是給編譯器設定參數比如某個段從某個地址開始編譯。
一般如嵌入式中常見的從0x8000000, 0x2000000.或者你可以單獨定義數據段從某個地址開始。
然後通過bootloader 或者PC端載入程序把程序載入到對應的地址運行。
這種方式適合沒有mmu的嵌入式系統的編譯和載入。尤其要求載入的物理地址必須與代碼段編譯地址空間相對應(起始位置要相同)。
2: 通過MMU來實現地址的重定位。
編譯器不關心的物理地址,編譯器把編譯地址認爲從0-4g進行統一編址。
每個elf文件被載入內存,首先確定其載入內存所在的地址作爲基地址,或者說將elf文件映射到對應的空間中。