1. 要不要学习汇编
可以懂一点,工作中基本不用,一旦用就是出了大问题了
ldr : load读内存
ldr r0, [r1] : r1里存放的是地址值,去这个地址读取4字节的内容,存入r0
str : store写内存
str r0, [r1] : r1里存放的是地址值,把r0里的4字节数据存入这个地址
所有的汇编、程序也好,终极目标就是:读写某个地址
2. 程序为何要分为代码段、数据段、BSS段
程序的指令等是只读的,可以把它们归为一类,一遍运行时可以放在ROM等设备上,当然也可以放在内存,只不过这块内存无需写操作
程序的全局变量等,是可读可写,可以把它们归为一类,放在内存里
假设程序里有1百万个初始值为0的全局变量,你最终编译出来的bin文件里要不要存放这1百万个0变量?
肯定不存,怎么办。把它们归为一类,只记录它们的起始地址、结束地址,在程序运行之前,把这一块内存全部清零
3. 栈的作用
3.1 调用C函数之前要设置栈,因为在C函数的开头要保存一些值(比如返回地址),这些值肯定要保存在内存中。这块内存大家约定使用SP寄存器指明位置,这块内存就是栈。
3.2 用来保存局部变量
4. 重定位/连接地址
使用全局变量时,是根据他的地址去读写内存,这个地址跟连接脚本的起始地址密切相关。也可以知道,要想正确访问到全局变量,程序运行之前应该位于它的连接地址上。
4.1 NAND启动时,NAND前4K会被自动复制到片内的SRAM并运行。如果程序超过4k,那么前4K的代码应该把程序完全复制到SDRAM
问:SDARM那么大,应该复制到那个位置呢?
答:复制到它的链接地址处,因为全局变量等是以连接地址来访问的,在程序运行之前,这个地址应该有正确值。
由此也可以得到裸板框架:
a. 必要的硬件初始化:看门狗、时钟、SDRAM
b. 重定位:把程序从FLASH读到SDRAM中它的链接地址处
c. 清楚BSS
d. 调用C函数
5. 位置无关代码
假设程序连接的地址是0x30000000,一上电是从0地址开始执行
问:为何0地址开始的那部分代码可以正确执行?
答:它们是使用位置无关的代码编写的
a. 不访问全局变量/静态变量
b. 跳转时使用相对跳转指令b,bl