一、跳轉指令實現函數調用
- LR(鏈接寄存器):保留函數返回地址
1.1 bl指令
????????跳轉指令bl,使LR保存當前函數進入前的下一條指令的地址,使函數調用后可以返回下一條指令的地址;
1.2 bx指令
????????跳到目標地址;
1.3 棧的使用方法?
函數調用前,保護現場,調用后恢復現場 :
????????使用棧(先進后出的特性);
棧的使用方法:
1.3.1.空增
????????保護時,SP先寫,再加;
????????恢復時,SP先減,再讀;
1.3.2 滿增?
????????保護時,SP先加,再寫;
????????恢復時,SP先讀,再減;
1.3.3 滿減
????????保護時,SP先減,再寫;
????????恢復時,SP先讀,再加;
1.3.4 空減
????????保護時,SP先寫,再減;
????????恢復時,SP先加,再讀;
1.4 ARM內核使用滿減棧,使用方法
1.4.1 stmfd指令
入棧保護時,使用stmfd指令;
????????stmfd <c><Rn>{!}, <registers>:
? ? ? ? 其中:
- !是讓棧指針的內容隨程序發生變化
- 命令含義是把多個寄存器保存到Rn寄存器中
- 舉例:stmfd sp!, {r0-r12, lr}
1.4.2 ldmfd指令?
出棧恢復時,使用ldmfd指令;
? ? ? ? 如:ldmfd sp!, {r0-r12, lr}
二、匯編與C語言混合調用
注意:由主調者負責保護現場和恢復現場
2.1 匯編為主調
?步驟:
- 首先確保SP指針有效
- 對函數聲明:import(導入)? ? ? ? ?export(導出)
- 保護現場
- 使用bl跳轉
- 恢復現場
注意:
若參數4個以內,R0-R3傳遞參數;
若有第五個參數,只能用棧的方式來傳參:
- ? ? ? ? stmfd sp!, {r4}
- ? ? ? ? ldmfd sp!, {r4}
main.c?
start.s?
2.2 c為主調
在匯編中,聲明c的函數,import main
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?export asm_add?
main.c?
start.s?
三、準備工作
3.1 切換模式
CPS命令修改CPSR寄存器的M[4:0]
????????如,CPS #<mode>
????????(但不支持keil)?
解決方法:
(1) msr指令:讀取cpsr、spsr寄存器
mrs r0, cpsr
(2) 于r0中,設置相關數據,設為User模式(10000)
bic r0, r0, #(0x1F << 0) //低5位清零 orr r0, r0, #0x10 //第5位置一
(3) msr指令:寫入cpsr、spsr寄存器
msr cpsr_c, r0
(4)將User模式下的SP進行設置
ldr sp, =0x40001000 sub sp, sp, #1024
3.2 異常處理被占用(解決),初始化異常向量表?
3.3 產生軟件中斷異常
加^,表示恢復執行前cpsr寄存器的值
四、IMX6ULL入門
- Windows編寫代碼
- Ubuntu編寫代碼
主要部分:
- 搭建編程環境
- 匯編點燈
- 下載程序
4.1 引腳的功能復用
- 說明哪些引腳歸哪個外設使用
- PAD:引腳
- MUX:功能復用
以點亮LED為例:
????????GPIO1組的3號引腳
數據寄存器? ? ? ? GPIO data register(GPIOx_DR)?
方向寄存器?
?