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 R0,R0,#0xFF000000
該指令將R0的高8位清零,並把結果保存到R0,意思就是取R0的低24位。
可能還是有人會問:爲什麼在SWI異常處理子程序中執行這兩條指令後,immed_24操作數的內容就保存到了R0寄存器呢?之所以會有這樣的疑問,基本都是因爲對LR寄存器的作用沒了解清楚。下面介紹一下鏈接寄存器LR(R14)的作用。
寄存器R14(LR寄存器)有兩種特殊功能:
·在任何一種處理器模式下,該模式對應的R14寄存器用來保存子程序的返回地址。當執行BL或BLX指令進行子程序調用時,子程序的返回地址被放置在R14中。這樣,只要把R14內容拷貝到PC中,就實現了子程序的返回(具體的子程序返回操作,這裏不作詳細介紹)。
·當某異常發生時,相應異常模式下的R14被設置成異常返回的地址(對於某些異常,可能是一個偏移量,一個較小的常量)。異常返回類似於子程序返回,但有小小的不同(這裏不作詳細介紹)。
所謂的子程序的返回地址,實際就是調用指令的下一條指令的地址,也就是BL或BLX指令的下一條指令的地址。所謂的異常的返回的地址,就是異常發生前,CPU執行的最後一條指令的下一條指令的地址。
例如:(子程序返回地址示例)
指令 指令所在地址
ADD R2,R1,R3 ;0x300000
BL subC ;0x300004
MOV R1,#2 ;0x300008
BL指令執行後,R14中保存的子程序subC的返回地址是0x300008。
再例如:(異常返回地址示例)
指令 指令所在地址
ADD R2,R1,R3 ;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 R0,R0,#0xFF000000語句,就可以獲得immed_24操作數的實際內容。
二、方法2:使用參數寄存器。
實際上,在SWI異常處理子程序的實現時,還可以繞開immed_24操作數的獲取操作,這就是說,我們可以不去獲取immed_24操作數的實際內容,也能實現SWI異常的分支處理。這就需要使用R0-R4寄存器,其中R0-R4可任意選擇其中一個,一般選擇R0,遵從ATPCS原則。
具體方法就是,在執行SWI指令之前,給R0賦予某個數值,然後在SWI異常處理子程序中根據R0值實現不同的分支處理。例如:
指令 指令所在地址
MOV R0,#1 ; #1給R0
SWI 0x98 ; 產生SWI中斷,執行異常處理程序SoftwareInterrupt
ADD R2,R1,R3 ;
;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左移2位(LDRLO 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的使用方法:
待續
四、ADS中C語言編程SWI的使用方法:
待續