關於ARM的PC指標(什麼時候PC+8,PC+4,PC-4,PC-8)
要理解PC指標,首先就要好好了解LR指標
連線暫存器LR(r14):用來儲存和恢復PC暫存器的內容,它有兩個特殊功能。
(1)儲存子程式返回地址。使用BL或BLX時,跳轉指令自動把返回地址放入r14中;子程式通過把r14複製到PC來實現返回,通常用下列指令之一:
MOV PC, LR
BX LR
通常子程式這樣寫,保證了子程式中還可以呼叫子程式。
stmfd sp!, {lr}
……
ldmfd sp!, {pc}
(2)當異常發生時,異常模式的r14用來儲存異常返回地址,將r14如棧可以處理巢狀中斷。
程式計數器r15(PC):PC是有讀寫限制的。當沒有超過讀取限制的時候,讀取的值是指令的地址加上8個位元組,由於ARM指令總是以字對齊的,故bit[1:0]總是00。當用str或stm儲存PC的時候,偏移量有可能是8或12等其它值。在V3及以下版本中,寫入bit[1:0]的值將被忽略,而在V4及以上版本寫入r15的bit[1:0]必須為00,否則後果不可預測。
知道PC暫存器和LR暫存器功能以後,再瞭解一下ARM處理器的三級流水線和多級流水線
首先,對於ARM7對應的流水線的執行情況,如下面這個圖所示:
從圖中可以看出,一條彙編指令的執行有三個步驟,取指、譯碼、執行,當第一條彙編指令取指完成後,緊接著就是第二條指令的取指,然後第三條...如此巢狀
其實很容易看出,第一條指令:
add r0, r1,$5
取指完成後,PC就指向了第二條指令,此時PC=PC+4
當第一條指令譯碼完成以後,此時PC=PC+8
所以第一條指令開始執行時,PC值已經加了8
所以必須記住這個前提,在arm中,每次該指令執行時,其實這時的PC值是PC=PC+8
而且這個前提也同樣適合多級流水線,原因就不解釋了
接下來談談我們在arm彙編時,什麼時候需要PC-4, PC-8, PC什麼都不減
這個取決於是在正常程式的跳轉還是發生異常:
如果是使用BL執行了正常程式的跳轉,那麼執行這條BL指令時,由於是正常的跳轉指令,所以cpu會將返回地址存放在LR中,即當前指令地址加4,當從子程式跳轉回來的時候,那麼就需要將儲存在LR暫存器中的值恢復給PC暫存器,
mov PC, LR 這樣的指令返回
IRQ異常發生時,因為這個異常是在指令執行時候發生的,PC的值等於當前執行指令加8,然後將這個值儲存在LR中。但是LR暫存器中儲存的是PC+8,指向的是後面的第二條指令,如果不進行減4處理,將會漏執行一條指令,所以PC恢復的時候就需要LR減4,所以正常從子程式返回的時候會使用如:
SUBS PC, LR,#4 返回到當前指令的下一條指令
未定義指令異常時,因為這個異常發生在指令譯碼階段,所以,此時PC的值就是未定義指令加4,然後儲存到LR(參考流水線圖);因為該指令未定義,所以返回時就不應該返回到這條未定義指令,而是返回到它的下一條指令,R14中儲存的剛好就是下一條指令的地址,所以就不用計算了,直接將R14賦值給PC就行了
預取指令異常是在流水線的執行階段時才進入異常,所以PC的值是當前執行指令地址加8,所以返回時應該返回到下一條指令,所以PC恢復的時候就需要R14減4
資料中止異常,這個異常是在本指令執行完成後才發生的,表示當前儲存器的訪問不能完成,從流水線圖可以看出,當第一條指令執行完成時,當前PC值已經指向了第一條指令地址加12的地址,LR中儲存的其實是第四條指令的地址了,所以從異常返回時,需要從第一條指令的下一條指令(第二條指令)開始執行,所以PC恢復的時候就需要R14減8
下面簡單總結一下:
1.SWI和和未定義指令異常中斷的返回:
指令地址
A PC-8 當前指令為SWI或未定義指令 此時發生中斷.PC的值還沒有更新.(不需要執行完此指 令,就跳到中斷了)
A+4 PC-4 中斷時處理器將PC-4儲存到LR
A+8 PC
返回時,從發生中斷的指令A(PC-8)的下一條指令A+4(PC-4)處開始執行,所以直接
把LR的值賦給PC就行了,具體指令為MOV PC,LR @(PC=A+4=LR)
2,IRQ和FIQ異常中斷處理的返回:
指令地址 對應於PC
A PC-8 執行此指令完成後(!)查詢IRQ及FIQ,如果有中斷請求
則產生中斷. .(需要執行完此指 令,再跳到中斷)
A+4 PC-4
A+8 PC
(此時PC的值已經更新,指向A+12.將當前PC-4(即A+8)
儲存到LR.返回時,要接著執行A+4(LR-4)處的指令,所以返回指令為
SUBS PC, LR,#4 @(PC=A+4=LR-4)
3,指令預取中止異常中斷處理的返回:
指令地址
A PC-8 執行本指令時發生中斷,
A+4 PC-4 處理器將A+4(PC-4)儲存到LR.
A+8 PC
返回時,發生指令預取中止的指令A(PC-8)處重新執行(A處的指令要重新執行),所以返回指令為
SUBS PC, LR,#4 @(PC=A=LR-4)
4,資料訪問中止異常中斷處理的返回:
指令地址
A PC-8 本指令訪問有問題的資料,產生中斷時,PC的值已經更新
A+4 PC-4 中斷髮生時PC=A+12,處理器將A+8(PC-4)儲存到LR.
A+8 PC
返回時,要返回到A處繼續執行,所以指令為SUBS PC, LR,#8 @(PC=A=LR-8)
(A處的指令要重新執行),
5.正常程式跳轉處理返回
使用BL跳轉時,它會自動將返回地址裝入LR中,即將當前PC-4存入LR中,返回時不用對LR進行加減操作
指令地址
對應於PC
A PC-8 (A處的指令不要重新執行)
A+4 PC-4
A+8 PC
mov PC, LR @(PC=A+4=LR) 現在LR的值就是A+4的地址
相關文章
- Go語言什麼時候該使用指標 與 指標使用分析Go指標
- 關於指標指標
- golang什麼時候應該把方法繫結在struct的值上而不是指標上?GolangStruct指標
- 什麼是智慧指標?為什麼要用智慧指標?指標
- 關於函式指標函式指標
- C++中什麼時候用move,什麼時候用forward?C++Forward
- 什麼時候需要自動化什麼時候用自動化?
- session是什麼時候建立的Session
- Python的類什麼時候用Python
- 什麼時候釋出
- 什麼時候能解脫
- 關於Swift中的指標的那些事Swift指標
- 關於Paging + Room,RecyclerView重新整理時的空指標異常OOMView指標
- 什麼時候採用socket通訊,什麼時候採用http通訊HTTP
- 什麼時候該用vuex?Vue
- beego 什麼時候支援grpcGoRPC
- 新版什麼時候釋出?
- 到底什麼時候使用mqMQ
- python什麼時候縮排Python
- win11什麼時候釋出的 win11什麼時候推送詳細介紹
- 關於引用(python中的偽指標)的理解Python指標
- 什麼時候才是微服務拆分的最佳時機?微服務
- OneThink什麼時候會有基於thinkphp5開發的啊?PHP
- 關於二維陣列指標的問題陣列指標
- Java關於空指標的防範與思考Java指標
- Mybatis什麼時候需要宣告jdbcType?MyBatisJDBC
- 複合指標、派生指標是什麼,你搞清楚了嘛?指標
- 什麼是資料指標管理,如何建立指標管理體系指標
- 什麼時候用linux系統多Linux
- shiro 什麼時候會進入 doGetAuthorizationInfo() ?
- 什麼時候選擇mmap而非read?
- 什麼是好的資料指標體系指標
- 美國公司年審時間是在什麼時候的?
- 指標相關指標
- 關於C++當中的指標懸空問題C++指標
- MySQL什麼時候會使用內部臨時表?MySql
- 英語日期序數詞的寫法?什麼時候加st?什麼時候加th?1~31號分別是怎麼加的?
- 你打算敲程式碼到什麼時候?
- 什麼時候會傳送options請求