网上找了一些解释:
;常量定义
USR_STACK_LENGTH EQU 64
SVC_STACK_LENGTH EQU 0
FIQ_STACK_LENGTH EQU 16
IRQ_STACK_LENGTH EQU 64
ABT_STACK_LENGTH EQU 0
UND_STACK_LENGTH EQU 0
;代码段
AREA EXAMPLE5,CODE,READONLY
ENTRY
CODE32
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
;当前的模式是管理模式,在调用子程序INITSTACK后会自动把返回地址存入LRsvc,但是会不会把CPSR也备份到SPSR中呢,经过实际
;验证是不能,保存CPSR的实现是在异常模式下实现的,在进入异常后,既要保存返回地址,又要保存CPSR到相应模式下的SPSR中,
;但是在子程序调用中只保存返回地址,不保存CPSR到相应模式的SPSR中
;芯片复位之后是管理模式,所以在调用子程序之前一直是管理模式
BL INITSTACK
;打开中断
MRS R0,CPSR
BIC R0,R0,#0X80
MSR CPSR_cxsf,R0
;切换到用户模式
MSR CPSR_c,#0XD0
MRS R0,CPSR
;切换到管理模式,切换成功了吗?为什么?
;因为我们的程序进入了用户模式,用户模式不是特权模式,根本没有权利去写CPSR,所以此处读出的CPSR仍然是用户模式
;用户模式下是不能为所欲为的,那么用户模式下如何进入特权模式呢?SWI(软件中断)可以使我们进入特权模式,在有操作系统的,
;可以通过调用SWI去切换模式
;现在应该理解在操作系统中,我们的应用程序运行在用户模式下,而操作系统运行在系统模式下
MSR CPSR_c,#0XDF
MRS R0,CPSR
B .
INITSTACK
MOV R0,LR ;为什么要在这里保存LR到R0?直接到子程序的最后直接MOV PC,LR不更省事吗?答案是,我们的程序在特权模式下,
;改变了存储器的模式,使我们的存储器进入了不同的模式,我们刚进入子程序时时管理模式,我们的返回地址就存储在管理模式下的LR,或者
;简写成LRsvc,但是你的子程序时改变存储器模式的,就有可能不是管理模式,那么,你如何返回地址呢?因为在那个模式下的LR并不是我们需要的
;返回地址,只有管理模式下的LR才是我们要的返回地址,所以这里他把地址存进了R0中,因为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 ;
;这个里面存放的是堆栈的指针,能看出是什么样的堆栈吗?
;没错是满递减堆栈,从"+"号看出来的,也就是指针指向堆栈空间地址的最高位置,当入栈时,地址是减少的,这个堆栈也是符合C语言的堆栈
;C语言的堆栈并不是什么堆栈都适合,是满递减的
STACKUSR DCD USRSTACKSPACE+(USR_STACK_LENGTH-1)*4
STACKSVC DCD SVCSTACKSPACE+(SVC_STACK_LENGTH-1)*4
STACKIRQ DCD IRQSTACKSPACE+(IRQ_STACK_LENGTH-1)*4
STACKFIQ DCD FIQSTACKSPACE+(FIQ_STACK_LENGTH-1)*4
STACKABT DCD ABTSTACKSPACE+(ABT_STACK_LENGTH-1)*4
STACKUND DCD UNDSTACKSPACE+(UND_STACK_LENGTH-1)*4
;下面是我们的堆栈空间,NOINIT表示没有初始化,ALIGN=2表示是4字节对齐的
AREA MYSPACE,DATA,NOINIT,ALIGN=2
USRSTACKSPACE SPACE USR_STACK_LENGTH*4
SVCSTACKSPACE SPACE SVC_STACK_LENGTH*4
IRQSTACKSPACE SPACE IRQ_STACK_LENGTH*4
FIQSTACKSPACE SPACE FIQ_STACK_LENGTH*4
ABTSTACKSPACE SPACE ABT_STACK_LENGTH*4
UNDSTACKSPACE SPACE UND_STACK_LENGTH*4
END
:intistack scv irq fiq abt und的sp有何关系
usr sp=svc sp
irq sp=usr sp+256
fiq sp=irq sp+64
abt sp=und sp=fiq sp
根据RW base设置的不同sp也不同,不过关系是这样的