原创 ARM汇编的SWI指令软中断

2006-10-12 13:42 9316 7 8 分类: MCU/ 嵌入式

从下面的一个ARM 汇编小程序要弄懂的以下三个问题:


1).在ARM状态转到THUNB状态和BX的应用


2).汇编的架构


3).SWI指令的使用


    AREA    ADDREG,CODE,READONLY


     ENTRY


MAIN


      ADR  r0,ThunbProg + 1  ;(为什么要加1呢?因为BX指令跳转到指定的地址执行程序   时,   若   (BX{cond}  Rm)Rm的位[0]为1,则跳转时自动将CPSR中的标志T置位即把目标 代码解释为 Thunb代码)


        BX    r0


       CODE16


ThunbProg


       mov r2,#2


      mov r3,#3


     add r2,r2,r3


    ADR r0,ARMProg


    BX  ro


    CODE32


ARMProg


     mov r4,#4


    mov r5,#5


    add  r4,r4,r5


             stop   mov r0,#0x18


              LDR  r1,=0x20026


             SWI   0x123456


             END


SWI--软中断指令:


SWI指令用于产生软中断,从拥护模式变换到管理模式,CPSR保存到管理模式的SPSR中.


 SWI{cond}      immed_24      ;immed_24为软中断号(服务类型)


使用SWI指令时,通常使用以下两种方法进行传递参数,SWI 异常中断处理程序就可以提供相关的服务,这两种方法均是用户软件协定.SWI异常中断处理程序要通过读取引起软中断的SWI指令,以取得24位立即数.


(1) 指令中的24位立即数指定了用户请求的服务类型,参数通过通用寄存器传递.


 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


                STMFD      SP!,{R0-R3,R12,LR}                  ;现场保护


               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位立即数


   ....


   LDMFD          SP!,{R0-R3,R12,PC}^    ;SWI异常中断返回


    


Thu Oct 12 2006


 


软件中断SWI的实现


在需要软件中断处调用


__SWI  0xNum           ;Num为SWI中断处理模块的编号,见表SwiFunction


;软件中断
SoftwareInterrupt
        CMP     R0, #12                         ;R0中的SWI编号是否大于最大值


/* 下面这句语句把 (LDRLO地址+ 8 + R0*4) 的地址装载到PC寄存器,举例如果上面的 Num="1",也就是R0 = 1, 假设LDRLO这条指令的地址是0x00008000,那么根据ARM体系的2级流水线 PC寄存器里指向是下两条指令 于是PC = 0x00008008  也就是伪指令DCD     TASK_SW 声明的标号TASK_SW  的地址,注意DCD     TASK_SW 这条指令本身不是ARM能执行的指令,也不会占有地址,这条指令靠汇编器汇编成可执行代码,它的意义就是声明 TASK_SW的地址,  , [PC, R0, LSL #2] 这个寻址方式就是 PC + R0的值左移2位的值( 0x01<<2  => 0x04 ),这样PC的值就是0x0000800C, 即ENTER_CRITICAL的地址于是ARM执行该标号下的任务 */


        LDRLO   PC, [PC, R0, LSL #2]        
        MOVS    PC, LR


SwiFunction
        DCD     TASK_SW                ;0
        DCD     ENTER_CRITICAL         ;1
        DCD     EXIT_CRITICAL            ;2
        DCD     ISRBegin                 ;3
        DCD     ChangeToSYSMode         ;4
        DCD     ChangeToUSRMode         ;5
        DCD     __OSStartHighRdy        ;6
        DCD     TaskIsARM               ;7
        DCD     TaskIsTHUMB             ;8
        DCD     OSISRNeedSwap           ;9
        DCD     GetOSFunctionAddr       ;10
        DCD     GetUsrFunctionAddr      ;11


TASK_SW
        MRS     R3, SPSR                        ;保存任务的CPSR
        MOV     R2, LR                          ;保存任务的PC
       
        MSR     CPSR_c, #(NoInt | SYS32Mode)    ;切换到系统模式
        STMFD   SP!, {R2}                       ;保存PC到堆栈
        STMFD   SP!, {R0-R12, LR}               ;保存R0-R12,LR到堆栈
                                                ;因为R0~R3没有保存有用数据,所以可以这样做
        B       OSIntCtxSw_0                    ;真正进行任务切换


ENTER_CRITICAL
                                                ;OsEnterSum++
        LDR     R1, =OsEnterSum
        LDRB    R2, [R1]
        ADD     R2, R2, #1
        STRB    R2, [R1]
                                                ;关中断
        MRS     R0, SPSR
        ORR     R0, R0, #NoInt
        MSR     SPSR_c, R0
        MOVS    PC, LR

PARTNER CONTENT

文章评论1条评论)

登录后参与讨论

用户1240011 2006-11-16 15:05

问下,在什么情况下用到软件中断,软件中断有什么用?
相关推荐阅读
用户1280303 2008-07-24 14:58
nand flash ECC 算法
ECC简介  由于NAND Flash的工艺不能保证NAND的Memory Array在其生命周期中保持性能的可靠,因此,在NAND的生产中及使用过程中会产生坏块。为了检测数据的可靠性,在应用NAND...
用户1280303 2008-06-06 09:25
bootload与linux以及根文件系统启动参数传替
lefthand0504-05-08, 16:01嵌入式BootLoader技术内幕(一)作者:詹荣开 (zhanrk@sohu.com) 本文选自:IBM DW 2003年12月30日 本文详细地介...
用户1280303 2007-10-29 18:22
从NANDA闪存中启动u-boot
从NAND闪存中启动U-BOOT的设计2007-05-12 07:48U-BOOT 支持ARM、 PowerPC等多种架构的处理器,也支持Linux、NetBSD和VxWorks等多种操作系统,主要用...
用户1280303 2007-10-29 18:11
增加u-boot命令的编程方法
6.2.5  添加U-Boot命令U-Boot的命令为用户提供了交互功能,并且已经实现了几十个常用的命令。如果开发板需要很特殊的操作,可以添加新的U-Boot命令。U-Boot的每一个命令都是通过U_...
用户1280303 2007-10-29 14:39
mkimage使用详解
uboot源代码的tools/目录下有mkimage工具,这个工具可以用来制作不压缩或者压缩的多种可启动映象文件。mkimage在制作映象文件的时候,是在原来的可执行映象文件的前面加上一个0x40字节...
用户1280303 2007-09-22 11:19
linux 常用指令
linux目录架构/ 根目录/bin 常用的命令 binary file 的目錄/boot 存放系统启动时必须读取的档案,包括核心 (kernel) 在内 /boot/grub/...
EE直播间
更多
我要评论
1
7
关闭 站长推荐上一条 /3 下一条