2013-03-27 65 views
5

我有一個在程序集中編寫的裸機ARM的啓動代碼,我試圖理解它是如何工作的。該二進制文件被寫入一些外部Flash中,並在啓動時將其自身的一部分拷貝到RAM中。儘管我讀到wikipedia entry,但我仍然沒有完全明白這種情況下的搬遷概念。 RAM被映射到低地址窗口,並且閃存在高地址窗口中。有人可以向我解釋爲什麼我們在這裏測試鏈接寄存器的值嗎?在程序集中的重新定位

/* Test if we are running from an address, we are not linked at */ 
     bl check_position 
check_position: 
     mov  r0, lr     
     ldr  r1, =check_position 
     cmp  r0, r1     /* ; don't relocate during debug */ 
     beq  relocated_entry 
+0

謝謝你的兩個很好的答案!我會接受這兩個,因爲我解釋了代碼的目標(JTAG程序加載器的假設是正確的),第二個是如何工作的。 – 2013-03-28 14:50:37

回答

5

我的猜測是應用程序從RAM中運行,調試應用程序時,這個作者也許是使用某種引導程序和或JTAG的直接加載測試程序到RAM中,因此沒有理由複製和運行(這可能會導致崩潰)。

你會這樣做的另一個原因是爲了避免無限循環。例如,如果你想從flash啓動(通常必須),但是從ram執行,最簡單的方法是將整個flash或整個flash的一部分複製到ram,然後轉到ram的開頭。當你這樣做的時候,你意味着你再次點擊「複製應用程序到RAM和分支」循環,以避免它第二次(這可能會使你崩潰),你有某種我從閃存運行這個循環或不測試。

3

任何人都可以向我解釋爲什麼我們在這裏測試鏈接寄存器的值?

bl check_position將放置的PC+4值到鏈接寄存器並轉移控制到check_position也PC相對的。 bl at ARM到目前爲止,一切都是PC相對。

ldr r1,=check_position從文字池中獲取值Ref1至實際的代碼看起來像,

ldr r1,[pc, #offset] 
... 
    offset: 
    .long check_position # absolute address from assemble/link. 

所以R0包含PC相對版和R1包含絕對組裝版本。在這裏,他們進行比較。如果非零,你也可以用算術來計算差值,然後分支;或者可能將代碼複製到絕對目標。 Ref2如果代碼是運行連接的地址,那麼R0R1是相同的。這是bl的一些pseudo code

mov lr,pc    ; pc is actually two instruction ahead. 
add pc,pc,#branch_offset-8 

的關鍵是,BL做基礎上,PC一切,包括的lr更新。我們可以使用mov R0,PC來代替這個技巧,但PC是8字節。另一種方法是使用adr R0,check_position,這將使彙編程序爲我們完成所有地址數學運算。

/* Test if we are running from an address, we are not linked at */ 
check_position: 
    adr r0, check_position 
    ldr r1, =check_position 
    cmp r0, r1     /* ; don't relocate during debug */ 
    beq relocated_entry 

Ref1至:Arm op-codes.ltorg在GNU彙編手冊
至Ref2:這正是Linux的head.S做了ARM。

編輯:我檢查了ARM ARM,PC很明顯是當前的指令+8,這說明爲什麼代碼是這樣的。我認爲adr版本更直接,更易讀,但adr僞操作不經常使用,所以人們可能不熟悉它。