15. 从0开始学ARM-位置无关码

发布者:sclibin最新更新时间:2021-07-28 来源: eefocus关键字:ARM  位置无关码  启动流程 手机看文章 扫描二维码
随时随地手机看文章

一、为什么需要位置无关码?

首先我们需要了解一下ARM板子的启动流程。

1. exynos 4412启动流程

  1. 首先看一下 exynos 4412 memory map :
    Memory Map可知:
    iROM基地址是0x00000000
    iRAM基地址是0x02020000

这两块内存都在 SOC中。

  1. 查看exynos 4412 Booting Sequence:

位于第五章。

Booting Time Operation
上图是exynos4412上电复位时的启动流程,大致如下:

<1>执行内部只读存储器iROM中的一段代码(厂家固化在里面的),这段代码主要是初始化一些系统的基本配置,比如初步时钟配置、堆栈、启动模式(对应图中的标志①)。

<2>iROM中的代码根据阶段一获取的启动模式(OM_STAT寄存器),从相应的存储介质中拷贝BL1镜像到内部静态随机存储器SRAM,BL1主要是完善系统时钟的初始化工作、内存控制器一些时序的配置。做完这些工作后把OS镜像拷贝到内存中(对应图中标志②③)。

<3>跳转到OS中执行。

SRAM只有256KB,而uboot镜像一般是超过这个大小的,也就是说它不能把完整的uboot镜像拷贝到SRAM中,因此,推测这里的拷贝方式应该还是:BL1拷贝的仅仅是uboot的一部分,这一部分除了能设置好基本的硬件运行环境外,还能把其自身(uboot镜像)完整的拷贝到内存中,然后uboot在内存中运行,完成OS镜像的拷贝和引导

一般情况下两者的地址并不相同,程序在DRAM中的地址重定位过程必须由程序员来完成。

这样就有了位置无关代码的概念,指代码不在连接时指定的运行地址空间,也可以执行,它一段加载到任意地址空间都能执行的特殊代码。

uboot搬移到DRAM中,然后跳转到DRAM继续运行uboot剩下的代码,那么在搬移之前的这段代码必须是位置无关,而且不能使用绝对寻址指令,否则寻址就会出错。


二、怎么实现位置无关码?

1. 什么是《编译地址》?什么是《运行地址》?

编译地址:

32位的处理器,它的每一条指令是4个字节,以4个字节存储顺序,进行顺序执行,CPU是顺序执行的,只要没发生什么跳转,它会顺序进行执行, 编译器会对每一条指令分配一个编译地址,这是编译器分配的,在编译过程中分配的地址,我们称之为编译地址。

运行地址:

是指程序指令真正运行的地址,是由用户指定的,用户将运行地址烧录到哪里,哪里就是运行的地址。
比如有一个指令的编译地址是0x40008000,实际运行的地址是0x40008000,如果用户将指令烧到0x60000000上,那么这条指令的运行地址就是0x60000000。

当编译地址和运行地址不同的时候会出现什么结果?
结果是不能跳转,编译后会产生跳转地址,如果实际地址和编译后产生的地址不相等,那么就不能跳转。

C语言编译地址:

都希望把编译地址和实际运行地址放在一起的,但是汇编代码因为不需要做C语言到汇编的转换,可以直接的去写地址,所以直接写的就是他的运行地址,这就是为什么任何bootloader刚开始会有一段汇编代码,因为起始代码编译地址和实际地址不相等,这段代码和汇编无关,跳转用的运行地址。


2. 举例

实现位置无关码主要考虑以下两个方面:


1. 位置无关的函数跳转2. 位置无关的常量访问

下面我们通过两个例子详细讲解。


3. 代码

编译代码使用的连接文件map.lds如下:


OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")/*OUTPUT_FORMAT("elf32-arm", "elf32-arm", "elf32-arm")*/OUTPUT_ARCH(arm)ENTRY(_start)SECTIONS{. = 0x40008000;. = ALIGN(4);.text      :{

gcd.o(.text)*(.text)}. = ALIGN(4);.rodata : 

{ *(.rodata) }. = ALIGN(4);.data : 

