C代碼中如何使用連結指令碼中定義的變數,連結指令碼
原文內容:http://www.100ask.org/bbs/forum.php?mod=viewthread&tid=16231&page=1&authorid=2
--------------------------------------------------------------------------------------------------------------------------
參考文章:https://sourceware.org/ml/binutils/2007-07/msg00154.html
在連結指令碼中,經常有這樣的代碼:
- SECTIONS
- {
- .....
- . = ALIGN(4);
- .rodata : { *(.rodata) }
- . = ALIGN(4);
- .data : { *(.data) }
- . = ALIGN(4);
- .got : { *(.got) }
- . = ALIGN(4);
- __bss_start = .;
- .bss : { *(.bss) }
- _end = .;
- }
複製代碼
其中__bss_start, _end 表示BSS段的起始、終止地址。
我們想對這段空間清零時,
1.在彙編代碼中,可以直接引用__bss_start, _end,比如:
- ldr r0, =__bss_start
- ldr r1, =_end
複製代碼
2. 在C代碼中,我們不能直接引用它們,要這樣做:
- void clean_bss(void)
- {
- extern int __bss_start, _end;
- int *p = &__bss_start;
-
- for (; p < &_end; p++)
- *p = 0;
- }
複製代碼
__bss_start, _end不是表示某個值嗎?在C代碼中為什麼要使用取址符號 & ?
原因:
一.
在C代碼中,這樣的語句:
- int foo = 1000;
複製代碼會導致2件事情發生:
1. 在代碼中,留出4位元組的空間,儲存數值1000
2.在C語言的symbole talbe,即符號表中,有一個名為foo的項,它裡面存有那4位元組空間的地址。
我們執行 foo = 1時,會先去符號表中找到foo對應的地址,然後把數值1填到那個地址對應的記憶體;
我們執行 int *a = &foo時,會直接把符號表中foo的地址,寫給a。
二.
在連結指令碼中,假設
- __bss_start = 1000
複製代碼
__bss_start並不是一個變數,它只是一個值,並不需要在記憶體中留出一段空間來儲存它;
在C語言中,符號表中會有一個名為__bss_start的項,這個項目中的值(地址值)是1000;
注意,這個1000並沒有實際存在的記憶體。
三.
所以:在C語言中,要去使用連結指令碼中定義的值時,應該這樣做:
- extern int __bss_start;
- int val = &__bss_start;
複製代碼
使用取址符號&去得到它在符號表中的值。
注意,這個值只是連結指令碼中定義的值,並不表示某個變數的地址。
查看評論