arm蛋疼汇编part 10--与位置有关代码 与位置无关代码

来源:互联网 发布:兰州广电网络客服电话 编辑:程序博客网 时间:2024/05/16 09:13

makefile:

test.S:

删除线chrome下竟然不能用  只能用框框了  下一个框框是上次错误的分析:

 

这段程序编译链接格式化后  下载到40000000 运行出错  下载到30000000运行正确
原因是我们指定了text段地址为30000000  
我们接着看一下:

 

看看这里:
   c:e59f0018 ldrr0, [pc, #24]; 2c <str+0x8>
   14:e59ff004 ldrpc, [pc, #4]; 20 <show>

删除线chrome下竟然不能用  只能用框框了  下一个框框是上次错误的分析:

以上分析出错了   原因是我开发板先下载程序到30000000  然后又下载到40000000 进行测试  得到一样的正确结果
刚刚仔细看了一下代码  发现自己在忽悠自己  哈哈   睁眼说瞎话了     这里
其实是将2c:   00000024    .word   0x00000024  这个地址所存放的数据读入r0中   所以这是一段与位置有关的代码    虽然pc加偏移与位置无关  但是pc加便宜读取到的数据却是与位置有关的    
而我在测试的时候也犯了低级的错误   开发板没有重新上电    导致内存数据没被改写   uboot下md查看发现两个区域的数据是一样的   这也解释了为了结果正确   
而当我将开发板重新上电  然后直接下载到40000000 的时候  程序执行出错了  没得到预期的结果  哎   
之前的分析就不删除了  虽然有部分错误  但是仍然是值得以后留着提醒自己的

 

ldrr0, [pc, #24]

 

 

 

而我们再看看part8中的代码相反 是一段与位置有关的代码    
我们看看它的反汇编结果:

 

这里:
3000000c:eb000002 bl3000001c <test>
30000010:eb000019 bl3000007c <test2>
这个寻址的方式是立即数寻址,直接跳转到3000****处执行
而30000000是我们在链接的时候指定了text段的地址    elf映像又顺序存储了各个段   当程序执行到这两句指令的时候   如果我们把程序下载到指定的入口点  30000000   则3000001c  3000007c即存储了我们预设的数据   但是如果我们将程序下载到40000000   那么3000001c  3000007c读取到的数据将是一堆垃圾数据  也是不可预期的               这类代码即是与位置有关的代码    也就是说采用绝对地址读取数据的指令就会生成与位置有关的代码 

不用多做对比也明白  与位置有关的代码在实际使用中约束更大   而如果是提供给操作系统调用的话  装载到内存的地址是由操作系统决定的  不能保证  也几乎不可能装载到链接时指定的位置执行    

再来谈谈编写与位置无关代码的注意事项:
1.并不是说哪个指令就是与位置有关或者与位置无关的指令,我们编写的代码经过汇编后  编译器会自动优化   也可能不优化   所以无法从指令使用方面来判定一份代码是否为与位置有关或者无关的代码,那么如果判断呢?   其实只要objdump -d反汇编看看结果  分析一下就有80%的把握了   呵呵  当然这也不是百分百的肯定     最简单最实际的办法  还是调试 实践测试    
2.一般调用c函数的代码都可能是与位置有关的代码    但不是绝对    
3.尽量避免源文件写得太长   如果源文件太长的话   出现与位置有关的代码的可能性也会增加 4.应该注意ldr指令的使用   绝大部分ldr伪指令 可能产生与位置有关的代码   ldr  寄存器,=标签  这种指令尽量用adr代替   因为反汇编后会发现adr伪指令会被汇编成add指令