uboot的引导阶段分为2个阶段,在第一阶段所有的寻址方式都是相对PC寻址,所以不管代码在什么地址都可以正确的运行,第一阶段还实现搬运代码到sdram,然后再跳转到第二阶段的入口地址,跳转后这时pc将指向sdram。
uboot第一阶段部分反汇编代码
- u-boot: file format elf32-littlearm
-
Disassembly of section .text:
-
33f80000 <_start>:
-
*/
-
.globl _start
-
_start: b reset
-
33f80000: ea000012 b 33f80050
-
ldr pc, _undefined_instruction
-
33f80004: e59ff014 ldr pc, [pc, #20] ; 33f80020 <_undefined_instruction>
-
ldr pc, _software_interrupt
-
33f80008: e59ff014 ldr pc, [pc, #20] ; 33f80024 <_software_interrupt>
- ......
- ......
- reset:
- /*
- * set the cpu to SVC32 mode
- */
- mrs r0,cpsr
- 33f80050: e10f0000 mrs r0, CPSR
- bic r0,r0,#0x1f
- 33f80054: e3c0001f bic r0, r0, #31 ; 0x1f
- orr r0,r0,#0xd3
- ......
- ......
由于arm多级流水线所以PC指向当前指令向下偏移2条指令(8 bytes),下文PC指向当前指令的地址
如果是norflash系统加电后PC=0,如果是s3c则进入steppingstone,然后执行第一句跳转指令
33f80000: ea000012 b 33f80050
这条指令的机器码是:0xea000012
跳转指令B,BL格式如下
In arm state, bit[1:0] are zero and bits[31:2] contain the PC. IN THUMB state, bit[0] is zero and bits[31:1] contain the PC.
arm state:ALIGN(4)
thumb state:ALIGN(2)
指令操作的伪代码:
if L == 1 then
LR = address of the instruction after branch instruction
PC = PC+ OFFSET << 2
也就是说b,bl指令只能跳到可以被4整除的内存地址处去执行,因此汇编源文件里经常看到.align n的语句
指向该指令时PC=0,PC = PC + 0x8 + 0x12 * 4; PC=0x50,指向reset代码,
而0x12是链接时计算出来的值,该偏移量与地址无关。
同理:
33f80004: e59ff014 ldr pc, [pc, #20] ; 33f80020 <_undefined_instruction>LDR指令格式
This addressing mode(mode 2) calculates an address by adding or subtracting the value of an immediate offset to or from the value of base register Rn
Syntax
[, #+/-]
where:
Specifies the register containing the base address.
Specifies the immediate offset used with the value of Rn to form the address.
Operation
if U == 1 then
address = Rn + offset_12
else /* U == 0 */
address = Rn - offset_12
所以该指令执行的效果后
PC = 【PC + 0x08 + offset_12】; PC = 【PC + 0x20】
PC的值等于PC+0x20内存地址的值
【总结】
B,Bl,LDR的地址访问方式是通过在当前值加一个偏移地址,反汇编的源码是在链接地址的基础上展开的,查看机器码可以发现代码的指向是通过相对偏移来实现的。
start.s的反汇编
- ./cpu/arm920t/start.o: file format elf32-littlearm
-
Disassembly of section .text:
-
00000000 <_start>:
-
0: ea000012 b 50
-
4: e59ff014 ldr pc, [pc, #20] ; 20 <_undefined_instruction>
-
8: e59ff014 ldr pc, [pc, #20] ; 24 <_software_interrupt>
-
......
-
......
-
00000050 :
-
50: e10f0000 mrs r0, CPSR
-
54: e3c0001f bic r0, r0, #31 ; 0x1f
-
58: e38000d3 orr r0, r0, #211 ; 0xd3
-
5c: e129f000 msr CPSR_fc, r0
-
60: e3a00453 mov r0, #1392508928 ; 0x53000000
-
......
-
......
对比uboot的反汇编代码发现机器码完全一样,被改变只是链接地址,所以程序不管是在什么地址都可以正确运行,也就是所说的地址无关代码,当然只是第一阶段引导代码。
如果代码是通过调试器运行的话,仿真器对sdram做好初始化,那么所有计算出的加载地址等于链接地址,程序运行地址等于33f80000
阅读(2492) | 评论(1) | 转发(0) |