快捷搜索:

GUN ARM汇编中标号的引用在汇编和C语言中区别

GUN ARM汇编中标号的引用在汇编和C语言中区别

汇编语言中标号表示的是地址,但是C中要取得该标号处的数据,却是直接使用该标号,不是应该对该地址进行取值运算(*指针地址)吗?其实不是的。

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

您可能还会对下面的文章感兴趣: