分类: 嵌入式
2013-02-26 14:44:20
点击(此处)折叠或打开
- #define S_FRAME_SIZE 72
- .macro bad_save_user_regs
- sub sp, sp, #S_FRAME_SIZE
- stmia sp, {r0 - r12} @ Calling r0-r12
- ldr r2, _armboot_start
- .endm
.macro和后面的.endm相对应,其语法是:
Figure 1.12. macro的语法
所以,此处就相当于一个无参数的宏bad_save_user_regs,也就相当于一个函数了。
即
sp = sp- S_FRAME_SIZE = sp - 72
stmia的语法为:
Figure 1.13. LDM/STM的语法
其中,条件域的具体含义如下:
Figure 1.14. 条件码的含义
更具体的含义:
六、批量数据加载/存储指令ARM微处理器所支持批量数据加载/存储指令可以一次在一片连续的存储器单元和多个寄存器之间传送数据,批量加载指令用于将一片连续的存储器中的数据传送到多个寄存器,批量数据存储指令则完成相反的操作。常用的加载存储指令如下:
LDM(或STM)指令
LDM(或STM)指令的格式为:
LDM(或STM){条件}{类型} 基址寄存器{!},寄存器列表{∧}
LDM(或STM)指令用于从由基址寄存器所指示的一片连续存储器到寄存器列表所指示的多个寄存器之间传送数据,该指令的常见用途是将多个寄存器的内容入栈或出栈。
其中,{类型}为以下几种情况:
IA 每次传送后地址加1;
IB 每次传送前地址加1;
DA 每次传送后地址减1;
DB 每次传送前地址减1;
FD 满递减堆栈;
ED 空递减堆栈;
FA 满递增堆栈;
EA 空递增堆栈;
{!}为可选后缀,若选用该后缀,则当数据传送完毕之后,将最后的地址写入基址寄存器,否则基址寄存器的内容不改变。
基址寄存器不允许为R15,寄存器列表可以为R0~R15的任意组合。
{∧}为可选后缀,当指令为LDM且寄存器列表中包含R15,选用该后缀时表示:除了正常的数据传送之外,还将SPSR复制到CPSR。同时,该后缀还表示传入或传出的是用户模式下的寄存器,而不是当前模式下的寄存器。
指令示例:
STMFD R13!,{R0,R4-R12,LR} ;将寄存器列表中的寄存器(R0,R4到R12,LR)存入堆栈。
LDMFD R13!,{R0,R4-R12,PC} ;将堆栈内容恢复到寄存器(R0,R4到R12,LR)。
所以,此行的含义是,
将r0到r12的值,一个个地传送到对应的地址上,基地址是sp的值,传完一个,sp的值加4,一直到传送完为止。
此处,可见,前面那行代码:
sp = sp - 72
就是为此处传送r0到r12,共13个寄存器,地址空间需要13*4=72个字节,
即前面sp减去72,就是为了腾出空间,留此处将r0到r12的值,放到对应的位置的。
此处的含义就是,将_armboot_start中的值,参考前面内容,即为_start,
而_start的值:
从 Nor Flash启动时:_stat=0
relocate代码之后为:_start=TEXT_BASE=0x33D00000
此处是已经relocate代码了,所以应该理解为后者,即_start=0x33D00000
所以:
r2=0x33D00000