一、 栈是一段CPU自动分配的空间 SP寄存器(栈寄存器)指向内存中当前栈的位置 栈的特性(先进后出) 1、空增栈EA(empty ascending)表示该栈指向的空间是一个空的空间可以往里面放数据然后再往高地址自增一位 2空减栈ED(full decending) 表示该栈指向的空间是一个空的空间可以往里面放数据,然后指针往低地址反向自减一位 3、满增栈FA(full ascending)表示该栈指向的空间是一个已经放了东西的空间,需要先向高地址自增一位再来存放数据 4、满减栈FD(full decending)表示该栈指向的空间是一个已经放了东西的空间,需要先向低地址自减一位再来存放数据
@@@@ARM 用的为满减栈所以是自减才往低地址放数据 @@读写都加后缀FD ,@你加其他的处理器也会帮你改成FD,因为它只支持FD @在内存读写中STM /LDM有四种寻址方式 @ARM在压栈和出栈的时候风别对应STMDB(decrease before)/LDMIA(increase after),我们在写的时候统一写成STMFD/LDMFD就对应的相应的压栈的弹栈。 二、SP(栈指针的应用) 1、叶子函数的调用过程(所调用的函数为叶子函数即这个函数里面不调用其他函数) MOV SP, #0X40000020 MAIN: MOV R1, #7 MOV R2, #8 BL FUNC ADD R3, R1, R2 B STOP FUNC: @@压栈保护现场 @STMFD SP! ,{R1,R2} MOV R1, #10 MOV R2, #20 MUL R3, R1, R2 @@出栈保护现场 @LDMFD SP!, {R1,R2} MOV PC, LR @@这个程序的运行结果很明显乘法子函数的结果正确而寄存器R1/R2的值被覆盖所以ADD的结果错误 @@那我们要俩个结果都正确就要用到栈指针SP把数据R1,R2的值压栈,算完乘法之后出栈给R1/R2 @这个栈的应用为保护之前的数据 2、 对于非叶子函数(即这个函数不是叶子函数,主函数调用的函数里面也调用了其他函数) @@我们知道LR存的是BL跳转之前的下一条语句的地址 @@但是我跳了俩次LR的值肯定也是会被覆盖 MOV SP, #0X40000020 MAIN: MOV R1, #7 MOV R2, #8 BL FUNC1 ADD R3, R1, R2 B STOP FUNC1: @@压栈保护现场 STMFD SP! ,{R1,R2} MOV R1, #10 MOV R2, #20 BL FUNC2 MUL R3, R1, R2 @@出栈保护现场 LDMFD SP!, {R1,R2} MOV PC, LR FUNC2: @@压栈保护现场 STMFD SP! ,{R1,R2,LR} MOV R1, #10 MOV R2, #20 SUB R3, R1, R2 @@出栈保护现场 LDMFD SP!, {R1,R2,LR} MOV PC, LR @@所以我们把LR的值一起压到栈里面 @@这样我们所有函数的值都是正确的结果
STOP: B STOP
.end @汇编程序结束
|