首先决定看 ARM 模板的启动文件,光这个启动文件就不简单啊,因为 ARM 汇编不了解,看见一个汇编词都是翻阅手册,不懂的就上网或者看书查找,争取明了。
首先就是启动代码的作用,它包含了异常向量入口,还有初始化了堆栈。启动代码的开始时定义了一些堆栈的大小。
至于大小为什么这么设定,暂时还不知道。接着是一些 ARM 模式的定义
然后是一些启动文件中需要用到的外部声明有外部文件需要用到的启动文件中的标号声明。
IMPORT
此伪指令指示编译器当前的符号不是在本源文件中定义的,而是其他源文件中定义的,在本源文件中可能引用该符号。
EXPORT
声明一个符号可以被其他文件中引用,相当于声明了一个全局变量。
接下来就是 ARM 首先执行的代码了.
C ODE32 伪指令指示汇编编译器后面的指令为 32 位的 ARM 指令。
AREA 伪指令用于定义一个代码段和数据段。这是因为 ARM 汇编程序设计采用分段式设计,一个 ARM 源程序至少需要一个代码段,大的程序可以包含多个代码段及数据段。
CODE 和 READONLY 表明下面的为代码段且只读。
LDR 为大范围的地址读取伪指令。LDR 伪指令用于加载 32 位的立即数或一个地址值到指定寄存器。
DCD 用于分配一段字内存单元,并用伪指令中的 expr 初始化。DCD 伪指令分配的内存需要字对齐,一般可用来定义数据表格或其他常数。
看完上面的代码后,我有几个疑问。
疑问 1:既然是加载异常地址到 PC,为什么不一下就把地址值赋给 PC,而非要先 LDR 后 DCD 呢。
搜索资料后得出答案:
因为 LDR 指令只能跳转到当前 PC 4KB 范围内,而 B 指令能跳转到 32M 范围,像上面所写 LDR PC,"XXXX" 这条指令不远处用 “XXXX” DCD 定义一个字,而这个字里存放最终异常服务程序的地址,这样可以实现 4GB 范围跳转。而 LDR 伪指令通过设置指令缓冲池才能实现全范围跳转。
疑问 2:
这句话突然出现在这里是什么意思?
答案:是为了让异常响亮跳转那 8 句机器码和为 0. 为什么这样,暂时不知道。
接下来是一些异常的处理
未定义指令,取指令中止与取数据中止的处理都只是一个重复的跳转。
接着是初始化堆栈,这是 MCU 复位后首先进行的工作。
接着是复位初始化所做的工作,其中有个工作就是上面刚刚那段代码叙述的那样。
接着是库函数初始化堆和栈,不能删除。不清楚这个是什么。
接着是整数除法除数为 0 错误处理代码。上次有个同学就是因为程序中有运算表达式中除数为 0,所以执行了下面的语句。
接着是一些跟堆栈有关的东西,暂时不清楚是作用
然后是一个芯片加密的处理,也是暂时不知道是怎么进行加密处理的。
最后是分配堆栈空间,启动文件结束。
原作者:Suagr