PS:在u-boot源码时遇到_armboot_start、_bss_start等这些变量,不知道指向什么地址,所以查了一下,弄清了ARM汇编中“.word”这个伪指令是什么意思了,感觉自己很菜。学习一下网友帖子的内容,要害在帖子最终的总结:
汇编和C引证变量的不同:汇编是“肯定”引证,即没有指针的概念,引证得到的便是值;c言语是“直接”引证,相当于指针的概念,引证地址变量,得到的便是该变量所指的内容值。
感谢原作者,以下为原帖:
aaronwong: u-boot中代码的疑问(_armboot_start与_start)?
—————————
我运用的是u-boot-1.3.0-rc2。在cpu/pxa/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的地址,该地址对应的存储单元内容是0xa1700000*/
/*
* These are defined in the board-specific linker script.下面的界说与上面应该是一个意思。
*/
.globl _bss_start
_bss_start:
.word __bss_start
======================
依照上面的了解,__bss_start是uboot的bss段开始地址,那么uboot映像的巨细便是__bss_start- _start;在relocate代码段中核算uboot的巨细时,也表现了这一点。
实际上,_armboot_start并没有实际含义,它仅仅在”ldrr2, _armboot_start”顶用來寻址_start的值罢了,_bss_start也是相同的道理,真实有含义的应该是_start和__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);//第三句话
……….
}
==============================================
依照上面的了解,_armboot_start与_bss_start都是没有实际含义的,它们仅仅一个地址,有实际含义的是地址中的内容_start和__bss_start(尽管也仍是地址)。象榜首句话,其“穷极无聊”很明显,是把gd作为大局数据结构体的指针,并初始化为“SDRAM中的uboot开始地址(即TEXT_BASE)-CFG_MALLOC_LEN-大局数据结构体巨细”。
要完成这个“穷极无聊”,应该是写成:gd= (gd_t*)(_start – CFG_MALLOC_LEN – sizeof(gd_t));或许gd= (gd_t*)(TEXT_BASE- CFG_MALLOC_LEN – sizeof(gd_t));才对阿?用_armboot_start来作运算应该是没有任何含义才对!?
第二句话也是相同的道理,它的穷极无聊是要核算u-boot映像的巨细,应该写成__bss_start- _start才对阿?
我运用readelf东西检查编译所得到的uboot映像文件得到信息如下:
[aaronwong@localhost build]$ readelf -s u-boot|grep _start
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
上面我删除了与该评论无关的包括“_start””t的标号信息。
明显,我前面的了解应该是正确的(_start=TEXT_BASE=0xa1700000)。那么u-boot源代码中的monitor_flash_len=_bss_start -_armboot_start=0xa1700048 – 0xa1700044 = 4,有什么含义??
苍茫中,期盼大虾指点迷津,谢谢~!!!
eltshan: [Re: aaronwong]
—————–
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
我想:
_start地点的地址是a1700000,
_armboot_start 地点的地址是a1700044,
那么 依据这句:
_armboot_start: .word _start
所以_armboot_start的值应该是a1700000
所以
monitor_flash_len = _bss_start – _armboot_start = a171b070 – a1700000 = 1b070
而不是你说的 = 4
以上个人定见.
aaronwong: [Re: eltshan]
——————-
谢谢,eltshan!你的了解是正确的,不过我看了之后仍是没能想得很了解,由于我在想,按你所说,那么_start的值应该是多少呢?莫非是“breset”这条指令的机器码?所以我对ELF格局的u-boot映像文件作了反汇编,剖析之后总算找到了症结地点。以下是部分剖析进程,首先是反汇编:
arm-iwmmxt-linux-gnueabi-objectdump -D u-boot > u-boot.s
并提取了monitor_flash_len = _bss_start – _armboot_start;这条查办相关的反汇编代码如下:
==============================
a1700044 <_armboot_start>:
a1700044: a1700000 .word 0xa1700000
a1700048 <_bss_start>:
a1700048: a171b070 .word 0xa171b070
a171b070
a171b070: 00000000 .word 0x00000000
…..
a1700f40: e59f41d0 ldr r4, [pc, #464] ; a1701118
//r4=[a1701118]=a1700044
…..
a1700f7c: e59f3198ldr r3, [pc, #408] ; a170111c
//r3=[a1700044]=a1700048
a1700f80: e5942000 ldrr2, [r4]
//r2=[a1700044]=a1700000
a1700f84:e59f4194 ldr r4, [pc,#404] ; a1701120
//r4=[a1701120]=a1719d24
a1700f88: e5933000 ldrr3, [r3]
//r3=[a1700048]=a171b070
a1700f8c: e0623003 rsb r3, r2, r3
//r3= r3-r2 = a171b070-a1700000 = 1b070;
a1700f90: e59f218cldr r2, [pc, #396] ; a1701124
//r2=[a1701124]=a171b070
a1700f94: e5823000 strr3, [r2]
//monitor_flash_len=[r2]=r3=1b070
……
a1701118: a1700044 .word 0xa1700044
a170111c: a1700048.word 0xa1700048
a1701120: a1719d24 .word 0xa1719d24
a1701124: a171b070 .word 0xa171b070
========================================
上面//是我自己的注释。这表明,你的了解的确是正确的。
经过这个进程之后,我总算认识到自己的误解在哪里了。本来,我是把”汇编言语中LDR伪指令对符号的引证”与”C言语中对汇编程序中符号/常量/变量的引证”搞混杂了。我想阐明以下几点:
(1) readelf以及u-boot.map和System.map所给出的符号表中符号的值,实际上是一共符号地点的地址,而不是指符号自身的值。
(2) 汇编言语中没有指针的概念,因而对符号的引证是”光秃秃”的。例如:
==========
.globl _armboot_start
_armboot_start: .word _start
ldr r2, _armboot_start
==========
实际上反汇编今后是:
============
a1700044 <_armboot_start>:
a1700044: a1700000 .word 0xa1700000
a1700074: e51f2038ldr r2, [pc, #-56] ; a1700044 <_armboot_start>
============
也便是说,_armboot_start是一个地址0xa1700044,其间的内容是0xa1700000,上面临_armboot_start的引证是直接将其替换为其一共的地址0xa1700044,而非其间的内容0xa1700000。这便是”光秃秃”的引证。
(3) C言语则不同,对变量/符号/常量的引证必需要经过地址来寻址,不管是大局变量仍是局部变量,不同的是局部变量在生命期完毕后,所占的地址空间会被开释罢了。即使是函数调用时的参数传递,尽管是将实参的值”劳动”给形参,但”劳动”的进程也是经过实参和形参的地址来对两者进行拜访的。
所以,在C言语中的 “monitor_flash_len =_bss_start – _armboot_start” 这句话中对_armboot_star的引证,实际上是把它用作了指针,把它作为拜访目标的地址来运用,经过这个地址即a1700044 来拜访对应存储空间所寄存的内容亦即0xa1700000,_bss_start也是相同的道理。所以这句话实际上是monitor_flash_len=[a1700048]-[0xa1700044]=a171b070-a1700000 = 1b070,这样就得到了正确的成果。
现在,咱们再答复最前面的问题:_start的值是什么?_start一共地址0xa1700000,在汇编言语中,对_start的”肯定引证”(这里是与用相对寻址进行跳转进行差异)便是将其替换为0xa1700000,但其间寄存的内容的的确确便是”b reset”这条指令的机器码,所以如果在C言语中引证_start,得到的成果反而便是这个指令的机器码了。其实这个问题很简单,仅仅和C言语的引证搅在一起,一些概念被偷换了罢了。