{ *(.data) }. = ALIGN(4);.bss : { *(.bss) }}

如文件map.lds所示:0x40008000就是链接地址,


其他源文件如下:

gcd.s


.text.global _start

_start:

ldr sp,=0x70000000         /*get stack top pointer*/

bl func

ldr pc,=func

b main

func:

mv pc,lr

main.c


/*

 * main.c

 *

 *  Created on: 2020-12-12

 *      Author: 一口Linux

 */int aaaa=0; int main(void){

aaaa = 0x11;while(1);return 0;}

Makefile


TARGET=gcd

TARGETC=main

all:

arm-none-linux-gnueabi-gcc -O1 -g -c -o $(TARGETC).o  $(TARGETC).c

arm-none-linux-gnueabi-gcc -O1 -g -c -o $(TARGET).o $(TARGET).s

arm-none-linux-gnueabi-gcc -O1 -g -S -o $(TARGETC).s  $(TARGETC).c

arm-none-linux-gnueabi-ld $(TARGETC).o $(TARGET).o -Tmap.lds  -o  $(TARGET).elf 

arm-none-linux-gnueabi-objcopy -O binary -S $(TARGET).elf $(TARGET).bin

arm-none-linux-gnueabi-objdump -D $(TARGET).elf > $(TARGET).dis


clean:

rm -rf *.o *.elf *.dis *.bin

反汇编文件gcd.dis

链接地址0x40008000

如上图所示:


_start对应的链接地址是0x40008000

9行 bl func对应的指令

10行 ldr pc,=pc对应的指令

func的链接地址0x40008010

全局变量aaaa对应的内存位于bss段0x4000802c

19行 aaaa = 0x11 赋值语句对应的机器码

如果我们将生成的bin文件拷贝到内存0x40008000位置运行必然没有问题,


bl func 和 ldr pc,=func 都能跳转到func函数,

而19行代码,也能访问到全局变量aaaa。

如果我们将该程序拷贝到其他地址是否能正常运行呢?


假定我们拷贝到0地址运行,那么程序的执行地址需要从0开始重新编排,即_start对应0地址,main对应0x18。


拷贝到0地址后内存布局:

拷贝到0地址后内存布局
拷贝到0地址运行后,**内存中指令(机器码)**的内容还和以前一样,
pc的值会根据实际运行地址重新修正。

  1. 首先看bl func

对应的汇编代码是 第9行;
该指令的机器码是0xeb000001,
我们在《4. 从0开始学ARM-ARM指令,移位、数据处理、BL、机器码》讲过该机器码格式是从pc的位置向前偏移1条指令
因为三级流水线,所以应该往下偏移3条指令,即func的位置,
所以bl仍然可以正确找到func这个函数。

bl func

  1. ldr pc,=func
    对应的汇编代码是 第10行;

ldr pc,=func
我们可以看到是从pc值+4位置取出对应的内存的值,pc值+4是14,该位置对应15行,
即将40008010写入到pc,

而我们的bin文件只有44个字节大小,所以此时内存40008010并没有我们编写的任何代码。


所以ldr pc,=func 无法跳转到func。

  1. c访问全局变量aaaa

对应的汇编代码是 第19行;

c访问全局变量aaaa

我们可以看到是从pc值+4位置取出对应的内存的值,pc值+4是28,该位置对应22行,
即将4000802c写入到r3,然后20行会将r2中值写入到0x4000802c这个地址,
而此时该地址并不是全局变量aaaa,
所以此指令是无法找到bss段的aaaa变量的内存。


四、总结

1. 位置无关码:

CPU取指时用相对地址取指令(比如pc +4),只要其相对地址没有变,都能够取指并运行。即该段代码无论放在内存的哪个地址,都能正确运行。究其原因,是因为代码里没有使用绝对地址,都是相对地址。


2. 位置相关码:

利用绝对地址取指并运行,这就需要你存放程序(链接过程中)需要按照连接脚本的要求那样执行(Makefile里面有 -Ttext xxx指定或连接脚本)。
即它的地址与代码处于的位置相关,是绝对地址,如:mov PC ,#0xff;ldr pc,=0xffff等。


