ARM異常向量表中LDR指令、LDR偽指令的來龍去脈
在ARM開發中,異常向量表(或者稱為中斷向量表)處在一個關鍵的位置,因為它控制了ARM芯片復位時的跳轉地址,也即是調到哪里去執行啟動代碼。一般來說,異常向量表的形式如下
本文引用地址:http://www.104case.com/article/201611/317546.htmVector: ; All default exception handlers (except reset) are ; defined as weak symbol definitions. ; If a handler is defined by the application it will take precedence. LDR pc, =resetHandler ; Reset LDR pc, Undefined_Addr ; Undefined instructions LDR pc, SWI_Addr ; Software interrupt (SWI/SYS) LDR pc, Prefetch_Addr ; Prefetch abort LDR pc, Abort_Addr ; Data abort B . ; RESERVED LDR pc, IRQ_Addr ; IRQ LDR pc, FIQ_Addr ; FIQ
Undefined_Addr: DCD Undefined_HandlerSWI_Addr: DCD SWI_HandlerPrefetch_Addr: DCD Prefetch_HandlerAbort_Addr: DCD Abort_HandlerFIQ_Addr: DCD FIQ_HandlerIRQ_Addr DCD IRQ_Handler
在編譯鏈接時,將此異常向量表安排到地址0處,芯片復位后PC == 0,便執行 LDR pc, =resetHandler 這條跳轉指令,轉而執行啟動代碼。若發生其他異常或者中斷時,PC被硬件強制賦值為 0x0000 00XX,也是取異常向量表中的跳轉指令執行,轉而執行對應的異常或者中斷處理例程。
但仔細觀察會發現,復位異常和其他的異常不同。復位異常使用偽指令 LDR pc, =resetHandler,而其他異常則使用LDR指令。為什么?
2、關于ARM偽指令
ARM偽指令不是真正的指令,偽指令在真正編譯鏈接后,會被一條真實的ARM指令代替。
3、LDR指令和LDR偽指令的區別
1)LDR指令是將內存中的一個字加載到目標寄存器中,如
LDR R0,[R1] ;將R1指向內存的32bit加載到R0中
LDR R4,lable ;將地址label處的內存中的一個32bit的字加載到R4中,如果地址為label處的內容是0xFFFF 5555,則此指令執行后,R4 = 0xFFFF5555
如果是LDR RX, label的形式,按照ARM官方文檔的說法,LDR指令的內存操作地址是在PC的基礎上加上指令中的立即數偏移得到,如果要訪問的內存離當前PC太遠,則LDR指令就無能為力了,因為LDR指令中只有12bit來存放偏移地址,太遠或者不適合移位形成的偏移量不能用LDR指令。
LDR指令在執行時,必定會訪問內存,訪問內存就需要地址,如上面的R1寄存器給出的地址、label常數作為的地址等。LDR指令執行完之后,PC的值等于label地址指向的內容。
2)LDR偽指令則是將一個數賦給寄存器。LDR偽指令是將一個寄存器等于某個值,這個值可以來源于指令中包含的立即數,也可以來源于一個內存位置存放的內容。當要賦予的值可以用ARM指令的立即數表示時,LDR偽指令用MOV指令代替,否則LDR偽指令用LDR指令代替。LDR偽指令的一般形式:
LDRR0,=0x01
LDRPC,=label
LDR R0,=0x01這條偽指令可以用MOV指令代替,因為要賦予的常數0x01可以包含在MOV指令的立即數中。而LDR PC, =label則不一定是用MOV指令來實現,因為label是一個地址常數,通過指令中12bit立即數移位的方式不一定能形成。若MOV指令不能實現,則用LDR指令來實現,實現的過程如下圖
:即先使用PC+偏移量作為地址訪問內存,將此地址的內存加載到目標寄存器中(PC寄存器)。當然,指定地址處的內存必須包含正確的值,編譯器自動在這個地址中寫入正確的label值。
所以,LDR偽指令可以實現將任何32bit的數裝入目標寄存器,并且在偽指令LDR PC, =label中執行之后,PC的值就是label的值。
4、回到異常向量表
Vector: ; All default exception handlers (except reset) are ; defined as weak symbol definitions. ; If a handler is defined by the application it will take precedence. LDR pc, =resetHandler ; Reset LDR pc, Undefined_Addr ; Undefined instructions LDR pc, SWI_Addr ; Software interrupt (SWI/SYS) LDR pc, Prefetch_Addr ; Prefetch abort LDR pc, Abort_Addr ; Data abort B . ; RESERVED LDR pc, IRQ_Addr ; IRQ LDR pc, FIQ_Addr ; FIQ
Undefined_Addr: DCD Undefined_HandlerSWI_Addr: DCD SWI_HandlerPrefetch_Addr: DCD Prefetch_HandlerAbort_Addr: DCD Abort_HandlerFIQ_Addr: DCD FIQ_HandlerIRQ_Addr DCD IRQ_Handler
LDR PC, =resetHandler 是將標號resetHandler的值(編譯器編譯時分配的地址值)載入PC,發生跳轉,即跳轉到resetHandler處執行;
LDR PC, XXXX_Addr 是將XXX_Addr處的內容載入PC,發生跳轉,必須訪問XXX_Addr地址的內存將跳轉值取出。
5、總結:
LDR PC, =label偽指令,可以實現任何地址的跳轉,執行后,直接跳轉到label處執行;
LDR PC, label指令,執行后是將label地址處的內容(跳轉地址)裝入PC,所以LDR指令常常配合DCD使用。但也可以實現任何地址的跳轉。
評論