/***********摘自《ARM LR寄存器https://blog.csdn.net/fivedoumi/article/details/50446444》********************/
異常的發生會導致程序正常運行的被打斷, 並將控制流轉移到相應的異常處理(異常響應),有些異常(fiq、irq)事件處理后,系統還希望能回 到當初異常發生時被打斷的源程序斷點處繼續完成源程序的執行(異常返回),這就需要一種解決方案, 用於記錄源程序的斷點位置,以便正確的異常返回。
類似的還有子程序的調用和 返回。在主程序中(通過子程序調用指令)調用子程序時,也需要記錄下主程序中的調用點位置,以便將來的子程序的返回。
在ARM處理器中使用 R14實現對斷點和調用點的記錄,即使用R14用作返 回連接寄存器(LR)。在硬件上和指令執行上,CPU 自動完成相應返回點的記錄。在ARM 匯編語言程序設計時,R14和LR通用。
ARM處理器相應異常時,會自動完成將當前的PC保存到LR寄存器。//注意:發生異常時進入異常程序時,LR中保存的不是斷點下一條指令,而是直接將PC保存到 LR中,不是將PC-4保存到LR中。
ARM處理器執行子程序調用指令(BL )時,會自動完成將當前的PC的值減去4的結果數據保存到LR寄存器。即將調用指令的下緊鄰指令的地址保存到LR。
ARM處理器針對不同的模式,共有6個鏈接寄存器資源(LR ),其中用戶模式和系統模式共用一個 LR,每種異常模式都有各自專用的R14 寄存器(LR )。這些鏈接寄存器分別為 R14、R14_svc、R14_abt、R14_und、R14_irq、R14_fiq,
程序設計者要清晰處理器的模式與相應寄存器的對應關系,都是使用 R14,但不同模式下的R14 不是同一個物理資源,其內容可能天壤之別。
R14 不用做鏈接寄存器(LR )時,也可以用做通用數據寄存器。
PC 代表程序計數器,流水線使用三個階段,因此指令分為三個階段執行:1.取指(從存儲器裝載一條指令);2.譯碼(識別將要被執行的指令);3.執行(處理 指令並將結果寫回寄存器)。而R15(PC)總是指向“正在取指”的指令,而不是指向“正在執行”的指令或正在“譯碼”的指令。一般來說,人們習慣性約定 將“正在執行的指令作為參考點”,稱之為當前第一條指令,因此PC總是指向第三條指令。當ARM狀態時,每條指令為4字節長,所以PC始終指向該指令地址 加8字節的地址,即:PC值=當前程序執行位置+8;
ARM指令是三級流水線,取指,譯指,執行時同時執行的,現在PC指向的是正在取指的地址,那么cpu正在譯指的指令地址是PC-4(假設在ARM狀態 下,一個指令占4個字節),cpu正在執行的指令地址是PC-8,也就是說PC所指向的地址和現在所執行的指令地址相差8。
當突然發生中斷的時候,保存的是PC的地址
這樣你就知道了,如果返回的時候返回PC,那么中間就有一個指令沒有執行,所以用SUB pc lr-irq #4
MOV PC,LR
看下面這個ARM匯編吧
BL NEXT ;跳轉到子程序
......... ;NEXT處執行
NEXT
..........
MOV PC,LR ;從子程序返回
這里的BL是跳轉的意思,LR(R14)保存了返回地址
PC(R15)是當前地址,把LR給PC就是從子程序返回
這里有一下總結
首先
1.SP(R13) LR(R14)PC(R15)
2.lr(r14)的作用問題,這個lr一般來說有兩個作用:
1》.當使用bl或者blx跳轉到子過程的時候,r14保存了返回地址,可以在調用過程結尾恢復。
2》.異常中斷發生時,這個異常模式特定的物理R14被設置成該異常模式將要返回的地址。
另外注意pc,在調試的時候顯示的是當前指令地址,而用mov lr,pc的時候lr保存的是此指令向后數兩條指令的地址,大家可以試一下用mov pc,pc,結果得到的是跳轉兩條指令,這個原因是由於arm的流水線造成的,預取兩條指令的結果.
3.子程序返回的三種方法:
- MOV PC,LR
- BL LR
- 把R14壓棧再出棧
- 在子程序入口處使用以下指令將R14存入堆棧
- 對應的,使用以下指令可以完成子程序的返回
LDMFD SP!, {<Regs>,LR}
深入理解ARM的這三個寄存器,對編程以及操作系統的移植都有很大的裨益。
1、堆棧指針r13(SP):每一種異常模式都有其自己獨立的r13,它通常指向異常模式所專用的堆棧,也就是說五種異常模式、非異常模式(用戶模式和系統模式),都有各自獨立的堆棧,用不同的堆棧指針來索引。這樣當ARM進入異常模式的時候,程序就可以把一般通用寄存器壓入堆棧,返回時再出棧,保證了各種模式下程序的狀態的完整性。
2、連接寄存器r14(LR):每種模式下r14都有自身版組,它有兩個特殊功能。
(1)保存子程序返回地址。使用BL或BLX時,跳轉指令自動把返回地址放入r14中;子程序通過把r14復制到PC來實現返回,通常用下列指令之一:
1、 MOV PC, LR
2、 BX LR
3、通常子程序這樣寫,保證了子程序中還可以調用子程序。
stmfd sp!, {lr}
……
ldmfd sp!, {pc}
(2)當異常發生時,異常模式的r14用來保存異常返回地址,將r14如棧可以處理嵌套中斷。
3、程序計數器r15(PC):PC是有讀寫限制的。當沒有超過讀取限制的時候,讀取的值是指令的地址加上8個字節,由於ARM指令總是以字對齊的,故bit[1:0]總是00。當用str或stm存儲PC的時候,偏移量有可能是8或12等其它值。在V3及以下版本中,寫入bit[1:0]的值將被忽略,而在V4及以上版本寫入r15的bit[1:0]必須為00,否則后果不可預測。