首页 > 编程语言 >关于链接脚本和汇编导致的数据段初始化错误的问题

关于链接脚本和汇编导致的数据段初始化错误的问题

时间:2024-04-13 14:55:55浏览次数:25  
标签:初始化 ram 汇编 flash 地址 lma srodata data 链接



链接脚本分别如下:

  • 有错误的类型
MEMORY
{
  flash (rxai!w) : ORIGIN = 0x20000000, LENGTH = 256k
  ram   (wxa!ri) : ORIGIN = 0x20040000, LENGTH = 384k   
}

  .lalign         :
  {
    . = ALIGN(4);
    PROVIDE( _data_lma = . );
  } > flash

  .dalign         :
  {
    . = ALIGN(4);
    PROVIDE( _data = . );
  } > ram 

  .data          :
  {
    *(.data .data.*)
    *(.gnu.linkonce.d.*)
    . = ALIGN(8);
    PROVIDE( __global_pointer$ = . + 0x800 );
    *(.sdata .sdata.*)
    *(.gnu.linkonce.s.*)
    . = ALIGN(8);
    *(.srodata.cst16)
    *(.srodata.cst8)
    *(.srodata.cst4)
    *(.srodata.cst2)
    *(.srodata .srodata.*)
  } > ram 
  • 没有错误的类型
  .lalign         :
  {
    . = ALIGN(4);
    PROVIDE( _data_lma = . );
  } >rom AT>flash :flash

  .dalign         :
  {
    . = ALIGN(4);
    PROVIDE( _data = . );
  } >ram AT>flash :ram_init

  .data          :
  {
    *(.data .data.*)
    *(.gnu.linkonce.d.*)
    . = ALIGN(8);
    PROVIDE( __global_pointer$ = . + 0x800 );
    *(.sdata .sdata.*)
    *(.gnu.linkonce.s.*)
    . = ALIGN(8);
    *(.srodata.cst16)
    *(.srodata.cst8)
    *(.srodata.cst4)
    *(.srodata.cst2)
    *(.srodata .srodata.*)
  } >ram AT>flash :ram_init
  • 汇编语言搬运data段的操作
	la a0, _data_lma
	la a1, _data
	la a2, _edata
	bgeu a1, a2, 2f
1:
	lw t0, (a0)
	sw t0, (a1)
	addi a0, a0, 4
	addi a1, a1, 4
	bltu a1, a2, 1b
2:

分析如下:

  • 原来存在的问题和分析思路

    • 问题:上诉所说第一个链接脚本存在data 段初始化失败的问题,第二个link 脚本增加了At>flash就可以正常的运行了,是为什么?如果只是链接错误的话,那么汇编从ram 向同地址的ram 中搬运为什么就会运行出错?
    • 解决思路:
        1. 确认链接器会把data 段的数据放在哪里?
        2. 真正代码跑起来的时候,mcu 会去哪里取代码?这个是由谁决定的?连接器还是编译器?
        3. 目前问题的逻辑解释
      • 对于问题1:一般情况下不加AT 属性就会编译在哪个内存空间,就存放在哪个内存空间。
      • 对于问题2:真正代码跑起来的时候,mcu 会去ram 中取data段,这个是由连接器决定的(连接器会 为每个符号分配地址?),因为两个lds 文件都是把data 段放在了ram 的区域。
      • 原因解释,对应这个问题,有以下几点
          1. 符号的定义,结合上面的lds 源码,_data_lma 永远在 flash地址,_data永远在ram地址
          2. 汇编代码:结合汇编,永远是从_data_lma 搬运 到data 地址处
          3. 链接脚本:第一种错误的链接脚本,没有加At>flash,data 段存放和使用地址都在 ram区域(data 地址开始),这个时候汇编代码还将_data_lma_ 的数据搬运到 data 处就会导致将错误的数据覆盖了正确的数据。
          4. 第二种正确的链接脚本,加个At>flash,data 段存放地址在_data_lma_ 开始的地址和使用地址在_data_开始的地址,这个时候利用汇编代码将_data_lma_ 的数据搬运到 data 处,就是将数据搬运到了改在的位置,程序能正常运行。
  • 对于符号的数值定义很重要

    MEMORY
    {
      flash (rxai!w) : ORIGIN = 0x20000000, LENGTH = 256k
      ram   (wxa!ri) : ORIGIN = 0x20040000, LENGTH = 384k   
    }
    
      .lalign         :
      {
        . = ALIGN(4);
        PROVIDE( _data_lma = . ); /* 这里的_data_lma  可以看到就是flash 中的地址 */
      } > flash
    
      .dalign         :
      {
        . = ALIGN(4);
        PROVIDE( _data = . ); /*  这里的 _data 地址是ram中的地址*/
      } > ram 
    
  • 由于链接的时候选择了将.data 段编译到了ram 中,所以实际的时候取数会去ram的地址取值。

      .data          :
      {
    	、、、、、、
      } >ram
    
