新聞中心

        EEPW首頁 > 嵌入式系統 > 設計應用 > ARM異常向量表中LDR指令、LDR偽指令的來龍去脈

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

        作者: 時間:2016-11-10 來源:網絡 收藏
        1、問題引出

        ARM開發中,異常向量表(或者稱為中斷向量表)處在一個關鍵的位置,因為它控制了ARM芯片復位時的跳轉地址,也即是調到哪里去執行啟動代碼。一般來說,異常向量表的形式如下

        本文引用地址:http://www.104case.com/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

        在編譯鏈接時,將此異常向量表安排到地址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使用。但也可以實現任何地址的跳轉。



        評論


        技術專區

        關閉
        主站蜘蛛池模板: 太白县| 阿瓦提县| 衡阳县| 信丰县| 遂宁市| 林芝县| 高密市| 东城区| 宿松县| 北流市| 齐齐哈尔市| 新建县| 吴江市| 盘山县| 德化县| 东宁县| 新民市| 台安县| 太保市| 新津县| 丹阳市| 康保县| 江北区| 金华市| 砚山县| 文登市| 葵青区| 阳西县| 曲麻莱县| 墨玉县| 池州市| 申扎县| 夏津县| 雅江县| 大理市| 墨竹工卡县| 乌兰县| 永登县| 弥勒县| 临泽县| 五家渠市|