一步一步写ARM汇编(五)

软中断SWI

在Linux程序中,用户程序是不能访问调用系统资源,但是可以通过系统调用或异常访问系统资源。那usr模式下是如何实现系统调用呢? 答案是通过SWI + 中断号。每一个系统调用对应一个SWI + 中断号,在arch/arm/kernel/entry-common.S下保存所有的SWI+ 中断号对应的系统调用。

在usr模式下,调用swi时cpu会跳到Supervisor工作模式下,在这个过程中会执行异常处理的所有操作,这个过程参考博文:arm异常处理流程。

示例代码如下:

       areafirst, code, readonly

       code32

       entry

; 定义的异常向量表

vector

       breset_handler  ; 跳转到 reset_handler

       nop

       bswi_handler ; SWI 指令异常跳转的地址

       nop

       nop

       nop

       nop

       nop

swi_handler

       ;swi handler code

       ;异常处理首先要压栈保存处理器现场

      

       mrsr0, cpsr

       movr0, #1

      mov r1, #2

      

       movspc, lr     ; lr > pc 且 spsr -> cpsr返回 SVC -> USER

reset_handler

       ;初始化 SVC 模式堆栈

       ldrsp, =0x40002000

       ;修改当前的模式从SVC模式改变为USER模式

       mrsr0, cpsr

       bicr0, r0, #0x1f

       orrr0, r0, #0x10

       msrcpsr_c, r0

    ;初始化 USER 模式堆栈

       ldrsp, =0x40001000

       movr0, #1   

      

       ;USER SWI

       swi5  ; open APP USER 这条语句由用户程序自己出发异常  

       ;观察并记录对比指令执行前后的 PC LR CPSR SPSR SP的变化  

       addr1, r0, r0

stop

       bstop

       end

cpu在swi 5 后异常处理流程由硬件自己完成,这个过程如下图:

注1:如果同时返回到异常发生的位置,同时又能切换模式只能使用如下指令:

  movs pc,lr

注2:进入swi异常,如何得到 swi 指令后面跟的那个参数?

所有的系统调用,都是依赖swi指令,操作系统提前给所有的系统调用编号

思路:swi异常发生的时候,会把该指令的下一条指令的地址给 svc模式的lr,

通过lr可以找到swi的地址,

ldr r0, [lr,#-4]   ; 获得SWI指令的机器码

bic r0, r0,#0xff000000  ; 通过机器码获得SWI NUMBER

 

 


猜你喜欢

转载自blog.csdn.net/weixin_42048417/article/details/80601292
今日推荐