uboot: 理解uboot要看哪些書


概覽:

 

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=0x3032.   假設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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM