SWI指令---軟件中斷實例詳解(原創)

                         

                   SWI指令---軟件中斷實例詳解

關鍵字:  SWI,指令,軟件中斷,實例,詳解

SWI,即software interrupt軟件中斷。該指令產生一個SWI異常。意思就是處理器模式改變爲超級用戶模式,CPSR寄存器保存到超級用戶模式下的SPSR寄存器,並且跳轉到SWI向量。其ARM指令格式如下:

SWI{cond} immed_24

Cond域:是可選的條件碼 (參見 ARM彙編指令條件執行詳解).

immed_24域:範圍從 0 224-1 的表達式, (0-16777215)。用戶程序可以使用該常數來進入不同的處理流程。

一、方法1:獲取immed_24操作數。

爲了能實現根據指令中immed_24操作數的不同,跳轉到不同的處理程序,所以我們往往需要在SWI異常處理子程序中去獲得immed_24操作數的實際內容。獲得該操作數內容的方法是在異常處理函數中使用下面指令:

LDR     R0[LR,#-4]

該指令將鏈接寄存器LR的內容減去4後所獲得的值作爲一個地址,然後把該地址的內容裝載進R0。此時再使用下面指令,immed_24操作數的內容就保存到了R0

BIC     R0R0#0xFF000000

該指令將R0的高8位清零,並把結果保存到R0,意思就是取R0的低24位。

可能還是有人會問:爲什麼在SWI異常處理子程序中執行這兩條指令後,immed_24操作數的內容就保存到了R0寄存器呢?之所以會有這樣的疑問,基本都是因爲對LR寄存器的作用沒了解清楚。下面介紹一下鏈接寄存器LRR14)的作用。

寄存器R14(LR寄存器)有兩種特殊功能:

·在任何一種處理器模式下,該模式對應的R14寄存器用來保存子程序的返回地址。當執行BLBLX指令進行子程序調用時,子程序的返回地址被放置在R14中。這樣,只要把R14內容拷貝到PC中,就實現了子程序的返回(具體的子程序返回操作,這裏不作詳細介紹)。

·當某異常發生時,相應異常模式下的R14被設置成異常返回的地址(對於某些異常,可能是一個偏移量,一個較小的常量)。異常返回類似於子程序返回,但有小小的不同(這裏不作詳細介紹)。

所謂的子程序的返回地址,實際就是調用指令的下一條指令的地址,也就是BL或BLX指令的下一條指令的地址。所謂的異常的返回的地址,就是異常發生前,CPU執行的最後一條指令的下一條指令的地址。

例如:(子程序返回地址示例)

指令                       指令所在地址

ADD     R2R1R3             ;0x300000

BL      subC                   ;0x300004

MOV     R1,#2                  ;0x300008

BL指令執行後,R14中保存的子程序subC的返回地址是0x300008

再例如:(異常返回地址示例)

指令                       指令所在地址

ADD     R2R1R3             ;0x300000

SWI     0x98                   ;0x300004

MOV     R1,#2                  ;0x300008

SWI指令執行後,進入SWI異常處理程序,此時R14中保存的返回地址爲0x300008

所以,在SWI異常處理子程序中執行 LDR  R0[LR,#-4]語句,實際就是把產生本次SWI異常的SWI指令的內容(如:SWI   0x98)裝進R0寄存器。又因爲SWI指令的低24位保存了指令的操作數(如:0x98),所以再執行BIC   R0R0#0xFF000000語句,就可以獲得immed_24操作數的實際內容。

二、方法2:使用參數寄存器。

    實際上,在SWI異常處理子程序的實現時,還可以繞開immed_24操作數的獲取操作,這就是說,我們可以不去獲取immed_24操作數的實際內容,也能實現SWI異常的分支處理。這就需要使用R0-R4寄存器,其中R0-R4可任意選擇其中一個,一般選擇R0,遵從ATPCS原則。

    具體方法就是,在執行SWI指令之前,給R0賦予某個數值,然後在SWI異常處理子程序中根據R0值實現不同的分支處理。例如:

指令                       指令所在地址

MOV     R0,#1                  ; #1R0

SWI     0x98                   ; 產生SWI中斷,執行異常處理程序SoftwareInterrupt

ADD     R2R1R3             ;

 

;SWI異常處理子程序如下

SoftwareInterrupt

        CMP     R0, #6              ; if R0 < 6

        LDRLO   PC, [PC, R0, LSL #2] ; if R0 < 6,PC = PC + R0*4,else next

        MOVS    PC, LR

SwiFunction

        DCD     function0     ;0

        DCD     function1     ;1

        DCD     function2     ;2

        DCD     function3     ;3

        DCD     function4     ;4

        DCD     function5     ;5

Function0

    異常處理分支0代碼

Function1

    異常處理分支1代碼

function2

    異常處理分支2代碼

function3

    異常處理分支3代碼

function4

    異常處理分支4代碼

function5

    異常處理分支5代碼

    ARM體系結構中,當正確讀取了PC的值時,該值爲當前指令地址值加8字節,也就是說,對於ARM指令集來說,讀出的PC值指向當前指令的下兩條指令的地址,本例中就是指向SwiFunction 表頭DCD  function0 這個地址,在該地址中保存了異常處理子分支function0的入口地址。所以,當進入SWI異常處理子程序SoftwareInterrupt時,如果R0=0,執行LDRLO   PC, [PC, R0, LSL #2]語句後,PC的內容即爲function0的入口地址,即程序跳轉到了function0執行。在本例中,因爲R0=1,所以,實際程序是跳轉到了function1

執行。R0左移2LDRLO   PC, [PC, R0, LSL #2],R0*4,是因爲ARM指令是字(4個字節)對齊的DCD  function0等僞指令也是按4字節對齊的。

    在本方法的實現中,實際指令中的24位立即數(immed_24域)被忽略了, 就是說immed_24域可以爲任意合法的值。如在本例中,不一定使用SWI 0x98,還可以爲SWI   0x00或者SWI 0x01等等,程序還是會進入SWI異常處理子程序SoftwareInterrupt,然後根據R0

的內容跳轉到相應的子分支。

三、KEIL CARM編譯器中SWI的使用方法:

    待續

四、ADSC語言編程SWI的使用方法:

        待續

發佈了17 篇原創文章 · 獲贊 2 · 訪問量 13萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章