.word __bss_start @ r2 bss 段的起始地址在 vmlinux.lds.S 中定义
.word _end @ r3 zImage(bss)连接的结束地址在 vmlinux.lds.S 中定义
.word zreladdr @ r4 zImage 的连接地址,我们在 arch/arm/mach-s3c2410/makefile.boot 中定义的
.word _start @ r5 zImage 的基地址,bootp/init.S 中的_start 函数,主要起传递参数作用
.word _got_start @ r6 GOT(全局偏移表)起始地址,_got_start 是在 compressed/vmlinux.lds.in 中定义的
.word _got_end @ ip GOT 结束地址
.word user_stack+4096 @ sp 用户栈底 user_stack 是紧跟在 bss 段的后面的,在 compressed/vmlinux.lds.in 中定义的
@ 在本 head.S 的末尾定义了 zImag 的临时栈空间,在这里分配了 4K 的空间用来做堆栈。
.section ".stack", "w"
user_stack: .space 4096
GOT 表的初值是连接器指定的,当时程序并不知道代码在哪个地址执行。如果当前运行的地址已经和表上的地址不一样,还要修正 GOT 表。*/
.text
adr r0, LC0 /*把地址表的起始地址放入 r0 中*/
ldmia r0, {r1, r2, r3, r4, r5, r6, ip, sp} /*加载地址表中的所有地址到相应的寄存器*/
@r0 是运行时地址,而 r1 则是链接时地址,而它们两都是表示 LC0 表的起始位置,这样他们两的差则是运行和链接的偏移量,纠正了这个偏移量才可以运行与”
地址相关的代码“
subs r0, r0, r1 @ calculate the delta offset 计算偏移量,并放入 r0 中
beq not_relocated @ if delta is zero, we are running at the address we were linked at.
@ 如果为 0,则不用重定位了,直接跳转到标号 not_relocated 处执行
/*
* 偏移量不为零,说明运行在不同的地址,那么需要修正几个指针
* r5 – zImage 基地址
* r6 – GOT(全局偏移表)起始地址
* ip – GOT 结束地址
*/
add r5, r5, r0 /*加上偏移量修正 zImage 基地址*/
add r6, r6, r0 /*加上偏移量修正 GOT(全局偏移表)起始地址*/
add ip, ip, r0 /*加上偏移量修正 GOT(全局偏移表)结束地址*/
/*
* 这时需要修正 BSS 区域的指针,我们平台适用。
* r2 – BSS 起始地址
* r3 – BSS 结束地址