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。
但是在ADS中PC确實是指向即将執行的指令處,這個是軟體處理後的結果,主要是為了使用者調試程式友善.
需要注意的是,目前使用指令STM/STR儲存R15時候,儲存的可能是目前指令位址值+8位元組,也可能儲存的是目前的指令位址+12位元組.到底是哪種,取決于晶片的具體的設計方式。無論如何,在同一晶片中,要麼采用目前的指令位址+8,要麼采用目前的指令位址+12。是以對于使用者來講,盡量避免使用STM/STR指令來儲存R15的值。但是可以在開始的時候用一段程式對晶片的offset進行測試!
代碼如下:
SUB R1, PC, #4 ;獲得下面的存放下面存放STR指令的位址
STR PC,[R0]
LDR R0,[RO]
SUB R0, R0, R1
ARM7中斷與PC、LR的問題:
1,假設目前是PC,PC-4,PC-8(三級流水)
2,發生IRQ異常,執行保護操作,LR中儲存由于FIQ或IRQ占先而沒有被執行的指令的位址(即有些資料上把這個位址寫成PC或者目前位址,很費解甚至誤解)的下一條位址
3,清空流水線
4,進入中斷服務程式
5,待流水線填滿,執行操作才被重新挂起(解釋了ARM7為什麼是0.9MIPS)
6,中斷傳回前,對LR處理,LR=LR-4,指向之前被清空的已譯碼但沒被執行的指令的位址
7,清空流水線,傳回
8,重新對丢棄的前一次已譯碼指令取指
9,待流水線滿,開始繼續執行