ARM中通過ldr pc, xxx地址,來跳轉到對應的絕對地址去執行
阿新 • • 發佈:2018-12-19
在學習ARM裸機實時,對於程式的連結地址和程式的執行地址是很重要的,通常在程式的前幾k的程式碼中使用的都是相當跳轉指令b,bl,前面幾k的程式碼的主要任務就是將整個程式複製到對應的連結地址上去的。這個過程就是程式碼的重定位,在重定位之前的程式碼與位置無關(是位置無關碼);重定位完成以後就可以跳轉到新的地址中去運行了,通常使用 ldr pc, xxx,來實現跳轉。這裡先來看看三段彙編程式碼,來理解uboot中重定位後,跳轉的實現。und_addr,do_und都是標記,也就是地址。
- ldr pc, und_addr(這是uboot中的用法)
- ldr pc, do_und
- ldr pc, =do_und(這是一條偽指令)
.text .global _start _start: b reset ldr pc, und_addr //1 //ldr pc, do_und //2 //ldr pc, =do_und //3 und_addr: .word do_und do_und: //設定未定義指令異常是的棧 ldr sp, =0x34000000 //儲存現場 stmdb sp!, {r0-r12, lr} //0x600000DB mrs r0, cpsr ldr r1, =und_string bl printException //輸出sprs 0x600000D3 mrs r0, spsr bl putHex ldmia sp!, {r0-r12, pc}^
分別編譯這三種情況,然後反彙編檢視彙編代買。
ldr pc, und_addr(這是uboot中的用法)
30000000 <_start>: 30000000: ea00000e b 30000040 <reset> 30000004: e51ff004 ldr pc, [pc, #-4] ; 30000008 <und_addr> 30000008 <und_addr>: 30000008: 3000000c .word 0x3000000c 3000000c <do_und>: 3000000c: e3a0d30d mov sp, #872415232 ; 0x34000000 30000010: e92d5fff push {r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, sl, fp, ip, lr} 30000014: e10f0000 mrs r0, CPSR 30000018: e59f109c ldr r1, [pc, #156] ; 300000bc <halt+0x4> 3000001c: eb0000dd bl 30000398 <printException>
ldr pc, do_und
30000000 <_start>:
30000000: ea00000e b 30000040 <reset>
30000004: e59ff000 ldr pc, [pc, #0] ; 3000000c <do_und>
30000008 <und_addr>:
30000008: 3000000c .word 0x3000000c
3000000c <do_und>:
3000000c: e3a0d30d mov sp, #872415232 ; 0x34000000
30000010: e92d5fff push {r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, sl, fp, ip, lr}
30000014: e10f0000 mrs r0, CPSR
30000018: e59f109c ldr r1, [pc, #156] ; 300000bc <halt+0x4>
ldr pc, =do_und(這是一條偽指令)
30000000 <_start>:
30000000: ea00000e b 30000040 <reset>
30000004: e59ff0b0 ldr pc, [pc, #176] ; 300000bc <halt+0x4>
30000008 <und_addr>:
30000008: 3000000c .word 0x3000000c
3000000c <do_und>:
3000000c: e3a0d30d mov sp, #872415232 ; 0x34000000
30000010: e92d5fff push {r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, sl, fp, ip, lr}
30000014: e10f0000 mrs r0, CPSR
30000018: e59f10a0 ldr r1, [pc, #160] ; 300000c0 <halt+0x8>
3000001c: eb0000dd bl 30000398 <printException>
30000020: e14f0000 mrs r0, SPSR
...
...
...
300000b8 <halt>:
300000b8: eafffffe b 300000b8 <halt>
300000bc: 3000000c .word 0x3000000c
300000c0: 3000002c .word 0x3000002c
300000c4: 4c000014 .word 0x4c000014
300000c8: 4c000004 .word 0x4c000004
程式碼中為什麼要在定義下面這段
und_addr: .word do_und
主要是為了佔領一個位置,不然這個地址放大CPU的片內srom以外了,不然就找不到他了。
在ldr pc, und_addr中可以將pc=3000000c,實現跳轉
ldr pc, do_und,實現的是pc=e3a0d30d,是錯誤的。
ldr pc, =do_und,可能可以實現pc=3000000c,這還要取決於程式碼是超過了片內srom的大小ldr pc, [pc, #176] ; 300000bc <halt+0x4>,不可靠,也無法預測。