ARM裸板开发:04_MMU 链接地址与运行地址不一致时,(SDRAM)初始化程序地址无关码问题的分析

ARM裸板开发过程,程序的链接地址设置为为0x30000000,而前期的启动代码以及相关硬件的初始化代码需要在内部iRAM(steppingstone,起始地址0x0)的4K中运行。链接地址与运行地址(程序启动后PC从0x0位置执行)不一致时,不能出现位置相关代码。文中主要针对 SDRAM 初始化程序地址无关码问题进行了简单的分析。
(本文的由来是博主在学习韦东山系列 ARM 裸板开发过程遇到的一个问题所引发的。在虚拟内存(MMU)操作部分,他提到了 SDRAM 初始化过程应该用位置无关的代码实现,方式是直接对SDRAM的寄存器组赋常量值。不过在解释为什么这样实现就是位置无关的过程,并没有给出清晰的解释,带着这样的疑问便有了以下的分析过程。)
 
1、位置相关的初始化过程
下面的初始化过程,由于使用数组存储常量值而产生了位置相关的代码。
               ARM裸板开发:04_MMU 链接地址与运行地址不一致时,(SDRAM)初始化程序地址无关码问题的分析
ARM裸板开发:04_MMU 链接地址与运行地址不一致时,(SDRAM)初始化程序地址无关码问题的分析
对于数组常量初始值的声明unsigned long const mem_cfg_val,不论此处是否有const关键字,数组元素均作为常量存储在常量数据区(两者反汇编代码完全一致)。初始化代码的反汇编如下:
               ARM裸板开发:04_MMU 链接地址与运行地址不一致时,(SDRAM)初始化程序地址无关码问题的分析
ARM裸板开发:04_MMU 链接地址与运行地址不一致时,(SDRAM)初始化程序地址无关码问题的分析
通过分析这部分代码可知,数组中的常数变量的起始地址存储在地址为0x30000100内存中,即300002d0。该地址处的内容如下图示,可见其与上述C代码的数组常量值保持一致。上面大括号处的代码则完成了将这些常量值从常量数据区copy到栈区的过程。这个过程之所以是位置相关的,关键代码在于 ldr    r3, [pc, #136]    ; 30000100 <first+0x100>
ARM裸板开发:04_MMU 链接地址与运行地址不一致时,(SDRAM)初始化程序地址无关码问题的分析
                     ARM裸板开发:04_MMU 链接地址与运行地址不一致时,(SDRAM)初始化程序地址无关码问题的分析
2、位置无关的初始化过程
下面是位置无关的初始化代码。该过程通过直接将初始值写入寄存器的方式,避免了对常量值的单独存储,直接将其融入代码段的二进制指令中。
               ARM裸板开发:04_MMU 链接地址与运行地址不一致时,(SDRAM)初始化程序地址无关码问题的分析
ARM裸板开发:04_MMU 链接地址与运行地址不一致时,(SDRAM)初始化程序地址无关码问题的分析
反汇编之后,如下:
                   ARM裸板开发:04_MMU 链接地址与运行地址不一致时,(SDRAM)初始化程序地址无关码问题的分析
ARM裸板开发:04_MMU 链接地址与运行地址不一致时,(SDRAM)初始化程序地址无关码问题的分析
通过分析可知,该初始化代码主要通过 r0, r1, r2, r3, ip 等5个寄存器来存放初始值并完成写入SDRAM寄存器组的任务。首个初始值的赋值操作,str r1, [r3],即p[0] = 0x22011110;为了将 0x22011110 存入 r1,共使用了3条汇编指令。由于ARM指令长度4字节的限制,不能直接对 r1 赋值为 0x22011110。其他操作与 r1 的过程类似。
整个初始化的过程并未出现对常量初始值在内存区绝对寻址的过程,故该初始化过程是位置无关的。