新聞中心

EEPW首頁 > 嵌入式系統(tǒng) > 設(shè)計(jì)應(yīng)用 > ARM異常向量表中LDR指令、LDR偽指令的來龍去脈

ARM異常向量表中LDR指令、LDR偽指令的來龍去脈

作者: 時(shí)間:2016-11-10 來源:網(wǎng)絡(luò) 收藏
1、問題引出

ARM開發(fā)中,異常向量表(或者稱為中斷向量表)處在一個(gè)關(guān)鍵的位置,因?yàn)樗刂屏薃RM芯片復(fù)位時(shí)的跳轉(zhuǎn)地址,也即是調(diào)到哪里去執(zhí)行啟動(dòng)代碼。一般來說,異常向量表的形式如下

本文引用地址:http://m.butianyuan.cn/article/201611/317546.htm

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

在編譯鏈接時(shí),將此異常向量表安排到地址0處,芯片復(fù)位后PC == 0,便執(zhí)行 LDR pc, =resetHandler 這條跳轉(zhuǎn)指令,轉(zhuǎn)而執(zhí)行啟動(dòng)代碼。若發(fā)生其他異?;蛘咧袛鄷r(shí),PC被硬件強(qiáng)制賦值為 0x0000 00XX,也是取異常向量表中的跳轉(zhuǎn)指令執(zhí)行,轉(zhuǎn)而執(zhí)行對(duì)應(yīng)的異?;蛘咧袛嗵幚砝?。

但仔細(xì)觀察會(huì)發(fā)現(xiàn),復(fù)位異常和其他的異常不同。復(fù)位異常使用偽指令 LDR pc, =resetHandler,而其他異常則使用LDR指令。為什么?

2、關(guān)于ARM偽指令

ARM偽指令不是真正的指令,偽指令在真正編譯鏈接后,會(huì)被一條真實(shí)的ARM指令代替。

3、LDR指令和LDR偽指令的區(qū)別

1)LDR指令是將內(nèi)存中的一個(gè)字加載到目標(biāo)寄存器中,如

LDR R0,[R1] ;將R1指向內(nèi)存的32bit加載到R0中

LDR R4,lable ;將地址label處的內(nèi)存中的一個(gè)32bit的字加載到R4中,如果地址為label處的內(nèi)容是0xFFFF 5555,則此指令執(zhí)行后,R4 = 0xFFFF5555

如果是LDR RX, label的形式,按照ARM官方文檔的說法,LDR指令的內(nèi)存操作地址是在PC的基礎(chǔ)上加上指令中的立即數(shù)偏移得到,如果要訪問的內(nèi)存離當(dāng)前PC太遠(yuǎn),則LDR指令就無能為力了,因?yàn)長DR指令中只有12bit來存放偏移地址,太遠(yuǎn)或者不適合移位形成的偏移量不能用LDR指令。

LDR指令在執(zhí)行時(shí),必定會(huì)訪問內(nèi)存,訪問內(nèi)存就需要地址,如上面的R1寄存器給出的地址、label常數(shù)作為的地址等。LDR指令執(zhí)行完之后,PC的值等于label地址指向的內(nèi)容。

2)LDR偽指令則是將一個(gè)數(shù)賦給寄存器。LDR偽指令是將一個(gè)寄存器等于某個(gè)值,這個(gè)值可以來源于指令中包含的立即數(shù),也可以來源于一個(gè)內(nèi)存位置存放的內(nèi)容。當(dāng)要賦予的值可以用ARM指令的立即數(shù)表示時(shí),LDR偽指令用MOV指令代替,否則LDR偽指令用LDR指令代替。LDR偽指令的一般形式:

LDRR0,=0x01

LDRPC,=label

LDR R0,=0x01這條偽指令可以用MOV指令代替,因?yàn)橐x予的常數(shù)0x01可以包含在MOV指令的立即數(shù)中。而LDR PC, =label則不一定是用MOV指令來實(shí)現(xiàn),因?yàn)閘abel是一個(gè)地址常數(shù),通過指令中12bit立即數(shù)移位的方式不一定能形成。若MOV指令不能實(shí)現(xiàn),則用LDR指令來實(shí)現(xiàn),實(shí)現(xiàn)的過程如下圖

:即先使用PC+偏移量作為地址訪問內(nèi)存,將此地址的內(nèi)存加載到目標(biāo)寄存器中(PC寄存器)。當(dāng)然,指定地址處的內(nèi)存必須包含正確的值,編譯器自動(dòng)在這個(gè)地址中寫入正確的label值。

所以,LDR偽指令可以實(shí)現(xiàn)將任何32bit的數(shù)裝入目標(biāo)寄存器,并且在偽指令LDR PC, =label中執(zhí)行之后,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 是將標(biāo)號(hào)resetHandler的值(編譯器編譯時(shí)分配的地址值)載入PC,發(fā)生跳轉(zhuǎn),即跳轉(zhuǎn)到resetHandler處執(zhí)行;

LDR PC, XXXX_Addr 是將XXX_Addr處的內(nèi)容載入PC,發(fā)生跳轉(zhuǎn),必須訪問XXX_Addr地址的內(nèi)存將跳轉(zhuǎn)值取出。

5、總結(jié):

LDR PC, =label偽指令,可以實(shí)現(xiàn)任何地址的跳轉(zhuǎn),執(zhí)行后,直接跳轉(zhuǎn)到label處執(zhí)行;

LDR PC, label指令,執(zhí)行后是將label地址處的內(nèi)容(跳轉(zhuǎn)地址)裝入PC,所以LDR指令常常配合DCD使用。但也可以實(shí)現(xiàn)任何地址的跳轉(zhuǎn)。



評(píng)論


技術(shù)專區(qū)

關(guān)閉