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汇编的一些规范,供您参考。
如果需要更多信息,建议查阅相关书籍或咨询专业人士。
位置无关可执行文件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。