待后续补充
  • 用readelf 查看两种编译方式编译出来的section的区别

标签:初始化,ram,汇编,flash,地址,lma,srodata,data,链接
From: https://www.cnblogs.com/satellite98/p/18132849

相关文章

  • windows下的重装是最笨也是最简单的重复解决问题的方法,解决goldendict的qt库链接问题
    goldendict✔goldendict:symbollookuperror:goldendict:undefinedsymbol:_ZN10QAudioSink12stateChangedEN6QAudio5StateE,versionQt_6~yay-Sgoldendict......
  • 汇编语言简易教程(10):宏
    汇编语言简易教程(10):宏汇编语言宏是一组预定义的指令,可以轻松插入到需要的地方。一旦定义,宏可以根据需要多次使用。当必须多次使用同一组代码时,它非常有用。宏可用于减少编码量、简化程序并减少重复编码带来的错误.汇编器包含一个强大的宏处理器,支持条件汇编、多级文件包含......
  • 汇编语言简易教程(11):函数与栈帧
    汇编语言简易教程(11):函数与栈帧需要注意.这里的函数指的是汇编语言(yasm)的函数,但对理解其他高级语言的函数在汇编中的实现会有很大的帮助.函数和过程(即空函数)有助于将程序分解为更小的部分,从而更容易编码、调试和维护。函数调用涉及两个主要操作:函数链接由于可以......
  • C 语言宏 + 内联汇编实现 MIPS 系统调用
    目录内联汇编宏函数宏定义Syscall内联汇编编译测试笔者最近作业要求练习MIPS汇编,熟悉MIPS汇编代码与C语言代码的对应关系。然而SPIM/MARS仿真器不能链接共享库以调用外部函数(如stdio.h下的函数),只能通过系统调用实现。C语言可以通过内联汇编(InlineAssembly)实现系统......
  • 区块链接交易系统搭建|合约交易系统软件开发
    在区块链上交换的好处在于交易所并不持有使用者大量的加密货币,所有的加密货币会储存在区块链上使用者的钱包或智能合约控管。本来需要信任中心化的交易所,现在仅需要信任区块链以及智能合约即可。而用于交易所的智能合约大多会公开源码让所有人可以确认这份合约的细节。区块链交易......
  • 汇编语言简易教程(8):寻址模式
    汇编语言简易教程(8):寻址模式寻址模式是使用正在访问(读取或写入)的数据项的地址来访问内存中的值的受支持方法。这可能包括变量的名称或数组中的位置。基本的寻址模式包含:寄存器立即数内存寻址注意事项使用[]需要注意:访问内存的唯一方法是使用方括号([]'s)。省略括号......
  • 汇编语言简易教程(9):程序栈
    汇编语言简易教程(9):程序栈在计算机中,栈是一种数据结构,其中项目以相反的顺序添加,然后从栈中删除。也就是说,最近添加的项目是第一个被删除的项目。这通常称为后进先出(LIFO).堆栈在编程中大量使用,用于在过程函数调用期间存储信息。下一章提供有关堆栈的信息和示例将项目添加......
  • 汇编语言简易教程(8):寻址模式
    汇编语言简易教程(8):寻址模式寻址模式是使用正在访问(读取或写入)的数据项的地址来访问内存中的值的受支持方法。这可能包括变量的名称或数组中的位置。基本的寻址模式包含:寄存器立即数内存寻址注意事项使用[]需要注意:访问内存的唯一方法是使用方括号([]'s)。省略括号......
  • 汇编语言简易教程(9):程序栈
    汇编语言简易教程(9):程序栈在计算机中,栈是一种数据结构,其中项目以相反的顺序添加,然后从栈中删除。也就是说,最近添加的项目是第一个被删除的项目。这通常称为后进先出(LIFO).堆栈在编程中大量使用,用于在过程函数调用期间存储信息。下一章提供有关堆栈的信息和示例将项目添加......
  • 痞子衡嵌入式:使能i.MXRT1050,1060 Hab签名或加密启动时App链接在片内SRAM的限制
    大家好,我是痞子衡,是正经搞技术的痞子。今天痞子衡给大家介绍的是使能i.MXRT1050,1060Hab签名或加密启动时App链接在片内SRAM的限制。最近有客户反馈,在RT1060上测试Non-XIP程序启动,如果程序体部分链接进0x20280000地址之后的片内OCRAM区域(这部分是由FlexRAM......