ARM指令栈操作&软中断

本文详细介绍了ARM处理器中的栈操作,包括PUSH和POP,以及满栈和空栈的两种实现方式。此外,文章还探讨了软中断的概念,如何通过SWI指令触发,并详细阐述了软中断的执行流程,包括模式切换、寄存器保存与恢复等关键步骤。最后,提供了一个示例代码来展示满栈降序式内存栈的软中断实现。
摘要由CSDN通过智能技术生成

书接上文:浅谈ARM处理器工作模式&内核寄存器&指令语句

栈操作

接上文LDM/STM指令部分提到的栈操作,栈操作主要分为两种:

  1. PUSH:压栈
  2. POP:弹栈

栈操作时又分为两种实现方式:

  1. 满栈:SP所指的地址有数据
  2. 空栈:SP所指的地址无数据

以下为不同的栈类型对应的栈操作指令:

栈类型压栈弹栈
满栈降序STMFD(STMDB,先减少,再操作)LDMFD(LDMIA,先操作,再增加)
满栈增序STMFA(STMIB,先增加,再操作)LDMFA(LDMDA,先操作,再减少)
空栈降序STMED(STMDA,先操作,后减少)LDMED(LDMIB,先操作,再增加)
空栈增序STMEA(SRMIA,先操作,后增加)LDMEA(LDMDB,先减少,再操作)

软中断

通过汇编指令软件实现中断称为软中断。通过软中段机制,运行在用户模式下的应用程序,可请求操作系统执行一系列的特权操作。

为了参考,我们再次将上一篇文章中的ARM内核寄存器组列表罗列于此:

寄存器
R0
R1
R2
R3
R4
R5
R6
R7
R8
R9
R10
R11
R12
SP(R13)
LR(R14)
PC(R15)
CPSR
SPSR
ELR_hyp
模式User/SystemHypSupervisorAbortUndefMoniterIRQFIQ

软中断命令

SWI{(cond)} <SWI NUMBER>

SWI指令可以产生一个异常陷阱,从而跳转到异常向量表的SWI_handler,SWI NUMBER为中断号。

^符号可以在弹栈的同时将SPSR的值赋给CPSR。

软中断原理

软中断需要实现模式改变后寄存器现场的保存,和模式恢复后寄存器现场的恢复,分为以下几步:

  1. 初始化特殊模式的内存栈,将特殊模式的内存栈首地址赋值给特殊模式的SP寄存器,此处我们赋值给软中断模式的SP寄存器。
  2. SWI指令产生异常陷阱,同时生成中断号。
  3. 跳转入异常向量表,再由异常向量表跳转至代码段对应的指令段。
  4. 将之前公用寄存器现场保存压入特殊模式的内存栈中,因为这些公用的寄存器在特殊模式下也会使用,会造成之前模式的寄存器现场破坏。
  5. 获取中断号。
  6. 跳转至对应中断号的指令代码
  7. 中断程序执行完毕,将特殊模式内存栈中存储的上一模式的寄存器现场恢复,即弹栈恢复。
SVC USER 获取SVC内存栈首地址 内存栈首地址赋值给SVC:SP寄存器 SWI产生陷阱 异常向量表,模式变为SVC 将公用寄存器压入SVC:SP所指向的SVC内存栈 获取中断号 进入中断号对应的中断程序 将SVC内存栈的寄存器值弹出到公用寄存器 SPSR赋值给CPSR恢复USER模式 SVC USER

以上为软中断实现的基本步骤,以下为满栈降序式的内存栈为例,进行的软中断实现:

.text
.global _start
_start:
@0
	b reset
@4
	b undef_handler
@8
	b swi_handler @进入异常向量表后,工作模式由user转为svc,从异常向量表跳转到软中断代码段
	b perfetch_handler
	b databort_handler
	nop
	b irq_handler
	b fiq_handler
	

reset:
	@将SVC模式下的栈内存首地址赋给SVC模式的SP寄存器
	ldr r0,=svc_stack
	add r0,#128 @指到栈底
	mov sp,r0	@初始化svc的sp
	
	mrs r0,cpsr
	bic r0,#3
	msr cpsr,r0 @进入user模式
	
	@将USER模式下的栈内存首地址赋给USER模式的SP寄存器
	ldr r0,=user_stack
	add r0,#128 @指到栈底
	mov sp,r0	@初始化user的sp
	
	mov r1,#11
	mov r2,#12
	mov r3,#13
	
	@swi跳转到异常向量表
	swi 10
	nop
	nop
	nop
	
	b .
undef_handler:
swi_handler:
	@将r0~r12,lr寄存器的数据压入svc模式下的内存栈中
	@保护user模式的寄存器现场
	stmfd sp!,{r0-r12,lr} 
	mov r1,#1
	mov r2,#2
	mov r3,#3
	
	@取当前模式的中断号
	sub lr,#4
	ldr r4,[lr]
	bic r4,#0xff000000
	cmp r4,#10
	beq swi_10 @若中断号为10跳转
	cmp r4,#1
	b swi_end
	
	nop
	nop
	nop
	
	movs pc,lr	@跳转回reset

swi_10:
	@将svc模式下内存栈中的数据弹栈到寄存器r0~r12,lr
	@^ 出栈的同时将当前的spsr->cpsr,恢复模式改变前cpsr的寄存器状态
	@将中断前user模式下的寄存器现场恢复
	@将lr的值赋给pc,也就是将程序重新指向中断事件断点处。
	ldmfd sp!,{r0-r12,pc}^ 
swi_end:
	movs r0,#0
	ldmfd sp!,{r0-r12,pc}^	@^ 出栈的同时将当前的spsr->cpsr
perfetch_handler:
databort_handler:
irq_handler:
fiq_handler:
	
.data
svc_stack: .space 128
user_stack: .space 128
.end
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值