GUN ARM汇编中标号的引用在汇编和C语言中区别(monitor_flash_len = _bss_start - _armboot_start;)

u-boot/cpu/xx/start.S中:

_TEXT_BASE: 
.word TEXT_BASE  /*uboot映像在SDRAM中的重定位地址,我设置为0xa170 0000 */ 

.globl _armboot_start 
_armboot_start: 
.word _start  /*_start是程序入口,链接完毕它的值应该是0xa170 0000=TEXT_BASE*/ 
/* 这句话的意思应该是在_armboot_start标号处,保存了_start的值,也就是说,_armboot_start是存放_start的地址,该地址对应的存储单元内容是0xa170 0000*/ 
/* 
* These are defined in the board-specific linker script. 下面的定义与上面应该是一个意思。 
*/ 
.globl _bss_start 
_bss_start: 
.word __bss_start 
===============================================
在C入口函数start_armboot()中(对应文件为lib_arm/board.c),有如下代码:

void start_armboot (void) 

......... 
gd = (gd_t*)(_armboot_start - CFG_MALLOC_LEN - sizeof(gd_t));  //第一句话 
.......... 
monitor_flash_len = _bss_start - _armboot_start;  //第二句话 
............... 
mem_malloc_init (_armboot_start - CFG_MALLOC_LEN);  //第三句话 
.......... 


在这里,如果混淆了在汇编中和C语言中对汇编标号的引用的区别,就会认为monitor_flash_len=_bss_start - _armboot_start=0xa1700048 - 0xa1700044 = 4
其实
monitor_flash_len = _bss_start - _armboot_start = a171b070 - a1700000 = 1b070

===============================================
下边总结一下,汇编语言和C语言中对汇编中的全局标号的引用的区别:

1018: a1700048 0 NOTYPE GLOBAL DEFAULT 1 _bss_start 
1083: a1700044 0 NOTYPE GLOBAL DEFAULT 1 _armboot_start 
1142: a1700000 0 NOTYPE GLOBAL DEFAULT 1 _start 
1197: a171b070 0 NOTYPE GLOBAL DEFAULT ABS __bss_start 

在汇编中,标号==地址,对标号的引用就是对标号对应的地址操作,如_armboot_start,其值就是a1700044,如果想取得其对应内存地址中的数据,就需要ldr等指令。举个不恰当的例子,如果在汇编语言中也可以有类似x-y的操作的话
monitor_flash_len=_bss_start - _armboot_start=0xa1700048 - 0xa1700044 = 4
这是完全正确的。

然而,在C语言中,其结果却不是这样的。在C中,对汇编中的全局标号的引用,其值不再是地址,而是地址对应内存单元中的数据,所以对于C语言
monitor_flash_len = _bss_start - _armboot_start = a171b070 - a1700000 = 1b070

在C语言中,对基本数据类型变量的引用,其值就是对应内存中的数据,而对于复杂数据类型及函数,其标识符名是指向首地址的指针,其值是它们的首地址。
或许可以这样理解,由于对于基本数据类型来说,其地址和对应内存单元中的数据刚好是一一对应的,对变量的引用目的也是希望对内存中的数据进行操作,所以默认是取得变量对应内存单元中的数据;而对于复杂数据类型及函数来说,利用一个地址取得全部数据是不可能的,所以就用标明首地址的方式,加上地址的线性连续,便可以通过首地址取得全部数据,这是通过对指针(地址)的操作来实现的。

你可能感兴趣的:(C,Programming,Language)