在线咨询
eetop公众号 创芯大讲堂 创芯人才网
切换到宽版

EETOP 创芯网论坛 (原名:电子顶级开发网)

手机号码,快捷登录

手机号码,快捷登录

找回密码

  登录   注册  

快捷导航
搜帖子
芯片精品文章合集(500篇!) 创芯人才网--重磅上线啦!
查看: 5210|回复: 3

SWI指令---软件中断实例详解

[复制链接]
发表于 2009-3-17 22:22:31 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?注册

x
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寄存器用来保存子程序的返回地址。当执行BLBLX指令进行子程序调用时,子程序的返回地址被放置在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的使用方法:
        待续
 楼主| 发表于 2009-3-17 22:25:17 | 显示全部楼层
怎么排版还是有问题呢.      ;这里是注释,怎么都另起一行了
 楼主| 发表于 2012-10-20 19:59:39 | 显示全部楼层
没人关注
发表于 2012-10-22 22:52:46 | 显示全部楼层
额,看不太懂啊,还是帮你顶一下
您需要登录后才可以回帖 登录 | 注册

本版积分规则

关闭

站长推荐 上一条 /2 下一条


小黑屋| 手机版| 关于我们| 联系我们| 在线咨询| 隐私声明| EETOP 创芯网
( 京ICP备:10050787号 京公网安备:11010502037710 )

GMT+8, 2024-11-26 11:44 , Processed in 0.017994 second(s), 9 queries , Gzip On, Redis On.

eetop公众号 创芯大讲堂 创芯人才网
快速回复 返回顶部 返回列表