在汇编中 使用位置无关码
b,bl
在c语言中 使用位置无关码
不用全局变量 不用静态变量
位置无关码:CPU取指时,总是相对于本条执行指令的相对地址去取指。比如指行一个ADD指令时,PC要取下一指令的地址,就在原来的基础上+4。这就不管你代码放在存储器的任何位置,只要他们的相对地址没有改变,就能正常执行程序。一般上电复位那几条语句就必须是位置无关码指令。 位置相关码:可以这样来说,就是CPU每次取指都从绝对位置去取,而不是上面的相对位置。这个绝对地址就是相对起始地址0来说的。这样,就要求你在存放程序时,必须给连接脚本所规定的一样,把代码放到指定位置
1.A排在第一的位置,B排在第二的位置2.A排在B的前面这两种情况,都说明的A和B的位置关系,而第一种跟位置相关,属于绝对地址;而第二种情况则跟位置无关,属于相对地址。
位置无关与位置相关代码是关于arm程序在跳转时的寻址方式的两种,一般情况下两种方法都能达到跳转到目的地址的目标,但是在某些特定的环境下,两种跳转方法得到的结果相关较大。
位置无关代码的跳转可通过“B或BL 标号”命令执行,当执行B或BL命令实现跳转时,实际的二进制代码在跳转时是执行:计算可执行代码中目标地址到当前PC值处的距离,然后把该距离值加上当前的PC值,然后赋值给PC寄存器实现跳转,该跳转方法由于指令的地址域只有26位,所以它只能向前/向后寻址32M位地址,如果目标地址到当前PC值的距离大于该值时,可使用伪指令“ADR和ADRL PC,=标号地址”实现跳转,实际执行过程是先计算目标址址到当前PC的距离,然后把当前PC值加上距离值赋值到目标寄存器PC中,实现跳转,ADR与B或BL功能类似,但ADRL可以实现全部范围内的跳转,其通过把目标地址与当前PC的距离值存储到一个缓存字中,然后把缓存字中的值加载到寄存器PC中。
位置相关跳转也可以叫绝对位置跳转,一般使用伪指令LDR PC,=label实现跳转到label标号的链接地址中,绝对地址也就是链接地址。这里位置相关及位置无关本质上的区别其实是链接地址与运行地址的区别。
在无操作系统中的裸机代码中,如果链接的偏移基址为0,则绝对位置跳转与相对位置跳转的效果是一样的,而对于一些把可执行代码拷贝到ram中再运行的程序中,链接地址与起始运行地址是不相同的,一般地链接地址是一个ram逻辑地址内的一个数值,而运行地址则是代码烧写的flash等存储器件的逻辑地址,一般是0地址。链接的偏移地址可以通过在编译时通过在链接脚本或Makefile中指定。
在完成可执行代码从flash到ram的拷贝后,通过LDR PC,=label指令跳转到内存中执行程序,而在这之前执行的代码跳转必须是位置无关的,否则会出现跑飞的异常。
B label BL label //位置无关跳转到label
ADR R0,label ADRL R0,=label //获取label到当前程序的偏移距离
ADR PC,label ADRL PC,=label //位置无关跳转到label
LDR PC,=label //位置相关的绝对位置跳转
LDR R0,=label //获取label到当前程序的偏移距离,注意这里不是获取label的(链接地址)绝对地址
LDR R0,=0x500000C0
LDR R1,[R0]
LDR R2,=0x00
STR R2,[R0]
LDR R0,=label加载label数据到寄存器R0中,如果label大于255则把LDR翻译成上述位置无关的伪指令,如果小于255则直接是用LDR指令进行立即数寻址方式
参考:
http://blog.chinaunix.net/uid-10696433-id-2935776.html
http://m.blog.csdn.net/blog/zhaigch/39433601