1.8.重定位

位置无关编码PIC:汇编源文件被编译后编码方式与位置(内存地址)无关(放在哪都可运行)

位置有关编码:汇编源文件被编译后 编码方式与位置(内存地址)有关

大部分编码都是位置有关代码,设计一个程序时会给程序指定一个运行地址

运行地址:实际上运行的地址-------链接地址:预先设定好的地址(位置有关码必须相同)

指定方式Makefile中用  -Ttext 0x0 指定链接的地址是0x0 或用链接脚本

实际我们运行在 0xd0020010(usb启动) 0xd0020000(sd启动)

datesheet中0xd0000 0000被映射到了 0x0000 0000

 

 

启动方式

UBOOT实际使用方式: Uboot大小随意

1.上电从IROM读取预先设置的代码(BL0,64k)(可直接读取运行)....读取第一部分启动代码(BL1,16K)到内部SRAM。

2.BL1运行时初始化DDR,将整个UBOOT搬运到DDR,长跳转指令从SRAM跳转到DDR中继续执行完全启动UBOOT

2.uboot启动后在uboot中启动OS

 

重定位作用:链接地址和运行地址没办法相同,还不能全部用PIC

Linux应用地址默认链接在0x0地址的,应用程序运行在OS的进程中,独享虚拟地址空间

210裸机程序运行地址由下载确定(CPU设计确定的)

 

 

链接脚本

代码编译过程:源代码

预编译:预编译器 处理宏 注释等东西

编译:编译器 将源码编成机器码.o文件

链接:链接器 将.o文件的各个函数(段)按照一定规则(链接脚本指定)累计在一起形成可执行文件

可选步骤:如strip 将可执行程序的符号信息去掉(由Debug版>Release版)

Objcopy:由可执行程序生成可烧录的bin文件

 

程序段:(与链接有关)程序的一部分:为了在链接脚本中用段名让段排序

代码段: .text段 文本段 函数编译后生成的

数据段: .data段 C语言中有初始化的(显式初始化为非0的)全局变量

BSS段: (ZI段 zero initial) 零初始化段 对应C语言初始化为0的全局变量

自定义段:

 

链接脚本:是链接器的规则文件,然后用规定规则处理.o文件的段 将 其链接成可执行程序

关键内容: 段名+地址(作为链接地址的内存地址)

代码:

SECTIONS

{

. = 0xd0024000;

 

.text : {

start.o

* (.text)

}

 

.data : {

* (.data)

}

 

bss_start = .;

.bss : {

* (.bss)

}

bss_end = .;

}

 

练习重定位:

长跳转:类似于b bl 跳转指令通过给pc(r15)赋值来完成跳转执行 长跳转指跳转到的地址和当前地址跳转范围较为宽广ldr pc,=main

adr和ldr伪指令的区别,ldr是长加载,adr是短加载

Adr加载符号地址时加载的是运行时地址

Ldr加载时加载的是链接地址

copy_loop:

ldr r3, [r0], #4 //源

str r3, [r1], #4 //目的

cmp r1, r2 //只要没到bss起始段就一直循环(都是链接地址)

bne copy_loop

其中#4是使4个字节放入r3地址在加4

只需重定位代码段和数据段 bss要手动清

写代码出现的问题:

  1. .global _start让_start符号成为可见的标识符,这样链接器就知道跳转到程序中的什么地方并开始执行程序。
  2. start.S: Assembler messages:

start.S:24: Error: internal_relocation (type: OFFSET_IMM) not fixed up

由于把ldr伪指令忘记加赋值符导致的

 

完整代码:start.s

//定义寄存器宏

#define WTCON 0XE2700000

#define SVC_STACK 0XD0037D80

.global _start

_start:

//关看门狗

ldr r0, =0x0

ldr r1, =WTCON

str r0, [r1]

//设置SVC栈

ldr sp, =SVC_STACK

//开关icache

mrc p15,0,r0,c1,c0,0//读cp15的c1到 r0

//bic r0, r0, #(1<<12)//置0关

orr r0, r0, #(1<<12)//置1开

mcr p15,0,r0,c1,c0,0//写回去

//重定位 本实验运行在0xd0020010,被链接在0xd0024000 将来运行位置有关码时 必须放在0xd0024000

adr r0, _start

ldr r1, =_start

ldr r2, =bss_start //加载bss段起始地址

cmp r0, r1 //比较运行地址和链接地址是否相等

beq clean_bss //相等则不进行重定位跳到clean_bss

copy_loop:

ldr r3, [r0], #4 //源

str r3, [r1], #4 //目的

cmp r1, r2 //(都是链接地址)只要没到bss起始段 就一直循环

bne copy_loop

 

clean_bss:

ldr r0, =bss_start

ldr r1, =bss_end

cmp r0,r1

beq run_on_dram //如果r0和r1相等,说明bss段为空 不需清空

clean_loop:

mov r2,#0

str r2, [r0],#4

cmp r0, r1

bne clean_loop

 

run_on_dram:

//重定位完成,长跳转到main

ldr pc, =main

//开始用C写程序 bl cfunction

//bl main //bl实现短跳转c语言函数

 

b . //死循环

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

hehelot

感谢您的打赏!!!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值