一 CCS鏈接器的作用和過程
匯編器已經將源文件(.asm)順序地按段的定義(SPC)轉換 成機器語言目標文件(.obj文件),即COFF文件, 連接器的主要任務是根據連接命令或連接命令文件(.cmd)將一個或多個 COFF目標文件連接起來,生成存儲器映象文件(.map)和可執行的輸出 文件(.out文件),即COFF目標模塊。 鏈接過程為:
(1)將各個目標文件合並起來,將各個文件的各個段配置到目標系統的存儲器中
(2)對各個符號和段進行重定位,並給它們指定一個最終的地址
(3)解決輸入文件之間未定義的外部引用 。
二 鏈接命令文件的寫法
coff(公共目標文件格式,Common object file format)文件格式是基於塊(section)的概念建立的,即程序被分解成各種塊的組合體:如文本塊、數據塊等。 具有一下特點:
(1)便於實現模塊化程序設計
(2)為管理代碼塊和目標系統存儲器提供更強有力和更加靈活的方法
(3)程序員設計時只需基於代碼塊和數據塊等概念進行,不需關注每條命令或每個數據的具體目標地址。至於它們的最終將處於存儲器的哪個位置,將由鏈接器來安排
(4)為程序編寫和移植提供了很大的方便
1 section
Section目標文件中最小單位稱為塊。一個塊就是最終在存儲器映象中占據連續空間的一段代碼或數據。所有的section按照是否自定義可以分為:
(1)Coff默認的section (2)自定義的section ,按照是否初始化可以分為:(1)初始化的section(2)未初始化的section 。C語言和匯編中可能有些不同。
匯編器中默認的section有:
section | 作用 | 通常位置 |
.text |
通常包含可執行代碼 |
RAM或者EPROM |
.data |
通常包含已初始化數據 |
ROM或者EPROM |
.bss |
通常用來為未初始化變量保留 |
RAM |
匯編中自定義模塊可以通過.sect 創建具可重定位地址的命名塊 和.usect創立未初始化塊。
C語言的section可以區分如下:
section | 作用 |
.text |
可代碼和常數 |
.cinit |
變量初值表 |
.switch | 用於大型switch語句的跳轉表 |
.const |
常量和字符串 |
.bss | 全局變量和靜態變量 |
.system | 全局堆(用於存儲器的分配) |
.stack | 堆棧 |
.far | 以far聲明的全局和靜態變量 |
.cio | 用於stdio函數 |
.ebss | 長調用的.bss(超過了64K地址限制) |
.esysmem | 長調用的.sysmem(超過了64K地址限制) |
econst | 長.const(可定位到任何地方) |
當然,C語言中可以自定義段
2.CMD
鏈接器有兩種定位快的辦法,一種是采用默認的分配算法,匯編中的過程如下:
(1)假定存儲器的起始地址為0
(2)假定有2^32字的存儲器可以用來分配
(3)將.text分配到起始地址為0的程序存儲器中
(4)將.data分配到緊接着.text的程序存儲器中
(5)將.bss分配到緊接着.data的程序存儲器中
(6)分配自定義的section。
連接器也可以通過鏈接命令文件來完成,CMD文件由三部分組成:
(1) 輸入輸出定義;
這一部分,可以通過ccs的“Build Option........”菜單設置。主要包含以下幾個部分:
具體的指令有:
-a 產生絕對地址(不可重新定位)的可執行模塊,若沒有指定-a或-r,默認情況為-a
-r 產生可重新定位不可執行的模塊
-ar 產生可重新定位可執行的模塊
-b 連接器將不合並任何由於多個文件而可能存在的重復符號表項,此項選擇的效果是使連接器運行較快,但其代價是輸出的COFF文件較大
-c 使用由TMS320C54x C/C++編譯器的ROM自動初始化模型所定義的連接約定
-cr使用由C編譯器的RAM自動初始化模型所定義的連接約定
-e global_symbol 定義全局符號為輸出模塊的指定主入口點
-f fill value為輸出段中空洞設定默認的填充值, fill value為16位的常數
-h 使所有的全局符號為靜態變量
-g global_symbol保持指定的global_symbol為全局符號,而不管是否使用了-h選項
-help , -? 顯示所有可利用的連接命令行選項
-head size為C語言的動態存儲器分配設置堆棧大小,以字為單位,並定義指定的堆棧大小的全局符號,size有默認值為1k字
-i dir 改變庫搜索方法為在搜索默認的位置前先搜索dir ,該項必須在-l(L)選項之前出現
-l filename 指定一個存檔庫文件為連接器的輸入 , filename為存檔庫文件名,該選項必須在-i 選項之后出現,目錄或文件名必須遵守操作系統的規定
-m filename 產生一個存儲器(地址)映射文件,輸出名為filename.map , 該文件列出了輸入和輸出段(包括空洞)的地址
-o filename 指定可執行輸出模塊的文件名(filename) , 默認為a.out , 目錄或文件名必須遵守操作系統的規定
-q 請求靜態運行(quiet run) ,即壓縮旗標(banner)必須是在命令行的第一個選項
-s 從輸出模塊中去掉符號表信息和行號
-stack size 設置C系統堆棧,大小以字為單位,並定義指定堆棧大小的全局符號,默認的size為1k
-u symbol 將不能分辯的外部符號放入輸出模塊的符號表
-vn 指定產生的COFF文件格式n , n=0、1或2,默認為COFF2
-w 當出現沒有定義的輸出段時,發出警告
-x 迫使重讀庫,以分辯后面的引用
MEMORY: 定義目標系統的存儲器映象,可以給它們命名,規定起始地址和長度
用法:MEMORY { 存儲器空間名:o = 十六進制存儲器起始地址 l = 十六進制存儲器長度 }
例如:
MEMORY { L2RAM: o = 0x10800000 l = 0x00020000 DDR2: o = 0x80000000 l = 0x10000000 }
(3) SECTION命令。
SECTIONS:指定怎樣組合各輸入塊以及將各輸出塊存放在存儲器 的哪個位置
用法:
sections { 段名1 > 存儲器空間名1 段名2 > 存儲器空間名2 . . . }
例子:
SECTIONS { .bss > L2RAM .cinit > L2RAM .cio > L2RAM .const > L2RAM .data > L2RAM .far > L2RAM .stack > L2RAM .switch > L2RAM .sysmem > L2RAM .text > L2RAM .ddr2 > DDR2 }
CMD中也可以自定義section,用法如下:
#pragma DATA_SECTION(函數名或全局變量名,"用戶自定義在數據空間的段名");
#pragma CODE_SECTION(函數名或全局變量名,"用戶自定義在程序空間的段名");
具體用法如下:
sections { 段名1 > 存儲器空間名1 段名2 > 存儲器空間名2 }
可以參開網址:CMD