3. 位置无关码的应用:

1). 程序在运行期间动态加载到内存;
2). 程序在不同场合与不同程序组合后加载到内存(共享的动态链接库);
3). 在运行期间不同地址相互之间的映射(如bootloader)


4. 结论

  1. 使用mov pc ,xxx ; ldr pc ,xxx等就是位置相关码。这些使用绝对指令寻址。

  2. 而使用bl ,b ,adr,ldr一般为位置无关码。

  3. 在使用b, bl调用C语言中的函数里不要使用全局变量,因为C中全局变量的地址也是根据链接地址生成的。

  4. 使用=和不使用=号是有很大区别的。
    无=号:取该标号处的值,位置无关
    有=号:取该标号的地址,位置相关

五、思考题

考一考大家为什么uboot的异常向量表的reset异常,指令是b reset,而其他异常却是我们本文所说的位置相关码,ldr pc,XXXXXX?

arm对应的uboot异常向量表如下:

arch/arm/cpu/armv7/start.S

在这里插入图片描述

关键字:ARM  位置无关码  启动流程 引用地址:15. 从0开始学ARM-位置无关码

上一篇:23. 基于Cortex-A9 uboot代码启动分析
下一篇:移植uboot-支持yaffs烧写,打补丁

推荐阅读最新更新时间:2024-11-04 07:42

矽鼎陈海雷:MID未来的方向是x86架构
    MID是什么?     从概念上理解,它是MobileInernetDevice的缩写,翻译成中文就是:移动互联网设备。最早的MID设备出现于2008年IDF大会上。按英特尔的定义,这是一种体积小于笔记电脑,但大于手机的流动互联网装置。通过MID,用户可进入互联网,随时享受娱乐、进行信息查询、邮件收发等操作。     在目前上网本如火如荼、 智能手机 步步紧逼的市场态势下,MID将走向何处了?作为英特尔在国内的重要战略合作伙伴,无锡矽鼎科技公司的CEO陈海雷博士认为:x86架构将会是MID发展的方向,而上网本并不会挤占原本属于MID的市场空间。     英特尔与Marvell的交易不是心血来潮     我们
[单片机]
X86没戏?欧洲百亿亿次超算或由ARM与RISC-V扛大旗
近年来,欧洲不断在超算方面进行布局。欧盟委员会希望在2022年至2023年部署一套计算能力达每秒百亿亿次的超级计算机和相应数据基础设施,并计划到2026~2027年使其计算能力超越上述级别。 今年,欧洲不断为推进自研超计算机微处理器加码。 今年3月,欧委会宣布推出欧洲处理器计划(EPI),以协同设计和开发一款低功耗微处理器,并将其推向市场。该计划汇集了欧洲10个国家的23家合作伙伴,以及各界专家。他们将通过协同设计方案,设计和开发第一批欧洲HPC片上系统和加速器,所有的组件都将在一台原型系统上实现和验证,该原型将为开发欧洲全自主的百亿亿次计算机奠定基础。EPI是欧洲高性能计算联合事业(EuHPC-JU)的组成部分之一,专门
[嵌入式]
X86没戏?欧洲百亿亿次超算或由<font color='red'>ARM</font>与RISC-V扛大旗
友善s3c2440init.s启动流程
菜鸟看s3c2440init.s启动代码,总结了一下: 1、关闭看门狗 2、关闭所有中断 3、设置时钟频率 4、初始化SDRAM 5、初始化各个模式下的堆栈(用户模式除外) 6、数据段复制,以及清零ZI段 7、跳转到main.c中执行主函数 认真看了一下其.s的代码,大概的流程是这样。如有错误,请告知。
[单片机]
联发科看淡ARM进入Windows PC机会
  据美国媒体报道,尽管过去几年比较糟糕,但今年晚些时候 Windows PC将依靠 ARM 芯片回归,只是只有高通芯片。另一家重要的 ARM 芯片制造商联发科(MediaTek)并未争取将 ARM 芯片安装到 Windows PC的机会,因为该公司认为这种机会有限。下面就随嵌入式小编一起来了解一下相关内容吧。   联发科的芯片已经使用到Chromebook中,但ARM在 Windows 中的应用历史比较糟糕,这是该公司置身局外的另一个原因。ARM进入PC的情况如同英特尔试图打入智能手机市场一样--联发科的销售总经理分巴尔·莫伊尼翰(FinbarrMoynihan)表示,这是冒险的主张。PC主要运行英特尔和AMD的x86芯片,但
