SWI 软件
中断指令
.data
stack_start:
.space 128
stack_end:
.end
1、SWI指令
SWI指令的格式为:
SWI{条件} 24位的
立即数
SWI指令用于产生软件中断,以便
用户程序能调用操作系统的系统例程。操作系统在 SWI的
异常处理程序中提供相应的系统服务,指令中 24位的立即数指定用户程序调用系统例程的类型,相关参数通过
通用寄存器传递,当指令中 24位的立即数被忽略时,用户程序调用系统例程的类型由通用寄存器 R0的内容决定,同时,参数通过其他通用寄存器传递。
指令示例:
SWI 0x02 ;该指令调用操作系统编号位02的系统例程。
2、SWI指令用于产生软中断,从用户模式变换到管理模式,CPSR保存到管理模式的SPSR中. SWI{cond} immed_24 immed_24为软中断号(服务类型) 使用SWI指令时,通常使用以下两种方法进行传递参数,SWI 异常中断处理程序就可以提供相关的服务,这两种方法均是用户软件协定.SWI异常中断处理程序要通过读取引起软中断的SWI指令,以取得24位立即数. (1) 指令中的24位立即数指定了用户请求的服务类型,参数通过通用寄存器传递.(APCS) mov r0,#34 设置子功能号位34 SWI 12 调用12号软中断 (2) 指令中的24位立即数被忽略,用户请求的服务类型有寄存器RO的值决定,参数通过其他的通用寄存器传递. mov r0,#12 ;调用12号软中断 mov r1,#34 设置子功能号位34 SWI 0 在SWI异常中断处理程序中,取出SWI立即数的步骤为:首先确定引起软中断的SWI指令是ARM指令还是Thunb指令,这可通过对SPSR访问得到;然后取得该SWI指令的地址,这可通过访问LR寄存器得到;接着读出指令,分解出立即数.如如下程序: T_bit EQU 0X20 SWI_Handler:0x00000008(SWI中断的入口地址应该有一个BL指令对应这一块) STMFD SP!,{R0-R3,R12,LR};现场保护
MOV r1,sp;// 若SWI调用带参,将R1指向第一个参数 MRS R0,SPSR ;读取SPSR STMFD SP!,{R0};保存SPSR TST R0,#T_bit LDRNEH R0,[LR,#-2] 若是Thunb指令,读取指令码(16位) BICNE R0,#0XFF00;取得Thunb指令的8位立即数 LDREQ R0,[LR,#-4];若是ARM指令,读取指令码(32位) BICEQ R0,#0XFF000000 取得ARM指令的24位立即数 ;// r0 now contains SWI number
;// r1 now contains pointer to stacked registers BL SWI_Exception_Function // 调用C编写的SWI处理函数(这个应该是下面的红色的部分) LDMFD sp!, {r0}
MSR spsr_cf,r0 // spsr出栈
LDMFD sp!, {r0-r3, r12, pc}^ // 恢复现场 软件中断SWI的实现 在需要软件中断处调用 __SWI 0xNum Num为SWI中断处理模块的编号,见表SwiFunction 软件中断 SWI_Exception_Function
CMP R0, #12 R0中的SWI编号是否大于最大值
MOV r1,sp;// 若SWI调用带参,将R1指向第一个参数 MRS R0,SPSR ;读取SPSR STMFD SP!,{R0};保存SPSR TST R0,#T_bit LDRNEH R0,[LR,#-2] 若是Thunb指令,读取指令码(16位) BICNE R0,#0XFF00;取得Thunb指令的8位立即数 LDREQ R0,[LR,#-4];若是ARM指令,读取指令码(32位) BICEQ R0,#0XFF000000 取得ARM指令的24位立即数 ;// r0 now contains SWI number
;// r1 now contains pointer to stacked registers BL SWI_Exception_Function // 调用C编写的SWI处理函数(这个应该是下面的红色的部分) LDMFD sp!, {r0}
MSR spsr_cf,r0 // spsr出栈
LDMFD sp!, {r0-r3, r12, pc}^ // 恢复现场 软件中断SWI的实现 在需要软件中断处调用 __SWI 0xNum Num为SWI中断处理模块的编号,见表SwiFunction 软件中断 SWI_Exception_Function
CMP R0, #12 R0中的SWI编号是否大于最大值
3、代码:
.text
.global _start
_start:
.global _start
_start:
b reset @reset
nop @undefine instruction
b swi_handle @swi
nop @prefetch abort
nop @data abort
nop @reserved
nop @irq
nop @fiq
nop @undefine instruction
b swi_handle @swi
nop @prefetch abort
nop @data abort
nop @reserved
nop @irq
nop @fiq
reset:
@set svc mode stack
ldr sp, =stack_end
ldr sp, =stack_end
@set user mode
mrs r0, cpsr
bic r0, #0x1F
orr r0, #0x10
msr cpsr, r0
mrs r0, cpsr
bic r0, #0x1F
orr r0, #0x10
msr cpsr, r0
mov r0, #0x5
mov r1, #0x7
mov r2, #0x8
mov r1, #0x7
mov r2, #0x8
swi 1
add r0, r1, r2
nop
add r0, r1, r2
nop
swi_handle:
stmfd sp!, {r0-r12, lr}
@get swi number
sub r0, lr, #4
ldr r1, [r0]
bic r1, #0xFF000000 @中断向量地址=中断号*4
cmp r1, #1
bleq func
cmp r1, #1
beq break
stmfd sp!, {r0-r12, lr}
@get swi number
sub r0, lr, #4
ldr r1, [r0]
bic r1, #0xFF000000 @中断向量地址=中断号*4
cmp r1, #1
bleq func
cmp r1, #1
beq break
cmp r1, #2
bleq func
cmp r1, #2
beq break
nop
break:
ldmfd sp!, {r0-r12, pc}^
bleq func
cmp r1, #2
beq break
nop
break:
ldmfd sp!, {r0-r12, pc}^
func:
mov r0, #0xCC
mov pc, lr
mov r0, #0xCC
mov pc, lr
.data
stack_start:
.space 128
stack_end:
.end