13.6代碼重定位_重定位_清除BSS段的C函數(shù)實(shí)現(xiàn)
在前面,我們使用匯編程序來實(shí)現(xiàn)了重定位和清bss段,本節(jié)我們將使用C語言,實(shí)現(xiàn)重定位和清除bss段。
1.打開start.S把原來的匯編代碼刪除改為調(diào)用C函數(shù)?

改為?

2. 在init.c 實(shí)現(xiàn)如上兩個(gè)C函數(shù)?

匯編中,為C語言傳入的參數(shù),依次就是R1、R2、R3。 編譯,燒寫運(yùn)行沒有問題。
我們假設(shè)不想?yún)R編傳入?yún)?shù),而是C語言直接取參數(shù)。
1. 修改start.S 跳轉(zhuǎn)到C函數(shù)不需要任何參數(shù)?

2. 修改鏈接腳本,讓__code_start 等于當(dāng)前地址,也就是這里的0x30000000?

3.修改init.c 用函數(shù)來獲取參數(shù)?


編譯燒寫運(yùn)行 ,沒有問題。
總結(jié): C函數(shù)怎么使用lds文件總的變量abc?
在C函數(shù)中聲明改變量為extern外部變量類型,比如:
extern int abc;
使用時(shí),要取址,比如:
int *p = &abc;//p的只即為lds文件中abc的值
匯編文件中可以直接使用外部鏈接腳本中的變量,但C函數(shù)中要加上取址符號。
解釋一下原因:
C函數(shù)中,定義一個(gè)全局變量int g_i;
,程序中必然有4字節(jié)的空間留出來給這個(gè)變量g_i
。
假如我們的lds文件中有很多變量
lds{
a1 =?;
a2 =?;
a3 =?;
...
}
如果我們C程序只用到幾個(gè)變量,完全沒必要全部存儲lds里面的所有變量,C程序是不保存lds中的變量的。
對于萬一要用到的變量,編譯程序時(shí),有一個(gè)symbol table符號表:

如何使用symbol table符號表?
對于常規(guī)變量g_i,得到里面的值,使用&g_i得到addr;
為了保持代碼的一致,對于lds中的a1,使用&a1得到里面的值;
這只是一個(gè)編譯器的小技巧,不用深究。
結(jié)論:
C程序中不保存lds文件中的變量,lds再大也不影響;
借助symbol table保存lds的變量,使用時(shí)加上"&"得到它的值,鏈接腳本的變量要在C程序中聲明為外部變量,任何類型都可以;