【ARM】微处理器工作模式

收获

  1. SPACEDCD 的区别在于:

    SPACE 申请一片内存空间(以字节为单位申请),但不赋初值

    DCD 申请一个(32bit)的内存空间,并赋初值

  2. 对于 32 位的 ARM,一个32 bit = 4 Byte

  3. 代码中的

     UsrStackSpace   SPACE   USR_STACK_LEGTH*4
    

    这里的 4*4 就是由于 SPACE 是以字节为单位分配空间,而我们需要的是以为单位的堆栈空间

  4. 对于代码中的

     StackUsr    DCD    UsrStackSpace+(USR_STACK_LEGTH-1)*4
    

    可以这样理解: UsrStackSpace 是标号,相当于地址,实际上就是在 UsrStackSpace SPACE USR_STACK_LEGTH*4 这个语句给分配的空间的首地址,UsrStackSpace+(USR_STACK_LEGTH-1)*4是这个地址空间的结束地址,将 StackUsr 指向这个地址,作为栈顶

每种模式堆栈位置

【ARM】微处理器工作模式

代码

;ARM 微控制器工作模式实验的参考程序如下:
;定义堆栈的大小
USR_STACK_LEGTH    EQU  64 ; 定义用户模式堆栈长度为 64 字
SVC_STACK_LEGTH    EQU   0
FIQ_STACK_LEGTH    EQU  16
IRQ_STACK_LEGTH    EQU  64
ABT_STACK_LEGTH    EQU   0
UND_STACK_LEGTH    EQU   0

        AREA Example3,CODE,READONLY ;声明代码段Example3
        ENTRY ;标识程序入口
        CODE32 ;声明32 位ARM 指令
START   MOV R0,#0
        MOV R1,#1
        MOV R2,#2
        MOV R3,#3
        MOV R4,#4
        MOV R5,#5
        MOV R6,#6
        MOV R7,#7
        MOV R8,#8
        MOV R9,#9
        MOV R10,#10
        MOV R11,#11
        MOV R12,#12

        BL InitStack                ;初始化各模式下的堆栈指针
        ;打开IRQ 中断(将CPSR 寄存器的1 位清零)
        MRS  R0,CPSR            ;R0 <-CPSR
        BIC   R0,R0,#0X80 ; 1000 0000  I 置 0,打开 IRQ 中断
        MSR  CPSR_cxsf,R0       ;CPSR <-R0

        ;切换到用户模式
        MSR CPSR_c,#0xd0
        MRS R0,CPSR

        ;切换到管理模式
        MSR CPSR_c,#0xd3 ; 不能成功切换到管理模式,因为不能从用户模式直接切换到其他模式,可以使用 SWI 指令切换到管理模式
        MRS R0,CPSR

HALT    B    HALT

;名称:InitStack
;功能:堆栈初始化,即初始化各模式下下的堆栈指针。
;入口参数:无
;出口参数:无
;说明:在特权模式下调用此子程序,比如复位后的管理模式
InitStack
        MOV R0,LR                ;R0 <-LR ,因为各种模式下R0 是相同的
        ;设置管理模式堆栈
        MSR CPSR_c,#0xd3
        LDR SP,StackSvc
        ;设置中断模式堆栈
        MSR CPSR_c,#0xd2
        LDR SP,StackIrq

        ;设置快速中断模式堆栈
        MSR CPSR_c,#0xd1
        LDR SP,StackFiq

        ;设置中止模式堆栈
        MSR CPSR_c,#0xd7
        LDR SP,StackAbt

        ;设置为定义模式堆栈
        MSR CPSR_c,#0xdb
        LDR SP,StackUnd

        ;设置系统模式堆栈
        MSR CPSR_c,#0xdf
        LDR SP,StackUsr
        MOV PC,R0

StackUsr    DCD    UsrStackSpace+(USR_STACK_LEGTH-1)*4 ; 定义一个字的空间,这个字的内容是一个递减堆栈的首地址
StackSvc    DCD    SvcStackSpace+(SVC_STACK_LEGTH-1)*4
StackIrq    DCD    IrqStackSpace+(IRQ_STACK_LEGTH-1)*4
StackFiq    DCD    FiqStackSpace+(FIQ_STACK_LEGTH-1)*4
StackAbt    DCD    AbtStackSpace+(ABT_STACK_LEGTH-1)*4
StackUnd    DCD    UndStackSpace+(UND_STACK_LEGTH-1)*4

;分配堆栈空间
        AREA   MyStacks,  DATA, NOINIT, ALIGN=2
UsrStackSpace   SPACE   USR_STACK_LEGTH*4 ; 为用户模式分配一个64字的堆栈空间
SvcStackSpace   SPACE   SVC_STACK_LEGTH*4
IrqStackSpace   SPACE   IRQ_STACK_LEGTH*4
FiqStackSpace   SPACE   FIQ_STACK_LEGTH*4
AbtStackSpace   SPACE   ABT_STACK_LEGTH*4
UndStackSpace   SPACE   UND_STACK_LEGTH*4