注意:為什么要進行C語言環境的初始化?
在沒有進行C語言環境的初始化之前的初始化工作都是用匯編進行初始化的。
比如核心初始化,和內存初始化
棧:
棧幀:一個進程中一般會有多個函數,每一個函數都需要在內存中開辟一個棧空間來使用,每一個函數所占用棧叫做棧幀。
pc
lr
sp
fp
這四個數據。
棧幀之空間的界定:fp(棧幀指針)指針用於界定最上面的棧界限,用於訪問棧中的數據(r11)
sp(棧指針)指針用於界定最下面的棧界限,一般一直指向棧頂(r13)
注意:當一個函數調用另外一個函數時,調用函數棧幀指針相關信息中的fp(棧幀指針)和sp(堆棧指針)保存於被調用函數的棧的頂部
棧的作用:
1:保存局部變量
2:傳遞參數
3:保存寄存器的值
注意:在arm中,對於函數參數的傳遞,如果傳遞參數的個數小於等於4個,就只需要用
r0,r1,r2,r3來傳遞參數,如果多於4個參數就會用到棧來傳遞參數
滿棧和空棧:
根據SP指向的位置,棧可以分為滿棧和空棧
1:滿棧(值向的位置有數據)
當堆棧指針sp總是指向最后壓入堆棧的數據
2:空棧(指向的位置沒有數據)
當堆棧指針sp總是指向下一個將要放入數據的空位置
arm使用是滿棧
1:升棧
隨着數的入棧,sp指針從低地址變到高地址
2:降棧
隨着數據的入棧,sp指針從高地址變道低地址
arm采用降棧
棧對C語言的作用:
(1)保存局部變量
bss段初始化:
一般情況下:
局部變量是存放在:棧
malloc函數中的數據對存放在:堆
位初始化的局部變量是存放在:bss段
一般要求對於BSS中的數據是默認為0 ,對於bss段中的數據的初始化就是將其中的數據預置為零
如何邁進C預言的大門:
找到main()函數的入口地址嗎,將這個地址直接賦值給PC
C預言和匯編混合編程:
一:為什么需要C預言和匯編語言的混合編程
1:執行效率
2:能夠更直接的控制未處理器,具體意思就是能夠直接用匯編指令訪問計算集中的某些特殊和重要的寄存器。
二:匯編語言調用C語言函數
調用方式:直接用匯編指令中的跳轉指令,跳到C語言main()函數的入口
三:C語言調用匯編語言
對於C語言,匯編語言中的用來定位函數頭符標號,相當於C語言中的一個函數。
主意調用的時候需要將匯編語言中調用的代碼用.global 偽指令定義該模塊為全局型
四:C語言中嵌套編寫匯編語言
格式:
_asm_(
匯編語言部分
:輸出部分
:輸入部分
:破壞描述部分
);
輸出部分:執行匯編語句后可能會把C語言中的的一些變量修改了,修改的就放在輸出部分
輸入部分:執行的匯編語言需要到C語言 中的拿到一些數據做參數,這部分數據就是輸入部分
破會描述部分:使用匯編語句時,凡是寄存器中值被修改了,被修改寄存器中都放在破壞描述部分
注意:帶分號的幾部分,分號后面刻意省略,但是分號不能省略
例子1:
void write_p15_c1(unsigned long value)
{
_asm_(
“mcr p15,0,%0,c1,c0,0\n”
:
:”r”(value)
)
}
分析:
:“r”(value) 輸入部分,表示寄存器,具體哪個通用寄存器,系統自己決定,(value)則表示將要讀取的值
例子2:
int gboot_main()
#define GPBCOM #0x56000010 @定義宏,將管腳控制寄存器的地址定義成宏(地址查看芯片手冊可得)
#define GPBDAT #0X56000014 @定義宏,將管腳數據寄存器的的地址定義成宏(地址查看芯片手冊可得){_asm_("ldr r1,=0x15400\n" @將控制字寫入到寄存器r1中(根據芯片手手冊 卡看控制字,每兩位控制一個引腳功能)"str r1,[%0]\n" @控制字寫入到控制寄存器中,注意[]中的"%0"表示一 個參數,這個參數來自於輸入或輸出部分,由輸入 和輸出部分定義 "ldr r1,=0x6bf\n" @將要寫入到 的數據寫入到r1中,(每一位控制一個 管腳,具體些什么查看芯片手冊) "str r1,[%1]\n" @將數據寫回到管腳寄存器中 : @輸出部分 :"r"(GPBCOM),"r"(GPBDAT) @輸入部分,一般讀為輸入,寫為輸出 :"r1" @破壞部分,表示程序在執行過程中影響或修 改到的明確的寄存器)return 0;}注意幾點:1:所有的匯編語句都要用雙引號擴起來2:注意輸入和輸出部分是怎么一回事,讀取數據一般就是輸入,寫入數據一般就是輸出