摘? 要: 對TI公司新的匯編器和鏈接器創(chuàng)建的目標(biāo)文件所采用的一種格式——COFF目標(biāo)文件格式的組成和產(chǎn)生過程作了詳細(xì)的闡述。
關(guān)鍵詞: DSP技術(shù)? COFF文件格式
?
近年來,數(shù)字信號處理器(DSPs)在信號處理及運動控制方面得到了日益廣泛的應(yīng)用。開發(fā)DSPs時不論使用匯編語言還是C語言,源程序都要經(jīng)過編譯(對C語言)生成目標(biāo)文件,再由鏈接器把目標(biāo)文件鏈接成可執(zhí)行的COFF文件。TI公司新的匯編器和鏈接器創(chuàng)建的目標(biāo)文件采用一種稱為COFF(Common Object File Format)的目標(biāo)文件格式。采用這種文件格式更有利于模塊化編程,并且為管理代碼段和目標(biāo)系統(tǒng)存儲器提供更強有力和更靈活的方法。
1? 塊的基本概念
COFF文件格式鼓勵程序員用匯編語言或高級語言編程時使用基于代碼塊和數(shù)據(jù)塊的概念,而不是一條條命令或一個個數(shù)據(jù),這就使得程序的可讀性和可移植性大大增強。在COFF格式中,這種塊稱為section。TI公司新的匯編器和鏈接器提供了相關(guān)的命令來創(chuàng)建塊和對塊進(jìn)行處理。
塊是目標(biāo)文件中的最小單元,是最終在TMS320C/F2xx存儲器映象中占據(jù)一段連續(xù)空間的代碼或數(shù)據(jù)。目標(biāo)文件中的每一個塊都是相互獨立的。通常COFF目標(biāo)文件包含3個默認(rèn)的塊:(1).text塊:包括可執(zhí)行代碼;(2).data塊:包括已初始化的數(shù)據(jù);(3).bss塊:為沒有初始化的數(shù)據(jù)保留空間。
此外,匯編器和鏈接器允許程序員創(chuàng)建、命名、鏈接自定義的塊,這些塊與.text、.data、和.bss的使用類似。所有的塊可分為二種基本類型,即已初始化的塊和未初始化的塊。已初始化的塊包括已初始化的數(shù)據(jù)和程序代碼,上面提到的.text塊和.data塊就屬于這類塊。另外,匯編器命令.sect和.asect所創(chuàng)建的塊也屬于這類塊。未初始化的塊為沒有初始化的數(shù)據(jù)在存儲器映象中保留空間,.bss塊和由匯編器命令.usect所創(chuàng)建的塊屬于這一類。
匯編器提供了將各種代碼和數(shù)據(jù)段與相應(yīng)塊聯(lián)系的命令。
2?塊的匯編
匯編器對塊的處理功能主要是確定匯編語言程序的各部分屬于哪個特定的塊。匯編器用.text、.data、.sect、.asect、.bss、.usect命令完成對塊的定位。其中,.text、.data、.sect和.asect命令建立已初始化的塊,.bss和.usect命令則用來建立未初始化的塊。如果程序中沒有用任何命令對塊進(jìn)行操作,則匯編器將把所有的程序塊或數(shù)據(jù)塊統(tǒng)一匯編到.text塊中。
2.1 匯編器對已初始化塊的處理
已初始化塊包括已初始化的數(shù)據(jù)和程序代碼。這部分塊的內(nèi)容存儲在目標(biāo)文件中。當(dāng)程序下載時被下載到TMS320C/F2xx的存儲器中。每個已初始化塊可以獨立地進(jìn)行重定位,并且可以引用其他塊中定義的變量。鏈接器可以自動解決塊與塊之間變量引用的問題。
下面4個命令將代碼或數(shù)據(jù)存放在一個塊中,其命令格式如下:
.text
.data
.sect “塊名”
.asect “塊名”,地址
在這些命令中,.text和.data命令建立的塊名稱就是.text和.data,而后二個命令建立的塊是自定義的塊。其中.asect建立的塊具有絕對地址,一般不要使用。當(dāng)匯編器遇到上述命令時,立即停止匯編當(dāng)前塊,且開始將隨后的代碼或數(shù)據(jù)匯編到當(dāng)前命令所對應(yīng)的塊中。
2.2 匯編器對未初始化塊的處理
未初始化塊在TMS320C/F2xx存儲器中為沒有初始化的數(shù)據(jù)保留空間,它們通常被分配到RAM中。程序在運行時利用這些空間創(chuàng)建和存儲變量。
匯編器用.bss和.usect命令建立未初始化塊。其中,.bss命令在.bss塊中保留空間,.usect命令在自定義的塊中保留空間。它們的命令格式如下:
.bss??????? 變量,塊大小
變量.usect“塊名”,塊大小
匯編器遇到.bss和.usect命令時并不結(jié)束當(dāng)前塊,只是暫時離開當(dāng)前塊而去創(chuàng)建一個新塊。所以,.bss和.usect命令可以出現(xiàn)在一個已初始化塊中的任何地方,而不影響已初始化塊的內(nèi)容。
2.3 匯編器對自定義塊的處理
自定義塊是程序員自己建立的塊,它與默認(rèn)的.text、
.data和.bss塊的使用方法相同,而與默認(rèn)塊是分開匯編的。
程序員可以用.usect、.sect和.asect命令建立自定義的塊。其中,.usect建立的塊用來在RAM中為變量保留空間,其用法類似于.bss塊;.sect和.asect建立包括代碼和數(shù)據(jù)的塊,用法類似于.text塊和.data塊。.sect命令建立的塊是可重定位的,.asect命令建立的塊是具有絕對地址的塊,是不能重定位的。它們的命令格式如下:
變量.usect“塊名”,塊大小
.sect “塊名”
.asect “塊名”,地址
3? 塊的鏈接
鏈接器對塊的處理主要包括下面2個方面。首先,鏈接器將COFF目標(biāo)文件中的塊建立為程序塊或數(shù)據(jù)塊并以這些塊作為輸入塊,鏈接器再把這些輸入塊組合起來以建立可執(zhí)行的COFF輸出模塊。然后,鏈接器為輸出塊選擇存儲器地址。鏈接器提供Memory和Sections 2個命令來完成上述工作。其中,Memory命令定義目標(biāo)系統(tǒng)的存儲器分配,程序員可以通過指定存儲器起始地址和長度來定義每一塊存儲器。Sections命令定義如何組合輸入塊以及在存儲器何處存放輸出塊。若不用這二條命令,鏈接器就會采用默認(rèn)的分配方法;若采用這二條命令,則需要在鏈接器命令文件(擴(kuò)展名為.cmd)中確定。下面是一個TMS320F240鏈接命令文件的例子。
4?程序的重定位
匯編器對目標(biāo)文件中的每個塊匯編時都假定其起始地址為0,所以每一塊中的重定位符號都是相對于0地址而言的。當(dāng)然,所有的塊在存儲器中并不都是以0地址起始,因此鏈接器用以下方法對每一個塊進(jìn)行重定位。首先,鏈接器把塊分配到存儲器中,從而使各個塊都有自己的起始地址;然后調(diào)整符號值使之對應(yīng)于新的塊地址;最后通過調(diào)整重定位后符號的參考值來反映調(diào)整后的符號值。
鏈接器利用重定位項來調(diào)整符號的參考值。匯編器在每次可重定位符號被參考時會建立一個重定位項,鏈接器則在符號被重定位后利用這個重定位項來修正參考值。
5?COFF目標(biāo)文件的生成
下面以C語言編寫的源程序為例,給出如圖1所示的COFF目標(biāo)文件的生成框圖。
?
用戶編寫的C源程序經(jīng)過C編譯器的處理后,轉(zhuǎn)化為具有相同功能的匯編語言代碼。之后再作為獨立的匯編源程序經(jīng)過匯編處理產(chǎn)生COFF目標(biāo)文件,其中包含上述的各類程序塊或數(shù)據(jù)塊。接下來,鏈接器以這些塊作為輸入將其組合起來,并參照具體的CMD文件,最終生成可執(zhí)行的COFF文件。此外在鏈接過程中系統(tǒng)將自動訪問目標(biāo)文件庫和運行庫,以簡化鏈接過程,縮短鏈接過程所需的時間。
6? 結(jié)? 論
本文介紹了TI公司新的匯編器和鏈接器所采用的COFF目標(biāo)文件格式及這種文件格式中的最小單元——塊,討論了匯編器和鏈接器對塊的處理方法。COFF目標(biāo)文件格式非常有利于模塊化編程,使管理代碼段和系統(tǒng)存儲器更加方便和靈活,使程序具有更強的可讀性和可移植性。