实验引导:
在main函数中引入全局变量a时,若将连接后的文件烧写在nand flash上,则可以访问修改全局变量a,若将连接后的文件烧写在nor flash上,则只可访问a,不能修改a。这是由于烧写在nand flash 上的代码会被加载到4K的片内内存SRAM上,全局变量a放在内存里是可读可写的;但将代码烧写在nor flash上时,cpu可以直接通过内存控制器来访问nor flash,然而全局变量在nor flash中是不可修改的,因此需要重定位代码,即将全局变量a,或者是整段代码重定位到SDRAM中,这样就能读写全局变量了。
概念梳理:
加载地址:指二进制.bin文件烧写时的地址,默认从零地址开始
运行时地址:指程序在真正运行时的地址
绝对跳转:在代码进行跳转时采用的是绝对地址,访问全局变量时采用绝对跳转
相对跳转:在代码进行跳转时采用的是相对地址,即汇编中的B/BL命令跳转
重定位步骤:1.指定代码的运行地址 2 将代码从加载地址复制到运行时地址。若采用将全部代码重定位,则在跳转到main时,需要使用绝对跳转(ldr pc,=main)才能使程序运行在SDRAM中,否则代码还是运行在加载地址。
注意点:在复制代码时,如果是以byte为单位复制并且以byte为单位读数据,则无需考虑字节对齐;但若是以4*byte为单位,则需注意字节对齐,否则有可能导致数据被破坏。
段分类说明:
.text :代码段
.data:数据段,存放已经初始化了的全局变量
.rodata:只读数据段,存放静态常量(const修饰)
.bss:存放未初始化或者初始化为0的全局变量
.初始化.bss段:
.bss段并不会被程序自动初始化,因此不会在内存中有.bss段,需要人为地添加.bss段,并且对其初始化为0。
链接脚本:
重定位运行时地址和加载地址的指定,是通过链接脚本实现的。以下代码为例子:
SECTIONS
{
. = 0x30000000;
. = ALIGN(4);
.text :
{
*(.text)
}
. = ALIGN(4);
.rodata : { *(.rodata) }
. = ALIGN(4);
.data : { *(.data) }
. = ALIGN(4);
__bss_start = .;
.bss : { *(.bss) *(.COMMON) }
_end = .;
}
知识点补充
:链接脚本在被编译时会产生符号表,里面存储了定义的各个标签极其位置的信息,在使用c语言进行编程时,将标签用extern声明为外部引用,然后进行取地址就能得到该地址了。
说明:本笔记只用于笔者个人总结知识点,指导意义有限,若有同样学习了韦老师视屏的同学,欢迎相互交流。
『本文转载自网络,版权归原作者所有,如有侵权请联系删除』