zoukankan      html  css  js  c++  java
  • 对链接地址的理解

      当我们写链接器脚本的时候,我们会设置代码段的起始链接地址为0x30008000(S3C2440)。如果对链接地址理解错误的话,可能会出现像我这样的问题。

      Q:gboot的链接器脚本里写的其实链接地址是内存中的0x30008000,再用交叉工具反汇编得到的start.S前几行代码地址都变成了0x30008000+,不太对啊。ARM启动流程里面讲处理器将NAND中的代码复制了4K到垫脚石中,垫脚石的地址是0x0,也正是因为这样,我们设置的异常向量表才有意义,处理器才能准确的找到处理异常的标号。但是把链接地址改成了0x30008000还怎么找?

      A:首先要理解链接地址。我认为,链接地址就是为程序假想了一个起点,之后的代码都是在这个假想的起点基础上展开的。我们只有根据这个链接地址,才能找到后续的一些指令并执行。但是这个链接地址不是实际的指令的地址,我们先对gboot.elf进行反汇编看看

    30008000 <_start>:
    30008000:    ea000014     b    30008058 <reset>
    30008004:    e59ff014     ldr    pc, [pc, #20]    ; 30008020 <_undefined_instruction>
    30008008:    e59ff014     ldr    pc, [pc, #20]    ; 30008024 <_software_intrrupt>
    3000800c:    e59ff014     ldr    pc, [pc, #20]    ; 30008028 <_prefetch_abort>
    30008010:    e59ff014     ldr    pc, [pc, #20]    ; 3000802c <_data_abort>
    30008014:    e59ff014     ldr    pc, [pc, #20]    ; 30008030 <_not_used>
    30008018:    e59ff014     ldr    pc, [pc, #20]    ; 30008034 <_irq>
    3000801c:    e59ff014     ldr    pc, [pc, #20]    ; 30008038 <_fiq>

    用b reset举例,虽然reset标号的地址已经到了0x30008000,但是我们的代码此时实际上是在垫脚石中运行的,也就是说PC指针还是指在0x0的位置。这样0x0和0x30008000就形成了一个映射的关系,即0x4相当于0x30008004,0x8相当于0x30008008......,都是因为我们将链接起始地址设成了0x30008000,这也就是我们所说的相对跳转。

      Q:为什么链接起始地址要写成0x30008000?

      A:照理说这个地址是随意的,只要在S3C2440的寻址空间内都可以。但是后期我们要执行C语言程序,而对堆栈等的初始化都是对SDRAM进行的,即在0x30000000之后的64M空间中。所以为了C语言能够成功运行,直接将代码的链接地址设到内存中,这样方面之后的绝对跳转,即

    ldr pc, =main
  • 相关阅读:
    ORA-1034 ORACLE not available (转)
    关于命名管道
    Linux12.3 exportfs命令
    Linux12.2 NFS配置
    Linux12.1 NFS介绍
    Linux11.4 常用SQL语句、数据库备份恢复
    Linux11.3 MySQL用户管理
    ssh远程连接错误
    Internal Server Error: /api/course/coursesection/
    vue.esm.js?efeb:591 [Vue warn]: Invalid prop: type check failed for prop "data". Expected Array, got String.
  • 原文地址:https://www.cnblogs.com/51qianrushi/p/4644233.html
Copyright © 2011-2022 走看看