_bss_start _armboot_start
生活随笔
收集整理的這篇文章主要介紹了
_bss_start _armboot_start
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
PS:在u-boot源碼時遇到_armboot_start、_bss_start等這些變量,不知道指向什么地址,于是查了一下,弄清了ARM匯編中“.word”這個偽指令是什么意思了,感覺自己很菜。借鑒一下網(wǎng)友帖子的內(nèi)容,關(guān)鍵在帖子最后的總結(jié):?? ?? ???匯編和C引用變量的不同:匯編是“絕對”引用,即沒有指針的概念,引用得到的就是值;c語言是“間接”引用,相當(dāng)于指針的概念,引用地址變量,得到的就是該變量所指的內(nèi)容值。
感謝原作者,以下為原帖:
aaronwong:?u-boot中代碼的疑問(_armboot_start與_start)?
---------------------------
我使用的是u-boot-1.3.0-rc2。在cpu/pxa/start.S中,有如下的標(biāo)號定義:?
_TEXT_BASE:?
.word TEXT_BASE?/*uboot映像在SDRAM中的重定位地址,我設(shè)置為0xa170 0000 */?
.globl _armboot_start?
_armboot_start:?
.word _start?/*_start是程序入口,鏈接完畢它的值應(yīng)該是0xa170 0000=TEXT_BASE*/?
/* 這句話的意思應(yīng)該是在_armboot_start標(biāo)號處,保存了_start的值,也就是說,_armboot_start是存放_start的地址,該地址對應(yīng)的存儲單元內(nèi)容是0xa170 0000*/?
/*?
* These are defined in the board-specific linker script. 下面的定義與上面應(yīng)該是一個意思。?
*/?
.globl _bss_start?
_bss_start:?
.word __bss_start?
======================?
按照上面的理解,__bss_start是uboot 的bss段起始地址,那么uboot映像的大小就是__bss_start - _start;在relocate代碼段中計算uboot的大小時,也體現(xiàn)了這一點。?
實際上,_armboot_start并沒有實際意義,它只是在"ldr r2, _armboot_start"中用來尋址_start的值而已,_bss_start也是一樣的道理,真正有意義的應(yīng)該是_start和 __bss_start本身。?
但是,令我不解的是,在C入口函數(shù)start_armboot()中(對應(yīng)文件為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都是沒有實際意義的,它們只是一個地址,有實際意義的是地址中的內(nèi)容_start和__bss_start(雖然也還是地址)。象第一句話,其“意圖”很明顯,是把gd作為全局?jǐn)?shù)據(jù)結(jié)構(gòu)體的指針,并初始化為“SDRAM中的uboot起始地址(即TEXT_BASE)-CFG_MALLOC_LEN-全局?jǐn)?shù)據(jù)結(jié)構(gòu)體大小”。?
要實現(xiàn)這個“意圖”,應(yīng)該是寫成:gd =(gd_t*)(_start - CFG_MALLOC_LEN - sizeof(gd_t));或者gd =(gd_t*)(TEXT_BASE- CFG_MALLOC_LEN -sizeof(gd_t));才對阿?用_armboot_start來作運(yùn)算應(yīng)該是沒有任何意義才對!??
第二句話也是一樣的道理,它的意圖是要計算u-boot映像的大小,應(yīng)該寫成__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?
上面我刪除了與該討論無關(guān)的包含“_start""t的標(biāo)號信息。?
顯然,我前面的理解應(yīng)該是正確的(_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,?
那么 根據(jù)這句:?
_armboot_start: .word _start?
所以_armboot_start的值應(yīng)該是a1700000?
所以?
monitor_flash_len = _bss_start - _armboot_start = a171b070 - a1700000 = 1b070?
而不是你說的 = 4?
以上個人意見.
aaronwong: [Re: eltshan]
-------------------
謝謝,eltshan!你的理解是正確的,不過我看了之后還是沒能想得很明白,因為我在想,按你所說,那么_start的值應(yīng)該是多少呢?難道是“breset”這條指令的機(jī)器碼?所以我對ELF格式的u-boot映像文件作了反匯編,分析之后終于找到了癥結(jié)所在。以下是部分分析過程,首先是反匯編:
arm-iwmmxt-linux-gnueabi-objectdump -D u-boot > u-boot.s?
并提取了monitor_flash_len = _bss_start - _armboot_start;這條語句相關(guān)的反匯編代碼如下:?
==============================?
a1700044 <_armboot_start>:?
a1700044: a1700000 .word 0xa1700000?
a1700048 <_bss_start>:?
a1700048: a171b070 .word 0xa171b070?
a171b070 <monitor_flash_len>:?
a171b070: 00000000 .word 0x00000000?
.....?
a1700f40: e59f41d0 ldr r4, [pc, #464] ; a1701118 <start_armboot+0x1dc>?
//r4=[a1701118]=a1700044?
.....?
a1700f7c: e59f3198 ldr r3, [pc, #408] ; a170111c <start_armboot+0x1e0>?
//r3=[a1700044]=a1700048?
a1700f80: e5942000 ldr r2, [r4]?
//r2=[a1700044]=a1700000?
a1700f84: e59f4194 ldr r4, [pc, #404] ; a1701120 <start_armboot+0x1e4>?
//r4=[a1701120]=a1719d24?
a1700f88: e5933000 ldr r3, [r3]?
//r3=[a1700048]=a171b070?
a1700f8c: e0623003 rsb r3, r2, r3?
//r3= r3-r2 = a171b070-a1700000 = 1b070;?
a1700f90: e59f218c ldr r2, [pc, #396] ; a1701124 <start_armboot+0x1e8>?
//r2=[a1701124]=a171b070?
a1700f94: e5823000 str r3, [r2]?
//monitor_flash_len=[r2]=r3=1b070?
......?
a1701118: a1700044 .word 0xa1700044?
a170111c: a1700048 .word 0xa1700048?
a1701120: a1719d24 .word 0xa1719d24?
a1701124: a171b070 .word 0xa171b070?
========================================?
上面//是我自己的注釋。這表明,你的理解的確是正確的。?
經(jīng)過這個過程之后,我終于認(rèn)識到自己的誤解在哪里了。原來,我是把"匯編語言中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: e51f2038 ldr r2, [pc, #-56] ; a1700044 <_armboot_start>?
============?
也就是說,_armboot_start是一個地址0xa1700044,其中的內(nèi)容是0xa1700000,上面對_armboot_start的引用是直接將其替換為其表示的地址0xa1700044,而非其中的內(nèi)容0xa1700000。這就是"赤裸裸"的引用。?
(3)C語言則不同,對變量/符號/常量的引用必須要通過地址來尋址,不管是全局變量還是局部變量,不同的是局部變量在生命期結(jié)束后,所占的地址空間會被釋放而已。即使是函數(shù)調(diào)用時的參數(shù)傳遞,雖然是將實參的值"拷貝"給形參,但"拷貝"的過程也是通過實參和形參的地址來對兩者進(jìn)行訪問的。?
所以,在C語言中的 "monitor_flash_len = _bss_start - _armboot_start"這句話中對_armboot_star的引用,實際上是把它用作了指針,把它作為訪問對象的地址來使用,通過這個地址即a1700044來訪問對應(yīng)存儲空間所存放的內(nèi)容亦即0xa1700000,_bss_start也是同樣的道理。所以這句話實際上是monitor_flash_len=[a1700048]-[0xa1700044]=a171b070-a1700000 = 1b070,這樣就得到了正確的結(jié)果。?
現(xiàn)在,我們再回答最前面的問題:_start的值是什么?_start表示地址0xa1700000,在匯編語言中,對_start的"絕對引用"(這里是與用相對尋址進(jìn)行跳轉(zhuǎn)進(jìn)行區(qū)別)就是將其替換為0xa1700000,但其中存放的內(nèi)容的的確確就是"breset"這條指令的機(jī)器碼,所以如果在C語言中引用_start,得到的結(jié)果反而就是這個指令的機(jī)器碼了。其實這個問題很簡單,只是和C語言的引用攪在一起,一些概念被偷換了而已。
感謝原作者,以下為原帖:
aaronwong:?u-boot中代碼的疑問(_armboot_start與_start)?
---------------------------
我使用的是u-boot-1.3.0-rc2。在cpu/pxa/start.S中,有如下的標(biāo)號定義:?
_TEXT_BASE:?
.word TEXT_BASE?/*uboot映像在SDRAM中的重定位地址,我設(shè)置為0xa170 0000 */?
.globl _armboot_start?
_armboot_start:?
.word _start?/*_start是程序入口,鏈接完畢它的值應(yīng)該是0xa170 0000=TEXT_BASE*/?
/* 這句話的意思應(yīng)該是在_armboot_start標(biāo)號處,保存了_start的值,也就是說,_armboot_start是存放_start的地址,該地址對應(yīng)的存儲單元內(nèi)容是0xa170 0000*/?
/*?
* These are defined in the board-specific linker script. 下面的定義與上面應(yīng)該是一個意思。?
*/?
.globl _bss_start?
_bss_start:?
.word __bss_start?
======================?
按照上面的理解,__bss_start是uboot 的bss段起始地址,那么uboot映像的大小就是__bss_start - _start;在relocate代碼段中計算uboot的大小時,也體現(xiàn)了這一點。?
實際上,_armboot_start并沒有實際意義,它只是在"ldr r2, _armboot_start"中用來尋址_start的值而已,_bss_start也是一樣的道理,真正有意義的應(yīng)該是_start和 __bss_start本身。?
但是,令我不解的是,在C入口函數(shù)start_armboot()中(對應(yīng)文件為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都是沒有實際意義的,它們只是一個地址,有實際意義的是地址中的內(nèi)容_start和__bss_start(雖然也還是地址)。象第一句話,其“意圖”很明顯,是把gd作為全局?jǐn)?shù)據(jù)結(jié)構(gòu)體的指針,并初始化為“SDRAM中的uboot起始地址(即TEXT_BASE)-CFG_MALLOC_LEN-全局?jǐn)?shù)據(jù)結(jié)構(gòu)體大小”。?
要實現(xiàn)這個“意圖”,應(yīng)該是寫成:gd =(gd_t*)(_start - CFG_MALLOC_LEN - sizeof(gd_t));或者gd =(gd_t*)(TEXT_BASE- CFG_MALLOC_LEN -sizeof(gd_t));才對阿?用_armboot_start來作運(yùn)算應(yīng)該是沒有任何意義才對!??
第二句話也是一樣的道理,它的意圖是要計算u-boot映像的大小,應(yīng)該寫成__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?
上面我刪除了與該討論無關(guān)的包含“_start""t的標(biāo)號信息。?
顯然,我前面的理解應(yīng)該是正確的(_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,?
那么 根據(jù)這句:?
_armboot_start: .word _start?
所以_armboot_start的值應(yīng)該是a1700000?
所以?
monitor_flash_len = _bss_start - _armboot_start = a171b070 - a1700000 = 1b070?
而不是你說的 = 4?
以上個人意見.
aaronwong: [Re: eltshan]
-------------------
謝謝,eltshan!你的理解是正確的,不過我看了之后還是沒能想得很明白,因為我在想,按你所說,那么_start的值應(yīng)該是多少呢?難道是“breset”這條指令的機(jī)器碼?所以我對ELF格式的u-boot映像文件作了反匯編,分析之后終于找到了癥結(jié)所在。以下是部分分析過程,首先是反匯編:
arm-iwmmxt-linux-gnueabi-objectdump -D u-boot > u-boot.s?
并提取了monitor_flash_len = _bss_start - _armboot_start;這條語句相關(guān)的反匯編代碼如下:?
==============================?
a1700044 <_armboot_start>:?
a1700044: a1700000 .word 0xa1700000?
a1700048 <_bss_start>:?
a1700048: a171b070 .word 0xa171b070?
a171b070 <monitor_flash_len>:?
a171b070: 00000000 .word 0x00000000?
.....?
a1700f40: e59f41d0 ldr r4, [pc, #464] ; a1701118 <start_armboot+0x1dc>?
//r4=[a1701118]=a1700044?
.....?
a1700f7c: e59f3198 ldr r3, [pc, #408] ; a170111c <start_armboot+0x1e0>?
//r3=[a1700044]=a1700048?
a1700f80: e5942000 ldr r2, [r4]?
//r2=[a1700044]=a1700000?
a1700f84: e59f4194 ldr r4, [pc, #404] ; a1701120 <start_armboot+0x1e4>?
//r4=[a1701120]=a1719d24?
a1700f88: e5933000 ldr r3, [r3]?
//r3=[a1700048]=a171b070?
a1700f8c: e0623003 rsb r3, r2, r3?
//r3= r3-r2 = a171b070-a1700000 = 1b070;?
a1700f90: e59f218c ldr r2, [pc, #396] ; a1701124 <start_armboot+0x1e8>?
//r2=[a1701124]=a171b070?
a1700f94: e5823000 str r3, [r2]?
//monitor_flash_len=[r2]=r3=1b070?
......?
a1701118: a1700044 .word 0xa1700044?
a170111c: a1700048 .word 0xa1700048?
a1701120: a1719d24 .word 0xa1719d24?
a1701124: a171b070 .word 0xa171b070?
========================================?
上面//是我自己的注釋。這表明,你的理解的確是正確的。?
經(jīng)過這個過程之后,我終于認(rèn)識到自己的誤解在哪里了。原來,我是把"匯編語言中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: e51f2038 ldr r2, [pc, #-56] ; a1700044 <_armboot_start>?
============?
也就是說,_armboot_start是一個地址0xa1700044,其中的內(nèi)容是0xa1700000,上面對_armboot_start的引用是直接將其替換為其表示的地址0xa1700044,而非其中的內(nèi)容0xa1700000。這就是"赤裸裸"的引用。?
(3)C語言則不同,對變量/符號/常量的引用必須要通過地址來尋址,不管是全局變量還是局部變量,不同的是局部變量在生命期結(jié)束后,所占的地址空間會被釋放而已。即使是函數(shù)調(diào)用時的參數(shù)傳遞,雖然是將實參的值"拷貝"給形參,但"拷貝"的過程也是通過實參和形參的地址來對兩者進(jìn)行訪問的。?
所以,在C語言中的 "monitor_flash_len = _bss_start - _armboot_start"這句話中對_armboot_star的引用,實際上是把它用作了指針,把它作為訪問對象的地址來使用,通過這個地址即a1700044來訪問對應(yīng)存儲空間所存放的內(nèi)容亦即0xa1700000,_bss_start也是同樣的道理。所以這句話實際上是monitor_flash_len=[a1700048]-[0xa1700044]=a171b070-a1700000 = 1b070,這樣就得到了正確的結(jié)果。?
現(xiàn)在,我們再回答最前面的問題:_start的值是什么?_start表示地址0xa1700000,在匯編語言中,對_start的"絕對引用"(這里是與用相對尋址進(jìn)行跳轉(zhuǎn)進(jìn)行區(qū)別)就是將其替換為0xa1700000,但其中存放的內(nèi)容的的確確就是"breset"這條指令的機(jī)器碼,所以如果在C語言中引用_start,得到的結(jié)果反而就是這個指令的機(jī)器碼了。其實這個問題很簡單,只是和C語言的引用攪在一起,一些概念被偷換了而已。
總結(jié)
以上是生活随笔為你收集整理的_bss_start _armboot_start的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 光环国际PMP:逗乐~项目经理感言
- 下一篇: ROS机器人程序设计-课程形成性评价表-