對連結地址的理解

來源:互聯網
上載者:User

標籤:

  當我們寫連結器指令碼的時候,我們會設定程式碼片段的起始連結地址為0x30008000(S3C2440)。如果對連結地址理解錯誤的話,可能會出現像我這樣的問題。

  Q:gboot的連結器指令碼裡寫的其實連結地址是記憶體中的0x30008000,再用交叉工具反組譯碼得到的start.S前幾行代碼地址都變成了0x30008000+,不太對啊。ARM啟動流程裡面講處理器將NAND中的代碼複製了4K到墊腳石中,墊腳石的地址是0x0,也正是因為這樣,我們設定的異常向量表才有意義,處理器才能準確的找到處理異常的標號。但是把連結地址改成了0x30008000還怎麼找?

  A:首先要理解連結地址。我認為,連結地址就是為程式假想了一個起點,之後的代碼都是在這個假想的起點基礎上展開的。我們只有根據這個連結地址,才能找到後續的一些指令並執行。但是這個連結地址不是實際的指令的地址,我們先對gboot.elf進行反組譯碼看看

30008000 <_start>:30008000:    ea000014     b    30008058 <reset>30008004:    e59ff014     ldr    pc, [pc, #20]    ; 30008020 <_undefined_instruction>30008008:    e59ff014     ldr    pc, [pc, #20]    ; 30008024 <_software_intrrupt>3000800c:    e59ff014     ldr    pc, [pc, #20]    ; 30008028 <_prefetch_abort>30008010:    e59ff014     ldr    pc, [pc, #20]    ; 3000802c <_data_abort>30008014:    e59ff014     ldr    pc, [pc, #20]    ; 30008030 <_not_used>30008018:    e59ff014     ldr    pc, [pc, #20]    ; 30008034 <_irq>3000801c:    e59ff014     ldr    pc, [pc, #20]    ; 30008038 <_fiq>

用b reset舉例,雖然reset標號的地址已經到了0x30008000,但是我們的代碼此時實際上是在墊腳石中啟動並執行,也就是說PC指標還是指在0x0的位置。這樣0x0和0x30008000就形成了一個映射的關係,即0x4相當於0x30008004,0x8相當於0x30008008......,都是因為我們將連結起始地址設成了0x30008000,這也就是我們所說的相對跳轉。

  Q:為什麼連結起始地址要寫成0x30008000?

  A:照理說這個地址是隨意的,只要在S3C2440的定址空間內都可以。但是後期我們要執行C語言程式,而對堆棧等的初始化都是對SDRAM進行的,即在0x30000000之後的64M空間中。所以為了C語言能夠成功運行,直接將代碼的連結地址設到記憶體中,這樣方面之後的絕對跳轉,即

ldr pc, =main

 

對連結地址的理解

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.