前言:本文档是根据朱友鹏老师课程中重定位内容摘抄。
当目的地址和运行地址必须不相同时且不使用位置无关码,这时我们使用重定位。//其主要使用在于uboot。
我将此过程理解为:我们写的代码,在位置有关码执行之前,将整个代码复制一份到我们指定的地址,此时还运行在下载进来的代码中,然后通过一个长跳转跳到我们复制的代码中执行。注意的是我们复制的代码需要将bss段清空,防止使用内存污染。
下面还是将最简过程贴上来:
adr r0, _start //加载当前运行的地址
ldr r1, =_start //加载链接时的地址
ldr r2, =bss_start //重定位代码结束地址,重定位只需要重定位代码段和数据段即可。
cmp r0, r1 //比较当前地址和链接地址是否相同
beq clean_bss //相等直接跳到clean_bss执行,否者顺序执行。
copy_loop: //复制代码段
ldr r3, [r0], #4 //源,将r0内容拷贝到r3,然后移动四个字
str r3, [r1], #4 //目的,将r3的内容写入r1中,然后移动四个字
cmp r1, r2 //判断内容是否完全复制(是否到达文件尾)
bne copy_loop
clean_bss: //清空bss段
ldr r0, =bss_start
ldr r1, =bss_end
cmp r0, r1 //判断内容是否为空
beq run_on_dram //相等直接跳到run_on_dram执行,否者顺序执行。
mov r2, #0
clear_loop:
str r2, [r0], #4 //将r2的内容即0写入r0中,然后移动四个字
cmp r0, r1 //判断内容是否为空
bne clear_loop //内容非空,继续写0
run_on_dram:
ldr pc, =(链接到我们的c语言函数) //ldr指令实现长跳转