6.2.1
异常中断处理程序的方法种类及其介绍
1.SWI 异常中断处理程序的实现
在 SWI 指令中包括一个 24 位的立即数,该立即数指示了用户请求的特定的 SWI 功能。在
SWI 异常中断处理程序要读取该 24 位的立即数,这涉及到 SWI异常模式下对寄存器 LR的读
取,并且要从存储器读取该 SWI 指令。这样需要使用汇编程序来实现。通常 SWI异常中断处
理程序分为两级:第 1 级 SWI 异常中断处理程序为汇编,用于确定 SWI 指令中的 24 位的立
即数;第 2级 SWI 异常中断处理程序具体实现 SWI 的各个功能,它可以是汇编程序,也可以
时 C 程序,下面我们分别介绍这两级。
● SWI 异常中断调用
① 在特权模式下调用 SWI
执行 SWI 指令后,系统将会把 CPSR 寄存器的内容保存到寄存器 SPSR_SVC 中,
将返回地址保存到寄存器 LR_svc 中。这样如果执行 SWI 指令时,系统已经处于
特权模式下,这时寄存器 SPSR_svc 和寄存器 LR_svc 中的内容就会被破坏。因
此如果在特权模式下调用 SWI 功能,比如在一个 SWI 异常中断处理程序中执行
SWI指令,就必须将原始的寄存器SPSR_svc和寄存器LR_svc值保存在数据栈中。
程序6.1说明在SWI中断处理程序中如何保存寄存器SPSR_svc和寄存器LR_svc
值。
程序 6.1 在SWI 中断处理程序中保存寄存器 SPSR_svc 和寄存器 LR_svc 值
;保存寄存器,包括寄存器 lr_svc
STMFD sp!(r0-r3,r12,lr)
;保存 SPSR_svc
MOV r1,sp
MRS r0,spsr
STMFD sp!,(r0)
;读取SWI指令
LDR r0,(lr,#4)
;计算其中的 24 位立即数,并将其放入寄存器 R0 中
BIC r0,r0.#0xff000000
;调用C_SWI_Handler 完成相应的 SWI 功能
BL C_SWI_Handler
;恢复SPSR_svc 的值
LDMFD sp!,(r0)
MSB spsr_cf,r0
;恢复其他寄存器,包括寄存器 LR_svc
LDMFD sp!,(r0-r3,r12,pc)^
② 从应用程序中调用 SWI
这里分两种情况考虑从应用程序中调用特定的 SWI 功能:一种考虑使用汇编指
令调用特定的 SWI 功能;一种考虑从 C 语言程序中调用特定的 SWI 功能。
使用汇编指令调用特定的 SWI 功能比较简单,将需要的参数按照 ATPCS 的要求
放在相应的寄存器中,然后在指令 SWI 中指定相应 24 位立即数即可。下面的例
子中,SWI 中断处理程序需要的参数放在寄存器 R0 中,这里该参数为 100,然
后调用功能号为 0x0 的SWI 功能调用。
MOV R0,#100
SWI 0x0
从 C 语言程序中调用特定的 SWI 功能比较复杂,因为这时需要将一个 C 程序的
子程序调用映射到一个 SWI 异常中断处理程序。这些被映射的 C 语言子程序使
用编译器伪操作__SWI 来声明。如果该子程序需要的参数和返回的结果只使用寄
存器 R0~R3,则该 SWI 可以被编译成 inline 的,不需要使用子程序调用过程。
否则必须告诉编译器通过结构数据类型来返回参数,这时需要使用编译器伪操
作_value_in_reg 声明该C 语言子程序。
下面通过一个完整的例子来说明如何从 C 程序中调用特定的 SWI 功能,该例子
是 ARM 公司的 ADS1.2 中所带的。该例子提供的 4 个SWI 功能调用,功能号分别
为 0x0,0x1,0x2,0x3。其中 SWI 0x0及 SWI 0x1 使用两个整形的输入参数,并返
回一个结果值,SWI 0x2使用 4 个输入参数,并返回一个结果值;SWI 0x3 使用
4 个输入参数,并返回 4个结果值。
整个 SWI 异常中断处理程序分为两级结构。第 1 级的 SWI 异常中断处理程序是
汇编程序 SWI_HANDLER,它读取 SWI 指令中的 24 位立即数,然后调用第 2 个级
SWI 异常中断处理程序 C_SWI_HANDLER来实现具体的 SWI 功能。第 2 级SWI异常
中谷底你处理程序 C_SWI_HANDLER 为 C 语言程序。其中实现了功能号分别为
0x0,0x1,0x2,0x3的 SWI功能调用。
主程序中的子程序 multiply_two()对应着 SWI 0x0;add_two()对应着
0x1;add_multiply_two()对应着 0x2;many_operations()对应着 SWI 0x3。
Many_operations()返回 4 个结果,使用编译器伪操作_valuc_in_reg 声明。4
个子程序都使用编译器伪操作__SWI来声明。主程序使用 lnstall_Handler()来
安装该 SWI异常中断处理程序,lnstall_Handler()在前面已经有详细的介绍。
整个代码如程序 6.2 所示。
程序 6.2 从C 程序中调用特定的 SWI功能
__swi(0) int multiply_two (int,int);
__swi(1) int add_two (int,int);
__swi(2) int add_multiply_two (int ,int ,int ,int );