ARM位置无关代码设计规范
- 格式:doc
- 大小:42.50 KB
- 文档页数:5
ARM7支持六种操作模式:(1)用户模式(usr):正常的程序执行状态(2)FIQ模式(fiq):支持数据传送或通道处理(3)IRQ模式(irq):用于通用的中断处理(4)管理模式(svc):用于操作系统的保护模式(5)异常模式(abt):数据或者指令预取异常时进入(6)无定义模式(und):当无定义指令被执行时进入(7)软件控制,外部中断,异常处理都可以改变操作模式。
大部分的应用程序在用户模式下执行。
其他模式,比如管理模式,在中断、异常服务、或者访问被保护资源时进入。
ARM 的中央寄存器集是16 个用户寄存器R0 – R15。
这些寄存器均是32 位宽度,R0 – R12 没有其他特殊功能,寄存器R13 – R15在CPU中有特殊功能。
R13被用作栈指针(stack pointer,SP)。
R14被称为链接寄存器(link register, LR),当调用一个函数时返回地址被自动保存到链接寄存器,在函数返回时有效。
这使得快速进入和返回“叶”函数(不调用其他函数的函数)成为可能。
如果函数是分支的一部分(即该函数将调用另一个函数),链接寄存器必须入栈(R13)。
R15 是程序计数器(program counter, PC)。
有趣的是,许多指令也可以在R13 – R15中执行,就像它们是标准的用户寄存器。
ARM中断的问题ARM的七种异常类型---------1> 复位异常2> 数据访问中止异常3> 快速中断请求异常4> 一般中断请求5> 预取指令异常6> 软件中断异常7> 未定义异常-------------------------问题:1> 为什么除了进入复位异常模式外,在别的异常处理模式中都允许FIQ中断?2> 数据访问中止异常的优先级大于 FIQ异常,为什么在数据访问异常处理模式中,还允许 FIQ中断?这样不就成了:在高优先级异常处理中允许低优先级的中断发生?即使这样,因为FIQ中断的优先级 < 数据异常中断优先级,也不会进入 FIQ中断处理程序啊,这样不就更没有用处了??ARM体系的各种异常的分析(学习日记)- [ARM7TDMI]版权声明:转载时请以超链接形式标明文章原始出处和作者信息及本声明/logs/10669519.html1.复位异常(1)当内核的nRESET信号被拉低时,ARM处理器放弃正在执行的指令,当nRESET信号再次变高时,ARM处理器进行复位操作;(2)系统复位后,进入管理模式对系统进行初始化,复位后,只有PC(0x00000000)和CPSR (nzcvqIFt_SVC)的值是固定的,另外寄存器的值是随机的。
Arm中的链接文件的规则-T选项是ld命令中比较重要的一个选项,可以用它直接指明代码的代码段、数据段、博士生、段,对于复杂的连接,可以专门写一个脚本来告诉编译器如何连接。
-Ttext addr-Tdata addr-Tbss addrarm-elf-ld -Ttext 0x00000000 -g led_On.o -o led_on_elf ,运行地址为0x00000000,由于没有data和bss,他们会默认的依次放在后面。
相同的代码不同的Ttext,你可以对比一下他们之间会变的差异,ld会自动调整跳转的地址。
*简单的Linker script(1) SECTIONS命令:The SECTIONS command tells the linker how to map input sections into output sections, and how to place the output sections in memory.命令格式如下:SECTIONS{sections-commandsections-command......}其中sections-command可以是ENTRY命令,符号赋值,输出段描述,也可以是overlay描述。
(2) 地址计数器‘.’(location counter):该符号只能用于SECTIONS命令内部,初始值为‘0’,可以对该符号进行赋值,也可以使用该符号进行计算或赋值给其他符号。
它会自动根据SECTIONS命令内部所描述的输出段的大小来计算当前的地址。
(3) 输出段描述(output section description):前面提到在SECTIONS命令中可以作输出段描述,描述的格式如下:section [address] [(type)] : [AT(lma)]{output-section-commandoutput-section-command...} [>region] [AT>lma_region] [:phdr :phdr ...] [=fillexp]很多附加选项是用不到的。
/s/blog_48aa915f0100b69p.htmlATPCS寄存器的使用规则:寄存器R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15ATPCS名称 a1 a2 a3 a4 v1 v2 v3 v4WRv5 v6SBv7SLv8FPIP SP LR PC1.子程序间通过寄存器R0~R3来传递参数。
被调用的子程序在返回前无须恢复寄存器R0~R3的内容。
2.在子程序中,使用寄存器R4~R11来保存局部变量。
这时,寄存器R4~R11可以记为v1~v8。
如果在子程序中使用了寄存器v1~v8中的某些寄存器,则子程序进入时必须保存这些寄存器的值,在返回前必须恢复这些寄存器的值。
在Thumb程序中,通常只能使用寄存器R4~R7来保存局部变量。
另外R9,R10和R11还有一个特殊作用,分别记为:静态基址寄存器SB,数据栈限制指针SL和桢指针FP。
3.寄存器R12用做过程调用中间临时寄存器IP。
寄存器R13用做堆栈指针SP。
在子程序中寄存器R13不能用做其它用途。
寄存器SP在进入子程序时的值和退出子程序的值必须相等。
寄存器R14称为链接寄存器LR,它用于保存子程序的返回地址。
如果在子程序中保存了返回地址,寄存器R14则可以用做其他用途。
寄存器R15为程序计数器PC,不能用做其他用途。
4.只有寄存器R0~R7,SP,LR和PC可以在Thumb状态下使用,其中R7常常作为Thumb 状态的工作寄存器,记为WR。
数据栈使用规则:1.满降序栈(FD),且8字节对齐。
关于PCS与ATPCS的一点介绍2008-09-01 22:21:50本文来自网络,我稍作了一点编辑。
如果读者使用的是ADS1.2编译器,那么ATPCS.pdf文档就在X:\ProgramFiles\ARM\ADSv1_2\PDF\specs目录里面。
(X:\指的是ADS1.2编译器所在的安装盘)什么是PCS,什么是ATPCS?PCS即Procedure Call Standard(过程调用规范),ATPCS即ARM-THUMB procedure call standard。
arm 位置无关指令实现原理Arm position-independent instruction is a concept that refers to a set of instructions that can be executed on an arm without the need to specify the exact position of the arm in space. This is an important feature in robotics, as it allows for more flexible and adaptable control of robotic arms in various applications.Arm位置无关指令是一个概念,指的是一组指令,可以在机械臂上执行,而无需指定机械臂在空间中的确切位置。
这在机器人技术中是非常重要的,因为它可以更灵活和可适应地控制机械臂在各种应用中。
The implementation of arm position-independent instructions is based on the use of kinematic algorithms and forward and inverse kinematics. These algorithms are used to calculate the position and orientation of the end-effector of the robot arm, without the need for explicit position information. This allows for the generation of motion commands that are independent of the initial position of the arm, making it possible to execute the same set of instructions regardless of the starting position of the arm.Arm位置无关指令的实现基于运动学算法和正向逆向运动学。
ARM下的位置无关和相关码位置无关代码,即该段代码无论放在内存的哪个地址,都能正确运行。
究其原因,是因为代码里没有使用绝对地址,都是相对地址。
而位置相关码,即它的地址与代码处于的位置相关,是绝对地址,如:mov PC ,#0xf f;ldr pc,=0xffff等。
一、位置无关的写法:(1) B指令B指令接受一个相对地址,因此在汇编里用B跳转到一个标号时,实际编译的结果是一个相对跳转。
相对地址有个范围限制,即目标不能太远,一般目标放在同一个文件里是肯定可以的。
Offset must IN 32Mbit_start:b _reset_reset:...(2) BLBL用于调用函数,也是一个相对跳转,same as B instrction(3) ADR获取标号的地址,在编译时会使用PC+偏移的方式得到该位置的地址。
例如,当TEXT_ BASE是0时SMRDATA可能被放在0x100的位置,当TEXT_BASE为0x30000000时放在0x300001 00的位置。
使用ADR总能获取正确的位置,与程序的加载地址无关。
ADR R0, SMRDATASMRDATA:.word 0x22111120.word 0x00002F50.word 0x00000700(相应的, LDR Rn, =LABEL是位置相关的)(4) LDR当加标号时,LDR可以用于伪指令,也可以真指令。
真指令: (标号前不加=号,表示取标号处的值)LDR R0, SDRDATA实际被编译为LDR R0, [PC, #NN],其中NN是目标的相对距离伪指令: (标号前加=号,取标号的地址)LDR R0, = SDRDATA实际编译的时候的时候,会在某位置存处SDRDATA的值,然后用一个LDR取出来。
显然,用LDR时,加不加=号有很大区别。
举例分析例1:中断向量跳转_start:b resetldr pc, _undefined_instructionldr pc, _software_interruptldr pc, _prefetch_abortldr pc, _data_abortldr pc, _not_usedldr pc, _irqldr pc, _fiq_undefined_instruction: .word undefined_instruction_software_interrupt: .word software_interrupt_prefetch_abort: .word prefetch_abort_data_abort: .word data_abort_not_used: .word not_used_irq: .word irq_fiq: .word fiq其中,ldr pc, _irq,由于没加=号,表示取值_irq处的值放在pc里 (位置无关) _irq: .word irq ,表示_irq存放的值是irq的绝对地址(位置有关)例2:bl main ; 位置无关ldr pc, =main; 把main的地址放在pc,位置相关例3: 静态变量_MAGIC_NUM:.word 0x12345678取值LDR R0, _MAGIC_NUM ; 位置无关例4: 存放标号绝对地址(绝对地址是编译的时候已经固定)_OS_Running_p:.word OS_Runing则_OS_Running_p存放的是标号OS_Running的绝对地址例5: 显式LDR和隐式LDR以给某C中的变量的g_num赋值为例(1) 使用伪指令LDR,即为隐式LDR R0, =g_num @取g_num的地址到R0MOV R1, #10STR R1, R0(2) 显式赋值先定义一个变量p_g_num,用于保存g_num的地址p_g_num:.word g_num @ g_num的绝对地址然后赋值LDR R0, p_g_numMOV R1, #10STR R1, R0显然,两者其实一样,伪指令被展开后其实就是(2)的样子。
ADS1.2集成开发环境使用手记一、概括ARM ADS的全称为ARM Developer Suite,它是ARM公司推出的新一代ARM集成开发环境,我们使用的ADS为1.2版本,它取代了早期的ADS1.1和ADS1.0,它可以安装在WindowsNT/2000/98/95/XP上面使用。
这个教程的主要目的,是让大家掌握ADS1.2开发的基本流程,不涉及代码讲解。
开发ARM,首先得会编写源码并且编译。
万事开头难,我们先不管具体细节,先拿现成的代码熟悉一遍开发环境,再慢慢修改代码去!二、软件环境PC:-Windows XP/VISTA(我是在VISTA下的做,大家笔记本是VISTA系统的不要担心兼容性)集成环境:-ADS1.2(下载地址:/MCU123_temp_0080309@/ARM/ads1.2.rar)三、正文本节通过一个简单的具体实例,介绍如何使用ADS集成开发环境。
包括如何创建一个新的工程,如何配置编译选项,并编译生成可以直接烧写到Flash中的bin格式二进制可执行文件和用于JLINK仿真调试的axf文件。
1.建立一个工程在ADS集成开发环境中,点File->New,打开如图所示窗口:--ARM技术交流网 --ARM 技术交流网可以看到有7种工程类型可以选择:ARM Excuteable Image :用于由ARM 指令的代码生成一个ELF 格式的可以执行映象文件。
ARM Object Library :用于由ARM 指令的代码生成一个armar 格式的目标文件库。
Empty Project :用于创建一个不包含任何库或者源文件的工程。
Makefile Importer Wizard :用于将Visual C 的nmake 或者GNU make 文件转入到CodeWarrior IDE 工程文件。
Thumb ARM Excutable Image :用于由ARM 指令和Thumb 指令的混和代码生成一个可执行的ELF 格式的映象文件。
arm的汇编标准
ARM的汇编语言规范如下:
1. 汇编语句格式:在ARM汇编中,所有标号必须在一行的顶格书写,其后面不要添加“:”,而所有指令均不能顶格书写。
2. 标识符大小写:ARM汇编器对标识符大小写敏感,书写标号及指令时字
母大小写要一致,一个ARM指令、伪指令、寄存器名可以全部为大写字母,也可以全部为小写字母,但不要大小写混合使用。
3. 注释:注释使用“;”,注释内容由“;”开始到此行结束,注释可以在一行的顶格书写。
4. 格式:格式为[标号] <指令条件S> <操作数>[;注释]。
5. 空行和换行:源程序中允许有空行,适当地插入空行可以提高源代码的可读性。
如果单行太长,可以使用字符“”将其分行,“”后不能有任何字符,包括空格和制表符等。
6. 变量和常量:对于变量的设置,常量的定义,其标识符必须在一行的顶格书写。
以上就是ARM汇编的一些规范,供您参考。
如果需要更多信息,建议查阅相关书籍或咨询专业人士。
Arm 汇编位置无关代码adr 指令adr r0,_start 得到的是_start 的当前执行位置,由pc+offset 决定的得到有效地址ldr r0,=_start 得到的是绝对的地址,链接时决定;------------------------------------------------------------------------/* 重定位Boot 代码到RAM 内存,将Boot 代码从FLASH 移到RAM 中*/relocate: /* relocate U-Boot to RAM */adr r0,_start /* r0 :* c008000: e59f000c ldr r0, [pc, #12] ; c008014 * c008004: e28f0008 add r0, pc, #8 ; 0x8* c008008: e59f0008 ldr r0, [pc, #8] ; c008018 * c00800c: e1a00000 nop (mov r0,r0)* c008010: e1a0f00e mov pc, lr** 0c008014 :* c008014: e1a00000 nop (mov r0,r0)** 分析:* ldr r0, _start* 从内存地址_start 的地方把值读入。
执行这个后,r0 = 0xe1a00000** adr r0, _start* 取得_start 的地址到r0,但是请看反编译的结果,它是与位置无关的。
其实取得的是相对的位置。
例如这段代码在0x0c008000 运行,* 那么adr r0, _start 得到r0 =0x0c008014;如果在地址0 运行,就是0x00000014 了。
即当前PC 值加上_start 的偏移量。
** ldr r0, =_start* 这个取得标号_start 的绝对地址。
这个绝对地址是在link 的时候确定的。
ARM的位置无关程序设计在Bootloader中的应用
黄振华;李外云;刘锦高
【期刊名称】《单片机与嵌入式系统应用》
【年(卷),期】2008(000)001
【摘要】ARM处理器支持位置无关的程序设计,这种程序加载到存储器的任意地址空间都可以正常运行,其设计方法在嵌入式应用系统开发中具有重要的作用.本文首先介绍位置无关代码的基本概念和实现原理,然后阐述基于ARM汇编位置无关的程序设计方法和实现过程,最后以嵌入式Bootloader程序设计为例,介绍位置无关程序设计在Bootloader程序设计中的作用.
【总页数】4页(P22-25)
【作者】黄振华;李外云;刘锦高
【作者单位】华东师范大学;华东师范大学;华东师范大学
【正文语种】中文
【中图分类】TP3
【相关文献】
1.ARM+DSP嵌入式系统BootLoader在LTE中的实现 [J], 陈发堂;郭丽强
2.Bootloader中MMC驱动程序设计与实现 [J], 沈祺;张哲;胡晨
3.ARM核微处理器 Bootloader的分析与应用 [J], 齐欣;张家栋;霍凯
4.离线加密编程器中的 BootLoader程序设计 [J], 綦声波;马秀明
5.基于ARM9-LINUX掌上电脑样机系统中Bootloader的设计与实现 [J], 王敬晓;陈良益
因版权原因,仅展示原文概要,查看原文内容请购买。
arm汇编语言程序设计ARM汇编语言程序设计一、引言ARM汇编语言是一种低级语言,用于编写底层程序,如操作系统、嵌入式系统等。
它具有高效、灵活、可移植等特点,被广泛应用于各种嵌入式设备中。
本文将介绍ARM汇编语言程序设计的基本概念、语法规则以及常用指令,以帮助读者快速入门和理解该领域的知识。
二、基本概念1. 寄存器:ARM处理器具有16个通用寄存器,分别用R0~R15表示。
这些寄存器用于存储数据、地址和中间结果,并且在程序执行过程中可以被读取和写入。
2. 指令:ARM汇编语言的指令包括数据处理指令、分支指令、加载存储指令等。
这些指令用于执行各种操作,如算术运算、逻辑运算、条件判断等。
3. 标志位:ARM处理器的标志位用于记录执行过程中的状态信息,如进位标志、溢出标志等。
这些标志位对于程序的正确执行非常重要。
三、语法规则1. 指令格式:ARM汇编指令由操作码和操作数组成,其中操作码表示指令的类型,操作数表示指令的操作对象。
指令格式一般为“操作码操作数1, 操作数2, ...”。
2. 注释:注释以分号开头,用于对指令进行解释和说明。
注释对于程序的可读性和维护性非常重要,应当充分利用。
3. 标签:标签用于标识程序中的某个位置或标记某个指令,以便在其他地方进行引用。
标签一般以英文字母开头,后面可以跟随数字或下划线等字符。
4. 伪指令:伪指令是一种特殊指令,用于约定程序的起始地址、存储空间的分配等。
伪指令一般以句点开头,如“.data”表示数据段,“.text”表示代码段。
四、常用指令1. 数据处理指令:数据处理指令用于进行算术运算、逻辑运算等操作。
例如,“ADD”指令用于将两个操作数相加,并将结果存放在目标寄存器中。
2. 分支指令:分支指令用于实现程序的跳转和循环等控制流程。
例如,“B”指令用于无条件跳转到指定标签处执行。
3. 加载存储指令:加载存储指令用于实现数据的读取和写入。
例如,“LDR”指令用于将指定地址处的数据加载到寄存器中。
ARM 当中一种位置无关代码的分析
PIC 是一种在ARM 当中的位置无关码。
位置无关码的意义,是代码放在存储器的无论哪个位置中都能使得程序正常执行,位置无关代码的相对地址
没有变化,就不会影响程序的运行。
在ARM 中,PIC 就是这样一种位置无关代码。
本文就将针对PIC 进行分析,帮助刚入门的朋友进行深入了解。
PIC 的特点
它被加载到任意地址空间都可以正确的执行。
其原理是PIC 对常量和函数入口地址的操作都是基于PC+偏移量的寻址方式。
即使程序被移动,但是PC 也变化了,而偏移量是不变的,所以程序仍然可以找到正确的入口地址或者
常量。
加载域:是代码存放的地址。
运行域:是代码运行时的地址。
链接地址:运行时,程序应该位于的地址。
在一些场合,一些代码并不在储存这部分代码的地址上执行,比如说,放
在norflash 中的代码可能最终是放在RAM 中运行,那幺在norflash 中的地址就是加载域,而在RAM 中的地址就是运行域。
在汇编代码中开发者常常会看到一些跳转指令,比如说b、bl(是位置无关的指令)等这些指令后面是一个相对地址而不是绝对地址,比如说bmain,
这个指令应该怎幺理解?main 这里究竟是一个什幺东西?
这时候就需要涉及到链接地址的概念了,链接地址实际上就是链接器对代
码中的变量名、函数名等东西进行一个地址的编排,赋予这些抽象的东西一
个地址,然后在程序中访问这些变量名、函数名就是在访问一些地址。
一般
所说的链接地址都是指链接这些代码的起始地址,代码必须放在这个地址开。
ARM的32位指令格式及各部分功能一、ARM的32位指令格式ARM的32位指令格式分为四部分,包括指令操作码、条件码、寄存器和操作数。
1. 指令操作码指令操作码是指令的基本操作类型,为了方便指令的译码和执行,ARM指令集将指令操作码分为几类,包括数据处理指令、分支指令、访存指令等。
不同的指令操作码代表了不同的操作类型,如加法、乘法、移位、与操作等。
2. 条件码条件码用于指定指令在何种条件下执行,如等于零、不等于零、大于、小于等。
通过条件码的设置,可以实现根据不同条件来执行不同的指令,这样可以提高指令的灵活性和效率。
3. 寄存器ARM的32位指令格式中包括多个寄存器字段,用于指定指令的操作对象和操作结果的存放位置。
ARM架构中一般有16个通用寄存器和几个特殊用途的寄存器,不同的寄存器字段代表了不同的寄存器编号。
4. 操作数操作数是指令的操作对象,ARM的32位指令中包括多个操作数字段,用于指定指令的源操作数和目的操作数。
操作数可以是寄存器、立即数或内存位置区域等。
二、各部分功能1. 指令操作码的功能指令操作码代表了指令的操作类型,不同的指令操作码对应了不同的操作,比如数据处理指令可以进行加法、减法、逻辑运算等操作,分支指令可以实现程序的跳转,访存指令可以进行内存的读写操作。
2. 条件码的功能条件码用于指定指令的执行条件,通过设置条件码可以实现根据不同条件来执行不同的指令,这样可以提高程序的执行效率和灵活性。
3. 寄存器的功能寄存器用于存放指令的操作对象和操作结果,ARM的32位指令中包括多个寄存器字段,用于指定指令的源操作数和目的操作数。
寄存器的功能包括存储数据、临时存储和传递参数等。
4. 操作数的功能操作数是指令的操作对象,ARM的32位指令中包括多个操作数字段,用于指定指令的源操作数和目的操作数。
操作数的功能包括指定操作对象、传递参数和存储数据等。
结论ARM的32位指令格式包括指令操作码、条件码、寄存器和操作数四部分,各部分都有特定的功能,通过它们的组合可以实现丰富多样的指令操作和灵活的程序控制。
位置无关可执行文件PIE包括位置无关代码PIC和位置无关数据PID两部分。
通常情况下,将bootloader程序下载到ROM的0x0地址进行启动(比如固化到NorFlash 中)。
然而在很多的设计中,比如将bootloader固化在NAND中,在系统复位后S3C2440A 中NAND控制器自动读取NAND中存储的前4K的代码到s3c2440a中称之为steppingstone的RAM中,steppingstone中的代码用进行一些非核心的硬件初始化,再将NAND中剩下的bootloader代码拷贝到RAM中运行。
一般境况下两者的地址并不相同,程序在SDRAM中的地址重定位过程必须由程序员来完成。
这样就有了位置无关代码的概念,指代码不在连接时制定的运行地址空间,也可以执行,它一段加载到任意地址空间都能执行的特殊代码。
这样在steppingstone设计的代码要用位置无关设计。
位置无关代码可以用于以下场合:
1. 程序在运行期间动态加载到内存;
2. 程序在不同场合与不同程序组合后加载到内存(共享的动态链接库);
3. 在运行期间不同地址相互之间的映射(如bootloader)
ARM位置无关程序设计要点
PID 主要针对可读写数据段(.data 段),其中保存已赋初值的全局变量。
为实现其位置无关性,通常使用寄存器R9作为静态基址寄存器,使其指向该可读写段的首地址,并使用相对于基址寄存器的偏移量来对该段的变量进行寻址。
这种方法常用于为可重入程序的多个实例产生多个独立的数据段。
在程序设计中,一般不必考虑可读写段的位置无关性,这主要是因为可读写数据主要分配在SDRAM 中。
PIC包括程序中的代码和只读数据(.text段),为了保证程序能在ROM和SDRAM空间中能真确的运行,必须采用位置无关代码程序设计。
PIC 遵循只读段位置无关
ROPI(Read-Only PositionIndependence)的ATPCS(ARM2Thumb Procedure Call Standard)的程序设计规范:
1. 程序设计规范
引用同一ROPI 段或相对位置固定的另一ROPI 段中的符号时,必须是基于PC 的符号引用,即使用相对于当前PC 的偏移量来实现跳转或进行常量访问。
位置无关的程序跳转。
在ARM 汇编程序中,使用相对跳转指令B/BL 实现程序跳转。
指令中所跳转的目标地址用基于当前PC 的偏移量来表示,与链接时分配给地址标号的绝对地址值无关,因而代码可以在任何位置进行跳转,实现位置无关性。
另外,还可使用ADR 或ADRL 伪指令将地址标号值读取到PC 中实现程序跳转。
这是因为ADR或ADRL等伪指令会被编译器替换为对基于PC 的地址值进行操作,但这种方式所能读取的地址范围较小,并且会因地址值是否为字对齐而异。
但在ARM 程序中,使用LDR 等指令直接将地址标号值读取到PC 中实现程序跳转不是位置无关的。
例如:
可见, 虽然LDR 是把基于PC 的一个存储单元LPOOL 的内容加载到PC 中,但该存储单元中保存的却是链接时所决定的main 函数入口的绝对地址,所以main函数实际所在的段不是位置无关。
位置无关常量访问
在应用程序中,经常要读写相关寄存器以完成必要的硬件初始化。
为增强程序的可读性,利用EQU 伪指令对一些常量进行赋值,但在访问过程中, 必须实现位置无关性。
下面以U-boot 的
SDRAM初始化介绍位置无关的常量访问方法。
由此可以得出如下结论:
使用LDR 伪指令将一个常量读取到非PC 的其他通用寄存器中可实现位置无关的常量访问;但将一个地址值读取到PC 中进行程序跳转时,跳转目标则是位置相关的。
其他被ROPI 段中的代码引用的必须是绝对地址,或者是基于可读写位置无关( RWPI) 段的静态基址寄存器的可写数据。
使用绝对地址只能引用被重定位到特定位置的代码段中的符号,通过在位置无关代码中引入绝对地址,可以让程序跳转到指定位置。
例如,假设Bootloader 的阶段1将其自身代码拷贝到链接时所指定的SDRAM 地址空间后,当要跳转到阶段2 的C 程序入口时,可以使用指令“LDR PC, = main”跳转到程序在SDRAM 中的main 函数入口地址开始执行。
这是因为程序在编译链接时给main 函数分派绝对地址,系统通过将main 函数的绝对地址直接赋给PC 实现程序跳转。
如果使用相对跳转指令“B main”,那么只会跳转到启动ROM 内部的main 函数入口。
bootloadr、内核等程序刚开始执行的时候,他们所处的地址通常不等于运行地址。
在程序的开头,先使用b、bl、mov等“位置无关”的指令将代码从flash等设备中复制到内存的“运行地址”处,然后再跳到“运行地址”去执行。
U-Boot位置无关分析举例来自100ask,我做了以下修改
当映像文件在nor flash中时,adr r0, _start 就想当于sub r0, pc, #offset,假设_start 在映像文件的0位置出,nor flash地址从0开始,那么这时r0中的值就是0。
当映像文件被加载到RAM后,adr r0, _start 还是相当于sub r0, pc, #offset,但这里的pc值已经是基于RAM加载地址的了。
所以结果r0中的值就是0x33f80000,等于
_TEXT_BASE。
判断这两个值是否相等,就可以确定映像是否已经加载到内存中了。
u-boot的连接地址是0x33f80000,意味着它“最后”将被复制到0x33f80000的内存中。
但是“刚开始时”肯定不在内存中,而是在NOR FLASH中──而NOR FLASH的起始地址是0。
为什么本应该在0x33f80000运行的指令,在0地址也可以运行?
答:u-boot中第一个执行的文件是start.S,它都是使用b、bl等等指令写成的,它们是“位置无关的”,就是说它们可以在任何位置运行,而不是非要在“0x33f80000那段地址”运行。
start.S完成什么功能呢?初始化、复制代码到SDRAM,然后跳到SDRAM去运行。
上面的NorFlash你可以理解成S3C2440A中的steppingstone。