位置无关代码码与位置相关代码

位置无关代码:就是说和某个具体位置无关,而是根据相对位置取值的代码。

位置相关代码:就是说和某个具体相关,严格按照给定的位置取地址的代码。

一般情况下两边都可以得到正确的地址,但在操作系统内核还没有加载的裸机上可能会出现问题。下面各举一个例子进行讲解。

位置相关代码:我们举LDR 这个指令的例子,LDR就是一个很严格的位置相关的代码。

这个给两行代码:

ldr r0, =0x40000000  
ldr r1, [r0]         

第一行是将0x40000000赋给r0,第二行就是将[0x40000000]这个存储器里面的值付给r1,执行的时候是真的去地址为0x40000000的位置去找,有可能是内存,有可能是某个端口。(这里我们用端口统一编制的方式)。这种使用情况一般是我们写驱动真的要找某个端口的具体地址。(一般地址会在手册里有)

然后是位置无关代码:一般gcc编译出来的都用的是位置无关,我们以b为例,

  b jump

jump:          

我们用b进行跳转的时候是用pc = pc + 偏移量。这个偏移量就是执行b这条语句时的pc值,和标号所代表地址之间的差值,有可能为正,有可能为负。所以这个代码在裸机上也能找到jump这个标号的位置。但是如果是我们用位置相关语句,就会出问题。你想。同样的例子,我用LDR来写。

ldr r0,jump

jump:

在裸机上运行的时候。

ldr拿到的就会是jump在elf文件里的链接地址。(我们最后生成的elf文件里,每个标签都会有一个具体的地址,我们可以用readelf去看,就能大概明白这个地址是多少,这个值应该会放在elf文件的符号表里对应jump这个标号的一栏,同时这个地址是编译器编号了就不会变了)。假设jump的值为0x0ffff4000。但是我们把他装到内存时地址为0x0ffff2000,那执行完后r0的值还会是0x0ffff4000,而我们真正的代码放在0x0ffff2000,就出事了。

但是如果用b指令的话,我们采用的是偏移量的方式,jump的值是多少我一点都不关心(他的值还是0x0ffff4000),我知道调到哪里的偏移量是8(64位机),那么我们执行b jump,实际上跑的是pc= pc + 8。就成功跳转到jump这个函数了。

至于这个偏移gcc是怎么算出来的,我们学过编译原理,大概率是我们看到一条b语言,我们也看到了后边的标志,我们将当前的b语句的pc值记一下,gcc向后面继续扫,扫到这个标志时,让现在的pc值去减我们当时记下的pc,然后把这个差值回填到b语句处。

参考:http://blog.chinaunix.net/uid-22841689-id-3934915.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值