樂鑫c3藍牙智能鎖樂鑫科技華南代理商嵌入式鏈接器功能,鏈接器把工程源程序中生成的二進制目標代碼和已經存在的二進制函數庫等機器語言模塊“拼接”起來,形成可執行程序。gcc鏈接器 ld 輸入二進制文件“.o”,輸出可執行與可鏈接格式(Executable andLinkable Format,ELF)的可執行文件“*.out”。樂鑫c3藍牙智能鎖樂鑫科技華南代理商鏈接過程的工作可分為兩部分,根據目標文件中的全局標簽銜接不同二進制文件中的指令塊,將程序中的指令和數據段映射到存儲空間,即分配內存地址及其范圍。用實模式下,指令和數露所映射的存儲空間必須與目標嵌入式系統中世紀物聯存儲資源一致。
在嵌入式系統中,通常將存儲器分為主存儲器(Main Memory)和輔助存儲器(Auklary Memory)兩種類型。主存儲器具有完整的總線接口,例如 RAM、ROM或Nor Flash 等,連接在處理器的存儲總線上,所有存儲單元直接映射到處理器的內存空間,處理器能夠隨機讀取 RAM、ROM 和 Nor Flash 的存儲單元,能夠隨機寫入RAM的存儲單元。運行程序時,主存儲器保存指令和數據。樂鑫c3藍牙智能鎖樂鑫科技華南代理商輔助存儲器通過I/O接口或串行通信接口與處理器相連,例如 Nand Flash、I2C 接口 EEPROM 和 SPI口EEPROM等,處理器不能直接隨機訪問其中的存儲單元。輔助存儲器常用于存系統鏡像文件、備份數據和設置系統參數。在鏈接過程中,所映射的存儲空間是系統中的主存儲器空間,與輔助存儲無關。
在 gcc鏈接器 ld 命令腳本文件中(或設置選項),使用內存(MEMORY)命令描述目標系統中內存塊的位置和大小,告訴鏈接器使用哪些存儲地址區域,以及必須免使用哪些存儲地址段。樂鑫c3藍牙智能鎖樂鑫科技華南代理商腳本文件多包含一個內存描述段,其中可以定義多個存塊。聲明內存描述段的語法格式如下:
MEMORY
{
name(attr);ORIGION = origion addr,LENGTH = len
....
}
其中,
name,鏈接器內部用于引用區域的名稱。
可以使用任何符號名稱(attr),屬性可選列表,指定是否使用特定內存放置鏈接器腳本文件中未列出段,所支持的常用屬性包括:
1、“Letter”,段屬性(section attribute);
2、“R”,只讀部分;
3、“w”,讀/寫部分;
4、“X”,包含可執行代碼;
5、“A”,可分配的部分;
6、“I”,需要初始化的段;
7、“!”,反轉隨后屬性的意義。
origion_addr,物理內存塊的起始地址。關鍵字 ORIGIN 可以縮寫為 org 或o。len,物理內存塊長度。關鍵字 LENGTH 可以縮寫為 len 或 1。
下面是內存措述段的示例。示例中,樂鑫c3藍牙智能鎖樂鑫科技華南代理商系統內存有 ROM和RAM 兩個可供分配的區域。ROM 區域,只讀,可執行程序,起始地址 0,大小256 KB。RAM 區域,可讀/寫,可執行程序,起始地址 0x20000000,大小 4 MB。
MEMORY
{
ROM (rx) : ORIGIN = 0,LENGTH = 256K
SRAM(wx):org = 0x20000000,1 = 4M
}
所有鏈接器腳本文件都必須包含內存描述段,但不同鏈接器所用的命令格式有所差異。鏈接器將程序中的指令和只讀數據映射到只讀存儲 ROM 中,將變量和可讀/寫數據映射到可讀/寫內存 SRAM 中。
鏈接器將數據空間 SRAM 分為靜態數據和動態數據空間。鏈接時將靜態變量全局變量和其他靜態數據映射到靜態數據空間,空間大小由變量和數據大小決定動態數據空間分為棧(stack)和堆(heap)。樂鑫c3藍牙智能鎖樂鑫科技華南代理商??臻g保存程序中的局部變量和臨時數據,堆空間為程序中動態申請內存的函數提供存儲資源。鏈接時通常將棧和堆空間映射到 SRAM 的地址范圍頂端(地址值大的區域)。
在圖 5.4 中,ROM 內 0x00000000~0x0000FFFF 是保留區域,0x00010000~0x0003FFFF 存放指令和只讀數據。SRAM區的起始地址是 0x20000000,靜態數據區映射到 SRAM 的低地址段,堆和棧映射到高地址段。
棧stack 動態數據dynamic data--靜態數區staic data--代碼text--保留reserved
圖5.4 鏈接內存分配示例圖
鏈接時將目標文件中的數據和指令標簽(地址符號)映射到內存中的地址位置。如果沒有在腳本文件中指定映射地址,則按照鏈接順序分配目標文件中的標簽地址。樂鑫c3藍牙智能鎖樂鑫科技華南代理商鏈接器為文件中先接的代碼和標簽分配低地址,為后連接的代碼和標簽分配高地址。
RV321采用相對分支跳轉(PC relartive branch),更容易生成與程地位關(Position Independent Code,PIC)的二進制 RISC-V 程序。
代碼生成示例
下面通過簡單程序“Hello World”,說明從輸入 C 語言源程序到生成可執行序的過程。
先輸入 C語言源程序 main.c,代碼如下:
void main(void)
{
printf("Hello World! n");
}
編譯后生成匯編語言程序 main.asm。
. section.text,main,"ax", @progbits //可分配,可執行,包含數據
.globl main //全局標簽聲明
.type main,@function //函數類型聲明
main; //標簽
Addi sp,sp,-16addi //分配??臻g
Sw ra,12(sp) //保存函數返回地址到棧中
Lui a0,hi(.LCO) //獲取printf參數
Addi a0,a0,%lo(.LC0)
Call printf
匯編和鏈接后,生成程序中 main 部分的可執行代碼。
內存地址 二進制指令 匯編語句
0x200001ec FF010113 //addi sp,sp,-16
0x200001f0 00112623 //sw ra,12(sp)
0x200001f4 200017B7 //lui a5,0x20001
0x200001f8 33078513 //addi a0,a5,816
0x200001fc 514000EE //jal 0x20000710 <printf>
其中,內存地址欄是指令映射到內存空間的地址,匯編語句欄是指令對應的匯編語句。