.bss符號像編譯器(或彙編器)生成的任何其他符號一樣得到解決。通常這通過在「部分」中放置相關的符號來工作。例如,編譯器可能會將程序代碼放在名爲「.text」的部分(出於歷史原因;-),在名爲「.data」的部分中初始化數據,以及在名爲「.bss」的部分中單元化數據。
例如:
int i = 4;
int x[10];
char chArray[100];
int main(int argc, char**argv)
{
}
產生(用gcc -S):
.file "test.c"
.globl i
.data
.align 4
.type i, @object
.size i, 4
i:
.long 4
.text
.globl main
.type main, @function
main:
leal 4(%esp), %ecx
andl $-16, %esp
pushl -4(%ecx)
pushl %ebp
movl %esp, %ebp
pushl %ecx
subl $4, %esp
addl $4, %esp
popl %ecx
popl %ebp
leal -4(%ecx), %esp
ret
.size main, .-main
.comm x,40,32
.comm chArray,100,32
.ident "GCC: (GNU) 4.3.2 20081105 (Red Hat 4.3.2-7)"
.section .note.GNU-stack,"",@progbits
的。數據指令通知彙編放置i的數據部分中,」。長4"給它它的初始值。當文件被組裝時,我將在數據部分的偏移量0處定義。
.text指令將把main放置在.text節中,同樣偏移量爲零。
這個例子有趣的是x和chArray是使用.comm指令定義的,而不是直接放在.bss中。兩者都只有一個大小,而不是抵消(還)。
當鏈接器獲取目標文件時,它通過組合具有相同名稱的所有部分並相應地調整符號偏移將它們鏈接在一起。它也爲每個部分提供了一個絕對的地址來加載它。
將由.comm指令定義的符號組合在一起(如果存在多個具有相同名稱的定義)並放置在.bss節中。在這一點上,他們得到了他們的地址。
+1無法解釋更好! 雖然所有這些都是架構相關的,雖然我不知道一個例子,但所有的.bss地址都可以相對於硬件寄存器組成 - 所以實際地址只能解析在運行時。 – James 2009-12-27 16:04:34
@Autopulated:好點。我實際上實現了一個C編譯器,它的確如此:它使用X索引寄存器指向.bss區域以獲取與位置無關的數據。 – 2009-12-27 16:17:12
謝謝:-)。因此,如果得到它,那麼一旦所有的.comm指令被合併,並且這些解析的地址在它們被引用的任何地方被修補(變量的.bss +偏移類型),則.bss將得到它的符號解析。在運行時分配.bss基址。對? – 2009-12-27 17:38:06