概覽:
1. 《嵌入式Linux應用開發完全手冊_.pdf》
韋東山編寫,講解arm硬件,uboot以及linux嵌入式開發,配合2440開發板最佳。
2. 《Uboot中start.S源碼的指令級的詳盡解析_v1.6.pdf》
對理解gnu arm匯編極其有幫助。
3. 《ARM指令集快速查詢手冊.pdf》
工具手冊,快速查找各種arm指令用法。
4. 《ARM指令詳解[ARM標准].pdf》
arm匯編的一些規范和常用形式,很多例子非常有用:子程序調用、散轉、數據塊復制等。對寫裸機程序很有幫助,同樣對理解uboot和內核啟動代碼有很大幫助。
5. 《ARM體系結構與編程 杜春雷.pdf》
第二章 ARM指令分類及其尋址方式 以及第三章 ARM指令集 對深入理解arm指令有很大作用。本書已經深入到單條arm指令深度含義的解析了,很多疑難問題在這里可能得到解析。
比如:
uboot啟動文件
.globl _start
_start: b reset
編譯的uboot.dis
33f80000 <_start>:
33f80000: ea000017 b 33f80064 <reset>
我一直不明白,如果是nand啟動,這個 b 33f80064 <reset>能對嗎? 看了b指令的實際構成, 恍然大悟。這里b 33f80064絕對不是單純的跳到33f80064這個地址,b指令是當前地址+偏移地址的方式來跳轉的。
在配合下面的講解,問題得到解決。我們從uboot.dis得到的33f80064是編譯地址,不代表是運行地址。
U-BOOT詳解 http://bbs.21ic.com/forum.php?mod=viewthread&tid=857037&typeid=114
位置相關和無關碼 http://wenku.baidu.com/link?url=HZyaKmsJTR9-qdi9pH4m-4i_Rz1Uoid0i6Sl2dJ8VoKM5ZAXsardull1zPSlHd34WF2ykP9CHkC4UceOEHcewczv2ApT1L98BNEb-QQVYhG
位置無關碼 http://www.cnblogs.com/mylinux/p/5577472.html
什么是《編譯地址》?什么是《運行地址》? (一)編譯地址: 32位的處理器,它的每一條指令是4個字節,以4個字節存儲順序,進行順序執行,CPU是順序執行的,只要沒發生什么跳轉,它會順序進行執行行, 編譯器會對每一條指令分配一個編譯地址,這是編譯器分配的,在編譯過程中分配的地址,我們稱之為編譯地址。 (二)運行地址:是指程序指令真正運行的地址,是由用戶指定的,用戶將運行地址燒錄到哪里,哪里就是運行的地址。 比如有一個指令的編譯地址是0x5,實際運行的地址是0x200,如果用戶將指令燒到0x200上,那么這條指令的運行地址就是0x200, 當編譯地址和運行地址不同的時候會出現什么結果?結果是不能跳轉,編譯后會產生跳轉地址,如果實際地址和編譯后產生的地址不相等,那么就不能跳轉。 C語言編譯地址:都希望把編譯地址和實際運行地址放在一起的,但是匯編代碼因為不需要做C語言到匯編的轉換,可以認為的去寫地址,所以直接寫的就是他的運行地址這就是為什么任何bootloader剛開始會有一段匯編代碼,因為起始代碼編譯地址和實際地址不相等,這段代碼和匯編無關,跳轉用的運行地址。 編譯地址和運行地址如何來算呢? 1. 假如有兩個編譯地址a=0x10,b=0x7,b的運行地址是0x300,那么a的運行地址就是b的運行地址加上兩者編譯地址的差值,a-b=0x10-0x7=0x3, a的運行地址就是0x300+0x3=0x303。 2. 假設uboot上兩條指令的編譯地址為a=0x33000007和b=0x33000001,這兩條指令都落在bank6上,現在要計算出他們對應的運行地址,要找出運行地址的始地址,這個是由用戶燒錄進去的,假設運行地址的首地址是0x0,則a的運行地址為0x7,b為0x1,就是這樣算出來的。 為什么要分配編譯地址?這樣做有什么好處,有什么作用? 比如在函數a中定義了函數b,當執行到函數b時要進行指令跳轉,要跳轉到b函數所對應的起始地址上去,編譯時,編譯器給每條指令都分配了編譯地址,如果編譯器已經給分配了地址就可以直接進行跳轉,查找b函數跳轉指令所對應的表,進行直接跳轉,因為有個編譯地址和指令對應的一個表,如果沒有分配,編譯器就查找不到這個跳轉地址,要進行計算,非常麻煩。 什么是《相對地址》? 以NOR Flash為例,NOR Falsh是映射到bank0上面,SDRAM是映射到bank6上面,uboot和內核最終是在SDRAM上面運行,最開始我們是從Nor Flash的零地址開始往后燒錄,uboot中至少有一段代碼編譯地址和運行地址是不一樣的,編譯uboot或內核時,都會將編譯地址放入到SDRAM中,他們最終都會在SDRAM中執行,剛開始uboot在Nor Flash中運行,運行地址是一個低端地址,是bank0中的一個地址,但編譯地址是bank6中的地址,這樣就會導致絕對跳轉指令執行的失敗,所以就引出了相對地址的概念。 那么什么是相對地址呢? 至少在bank0中uboot這段代碼要知道不能用b+編譯地址這樣的方法去跳轉指令,因為這段代碼的編譯地址和運行地址不一樣,那如何去做呢? 要去計算這個指令運行的真實地址,計算出來后再做跳轉,應該是b+運行地址,不能出現b+編譯地址,而是b+運行地址,而運行地址是算出來的。 _TEXT_BASE: .word TEXT_BASE //0x33F80000,在board/config.mk中 這段話表示,用戶告訴編譯器編譯地址的起始地址
6. 下面幾篇是講解arm匯編和gnu arm匯編的小差別,了解這些主要是為了移植boot啟動代碼:
{
《第6章 ARM匯編偽指令與偽操作》ARM匯編 http://wenku.baidu.com/view/78342db069dc5022aaea00cb.html?re=view
《第6章 ARM匯編偽指令與偽操作(2) 》GNU arm匯編 http://wenku.baidu.com/view/73ec7dea998fcc22bcd10dcb.html?re=view
ARM標准匯編與GNU匯編 http://blog.sina.com.cn/s/blog_5c93b2ab0100ivfp.html
ARM匯編和Gnu匯編的轉換 http://blog.csdn.net/jun2ran/article/details/6473458
}
《嵌入式Linux應用開發完全手冊_.pdf》
《Uboot中start.S源碼的指令級的詳盡解析_v1.6.pdf》
《ARM指令集快速查詢手冊.pdf》
《ARM指令詳解[ARM標准].pdf》
《ARM體系結構與編程》杜春雷.pdf