[嵌入式]
ARM嵌入式平台的VGA接口设计
  大多数嵌入式产品的显示终端都选择LCD,但在某些需要大屏幕显示的应用中,工业级LCD的价格比较昂贵,且现有的大屏幕显示器(包括CRT显示器和LCD显示器)一般都采用统一的15针VGA显示接口。三星公司ARM9芯片S3C2410以其强大的功能和高性价比在目前嵌入式产品中得到广泛的应用。笔者在开发基于ARM嵌入式平台的血液流变测试仪的过程中,成功地利用高性能视频D/A转换芯片ADV7120,将S3C2410自带的LCD扫描式接口转换为VGA接口,使之能够驱动VGA接口的显示器。   1 VGA接口介绍   近年来,业界制定出了众多数字化的显示接口协议,较为典型的是DVI(Digital Visual Interface)。
[单片机]
<font color='red'>ARM</font>嵌入式平台的VGA接口设计
MCU,DSP,ARM学习方法经验分享
  很多初学者,甚至是混了好几年的老手,都在抱怨,电子这行怎么竞争这么大啊? 颓废,这完全在抹杀自己的激情,没了激情,搞电子,完全就是在浪费生命。其实,竞争真的大吗??对比一下,难道做业务的竞争不大,做管理的竞争不大,现在这个社会,哪个领域,哪个行业,竞争都大,所以,假如你想逃避竞争,那你就不用活了,当然,你本身家庭很好,父辈好有米的话,那另当别论!所以, 不管什么行业,竞争大不大的问题,都不用问了。答案都是:竞争大,但是必须面对,我们要自己面对的竞争越小,那么你的技术能力应该是越牛X。搞电子的人要跟得上时代,但是人的脑袋会随着年龄的增大而迟钝,所以这就造成了电子人才(特别是搞电子软件)的一种生老病死的自然规律。也就是说,一般40
[单片机]
基于ARM Linux的无线音视频对讲系统分析
随着数字化和网络化时代的到来,尤其是宽带无线网络的发展,为音视频这样大数据量传输业务在无线网络上的应用提供了契机。同时由于音视频独特的感官特性,使其相关的应用需求也变得越来越迫切。无线多媒体是多媒体和移动通信这两个领域的技术相互融合的产物,成为当今通信领域的一个热点。鉴于Linux内核的开源性,采用其作为操作系统,从而使整个系统具有更好的实时性和稳定性。整个系统以ARM11为核心处理器、采用新一代视频编解码标准H.264进行编译码,并通过无线网络传输音视频。它充分利用S3C6410微处理器内部集成的多媒体编解码器(Multi-Formatvideo Codec,MFC),有效提高了系统的性价比。整个系统为无线多媒体音视频的传输提供
[单片机]
基于<font color='red'>ARM</font> Linux的无线音视频对讲系统分析
拒绝X86 传Facebook将使用ARM服务器
凭借着掌上设备市场的突飞猛进,如今ARM架构处理器的声势已经今非昔比,甚至引起了有关x86是否可能被替代的讨论。虽然我们可以承认ARM架构智能本在功能上确实有可能取代x86笔记本,但绝大多数人不会想到的是,在高端服务器市场,ARM处理器也有可能替代x86。 近期有消息传出,社交网络大鳄Facebook准备在美国俄勒冈州兴建新数据中心时,使用ARM架构服务器,替代传统的x86产品。消息称来自美国得克萨斯州奥斯丁的芯片设计公司Smooth-Stone将承担为Facebook定制ARM服务器处理器的任务,而SuperMicro则会提供服务器主板。 虽然大家还很难想象常见于智能手机中的ARM处理器性能匹敌Intel至
[嵌入式]
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
随便看看

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved