_TEXT_BASE:此处定义一汇编语言标签,更好的理解就是:告诉编译器,为_TEXT_BASE分配存储空间,该空间的名字就叫_TEXT_BASE,该空间中存储的值就是由.word后面确定的TEXT_BASEC(即0x33F80000),相当于C语言中 long _TEXT_BASE=TEXT_BASE; TEXT_BASE定义在board\smdk2410\config.mk文件中。该值的作用是告诉链接器,本程序运行的基地址为TEXT_BASE。U-boot编译后,烧在FLASH的第一个块中,CPU复位上电后,PC寄存器为0x0000。怎么会跑到TEXT_BASE处执行呢?
事实上,CPU上电后,从地址0x0000处执行,而U-BOOT的最起始代码,即本文件中从_start开始的代码是与地址不相关的,这段代码放在任何空间执行的结果都是一样(当然不是绝对,假设u-boot代码段是100K,则放在TEXT_BASE-80K处,搬运时就会把u-boot代码后面20K部分覆盖为最前面的20K)。
.globl _armboot_start
_armboot_start:
.word _start
定义外部可以引用的变量_armboot_start,。即相当于C long _armboot_start=&_start; _armboot_start值是多少?是TEXT_BASE,即0x33F80000!等价的那条C语句,取的是_start变量地址,而不是_start本身。在C语言中,定义一变量 int x=100;就是告诉编译器。给我一个int大小的存储空间,该空间存储的值就是100,这个空间在哪呢?即空间地址是多少呢?我们可以通过&x知道。
在汇编语言中,理解上有点不一样。上面三行语句,
第一句,告诉编译器,向外面输出变量_armboot_start
第二句,_armboot_start变量在此处,到底在哪,要到链接时才能确定,凡正现在知道有这么一个变量了。
第三句,_armboot_start变量空间放的数据为_start标签的值。这点与C语言的理解有点不一样了。此处引用的是_start标签对应处的地址。在汇编语言中,标签代表的就是那行所在的地址。
图1是从u-boot编译后生成的u-boot.map截图的。从此文件中知道,_armboot_start这个变量地址为0x33f80044,
*/
/*
* we do sys-critical inits only at reboot,
* not when booting from ram!
*/
#ifndef CONFIG_SKIP_LOWLEVEL_INIT
bl cpu_init_crit
#endif
/*
下面是重定位代码,即将整个u-boot搬到TEXT_BASE地址处的代码
/*
#ifndef CONFIG_SKIP_RELOCATE_UBOOT
relocate: /* relocate U-Boot to RAM */
adr r0, _start /* r0
ldr r1, _TEXT_BASE /* test if we run from flash or RAM */
cmp r0, r1 /* don't reloc during debug */
beq stack_setup