目录
一.四种栈
1.满增栈:进栈(先移动指针再入栈,指针往地址增大的方向移动);出 栈(先出栈,栈指针往地址减小的地方移动)。
2.满减栈:进栈(先移动指针再入栈,指针往地址减小的方向移动);出栈(先出栈,栈指针往地址增大的地方移动)。
3.空增栈:进栈(先进栈,栈指针往地址增大的方向移动);出栈(先移动指针再出栈,栈指针往地址减小的方向移动
4.空减栈:进栈(先进栈,栈指针往地址减小的方向移动);出栈(先移动指针再出栈,栈指针往地址增大的方向移动)
二.LDM(多寄存器加载)和STM(多存储内存)
1.LDM指令格式
2.STM指令格式
3.LDM和STM多种模式
4.arm 满递减栈使用
1)STMFD 压栈操作
2)LDMFD 寄存器加载操作
3)实际场景分析
一.四种栈
考验大家理解能力的地方来了,专心点,嘿嘿!!
1.满增栈:进栈(先移动指针再入栈,指针往地址增大的方向移动);出 栈(先出栈,栈指针往地址减小的地方移动)。
2.满减栈:进栈(先移动指针再入栈,指针往地址减小的方向移动);出栈(先出栈,栈指针往地址增大的地方移动)。
3.空增栈:进栈(先进栈,栈指针往地址增大的方向移动);出栈(先移动指针再出栈,栈指针往地址减小的方向移动
4.空减栈:进栈(先进栈,栈指针往地址减小的方向移动);出栈(先移动指针再出栈,栈指针往地址增大的方向移动)
满栈:当堆栈指针总是指向最后压入堆栈的数据
空栈:当堆栈指针总是指向下一个将要放入数据的空位置
二.LDM(多寄存器加载)和STM(多存储内存)
1.LDM指令格式
LDM{cond}<模式> Rn{!},reglist{^} ;
reglist :表示寄存器列表,可以包含多个寄存器,它们使用“,”隔开,如{R1,R2,R6-R9},寄存器由小到大排列;
2.STM指令格式
STM{cond}<模式> Rn{!},reglist{^} ;
3.LDM和STM多种模式
模式 | 说明 | 模式 | 说明 |
IA | 每次传送后地址加4 | FD | 满递减堆栈 |
IB | 每次传送前地址加4 | ED | 空递减堆栈 |
DA | 每次传送后地址减4 | FA | 满递增堆栈 |
DB | 每次传送前地址减4 | EA | 空递增堆栈 |
数据块传送操作 | 堆栈操作 |
4.arm 满递减栈使用
ARM 微处理器支持这四种类型的堆栈工作方式,一般使用那种栈都是由编译器决定的,arm_gcc是使用的满递减栈,那么我们写.s也按照满递减栈才方便。
1)STMFD 压栈操作
STMFD SP!,{r0,r1,R2,r14}
满递减入栈,r13(lr)为基址地址:
这里需要注意,寄存器r0 r1 r2 r14,哪一个先压得栈?这里有一个总结:不管递减存还是递增存,寄存器组里的高位寄存器(r14)对应到高地址,低位寄存器(r0)对应到低地址。那么取也就好理解了,高地址得load到高位寄存器,低地址得内容load到低位寄存器。
2)LDMFD 寄存器加载操作
LDMFD SP!,{r0,r1,R2,r14}
3)实际场景分析
__swi_entry: //svc_mode
stmfd sp!, lr; //保存管理模式下得lr save svc_mod:lr
stmfd sp!,{r0-lr}^; //保存用户模式下得寄存器 usr_mode:r0-r14
.
.
.
bl ker_syscall; //系统调用
.
.
.
//这里可能产生调度
ldmfd sp!,{r0-lr}^; //调度回来,为用户态寄存器恢复线程得现场。
ldmfd sp!,{pc}^; //修改pc指针,并且改CRSP得状态。
1). "!":
表示在操作结束后,将最后的地址写回Rn中;
2). "^":
可选后缀,它的作用就是在IRQ FIQ ABT UNDEF这些模式下,直接可以获取到user的r0-r14寄存器,而不用切模式。通常用作异常进入的压栈和异常退出时的恢复寄存器。(不能在USR模式和SYS模式下使用该符号,因为user和sys模式是公用r0-r14的,所以这两个模式下都不能用^。)
LDM寄存器列表如果包含R15(PC)时,那么除了正常的多寄存器传送外,还将SPSR也复制到CPSR中。这用于异常处理返回,仅在异常模式下使用。