舉個小例子,下面是一段arm彙編**:
位址指令
0x3000
bl add
0x3004
mov r0,#0
0x3008
mov r1,#1
0x300c
mov r2,#2
area test,code,readonly
entry
start
mov r0,#1
mov r1,#1
bl add
mov r0,#0
mov r1,#1
addadd r0,r0,r1
mov r0,r0,r1
end當0x3000處的bl指令執行時,會把pc(=0x3008)儲存到lr暫存器裡面,也就是lr=0x3008。接下來處理器會立即對lr進行乙個自動的更新動作:lr=lr-0x4,這樣,lr裡面的位址為0x3008 – 0x4 = 03004,它是指令」mov r0,#0」的位址,所以當從子程式add返回時,lr裡面正好是正確的返回位址。既是下一條要執行的指令的位址。
(2)中斷異常處理函式呼叫
異常就是正在執行的指令,由於各種軟體或硬體故障被打斷,比如,在讀資料或指令時,訪問儲存器失敗、產生了乙個外部硬體中斷等。當這些情況發生時,在arm系統裡,由異常和中斷處理程式做出相應的處理,當處理完成後,要返回到被中止的指令,使被中止的指令能夠繼續正常執行下去。因此,確定異常和中斷處理程式的返回位址是乙個非常重要的問題。
1、中斷處理
當外部中斷irq和fiq(fast interrpt request,快速中斷請求)發生時,arm核完成一部分工作。當然,這些工作是任何異常發生時都必須要做的,所以arm處理器就會自動帶我們完成。 其它重要的工作,必須由程式設計師來完成。arm處理器處理的事包括從使用者模式切換到irq模式、狀態暫存器值的變化及跳轉。比如說,處理器自動跳轉到從0x0位址開始的異常中斷向量表的0x18處,在向量表的0x18處,簡單的指令為」b handlerirq」。
那程式設計師所要關心的就是實現具體的異常處理程式(handlerirq)。當用arm組合語言實現handlerirq函式的時候,如何確定handlerirq函式正確地返回位址,使被中止的指令能夠繼續正常執行下去。
比較常用的中斷處理程式結構如下:
handlerirq ;中斷響應,從向量表直接跳來
sub r14,r14,#4 ;計算返回位址
stmfd r13, ;保護現場,一般只需要保護
bl irqhandler ;跳到具體的異常處理函式
ldmfd r13,^ ;恢復現場
有程式可以看出,通過」sub r14,r14,#4」計算中斷函式的返回位址。那有人一定會問,為什麼計算返回位址的時候要減去4呢?
位址指令
0x3000
bl add
0x3004
mov r0,#0
0x3008
mov r1,#1
0x300c
mov r2,#2
我們看上個表,比如在執行位址為0x3004的move指令時,突然來了乙個irq中斷,這個中斷打斷了move指令的執行,這個時候就要去跳轉到異常處理函式,之後還要返回0x3004位址重新執行move指令。當中斷發生時,lr裡面儲存了使用者模式下pc的值,那麼當執行位址為0x3004的move指令時,pc的值應該是0x300c,前面介紹過,當發生跳轉時,處理器會對lr進行乙個自動的更新動作:lr=lr-0x4,這樣lr裡面的位址是0x300c-0x04=0x3008。但是0x3008並不是我們要的位址,因為中斷發生在位址為0x3004的move指令執行的時候,所以中斷處理完後應該返回這個位址。 這就是在計算返回位址的時候lr減去4的原因。對於fiq中斷和預取指中止異常,計算返回位址方法和irq相同。
arm中斷保護和恢復 ARM的中斷處理 一
前面的文章介紹了linux的中斷處理機制,而作業系統的中斷處理是和硬體的中斷控制器緊密相關的,本文將以arm這樣乙個具體的處理器為例,講解硬體層面對中斷的支援。arm的中斷控制器被稱為gic generic interrupt controller 最開始的v1版本最多支援8個pe和1020個中斷源...
arm中斷保護和恢復 ARM中斷異常處理的返回
舉個小例子,下面是一段arm彙編 0x3000bl add 0x3004mov r0,0 0x3008mov r1,1 0x300cmov r2,2 area test,code,readonly entry start mov r0,1 mov r1,1 bl add mov r0,0 mov r...
arm中斷保護和恢復 ARM異常中斷返回的幾種情況
重要基礎知識 r15 pc 總是指向 正在取指 的指令,而不是指向 正在執行 的指令或正在 解碼 的指令。一般來說,人們習慣性約定將 正在執行的指令作為參考點 稱之為當前第一條指令,因此 pc總是指向第三條指令。當 arm 狀態時,每條指令為 4 位元組長,所以 pc 始終指向該指令位址加 8 位元...