/*
* 2018/12/17 20:48 qing
*/
/*
* 栈
*/
在高级语言里面,操作的是变量。在ARM汇编里面,操作的是寄存器(register)、内存和栈(stack)。
一般来说,栈是一片在程序/进程中的内存区域。这部分内存是在进程创建的时候被创建的。
我们利用栈来存储一些临时数据比如说函数的局部变量,环境变量等
栈的增长,即当我们把32位的数据放到栈上时候它的变化。栈可以向上增长(当栈的实现是负向增长时),或者向下增长(当栈的实现是正向增长时)。
具体的关于下一个32位的数据被放到哪里是由栈指针来决定的,更精确的说是由SP寄存器决定。不过这里面所指向的位置,
可能是当前(也就是上一次)存储的数据,也可能是下一次存储时的位置。如果SP当前指向上一次存放的数据在栈中的位置(满栈实现),
SP将会递减(降序栈)或者递增(升序栈),然后再对指向的内容进行操作。而如果SP指向的是下一次要操作的数据的空闲位置(空栈实现),
数据会先被存放,而后SP会被递减(降序栈)或递增(升序栈)。
栈类型 压栈(存储) 弹栈(加载)
满栈降序(FD,Full descending) STMFD(等价于STMDB,操作之前递减) LDMFD(等价于LDM,操作之后递加)
满栈增序(FA,Full ascending) STMFA(等价于STMIB,操作之前递加) LDMFA(等价于LDMDA,操作之后递减)
空栈降序(ED,Empty descending) STMED(等价于STMDA,操作之后递减) LDMED(等价于LDMIB,操作之前递加)
空栈增序(EA,Empty ascending) STMEA(等价于STM,操作之后递加) LDMEA(等价于LDMDB,操作之前递减)
栈其实也是一片内存区域,但它具有内存的特点:先进后出。ARM的栈是满递减(Full Descending)的,向下增长,也就是开口朝下,
新的变量被存放到栈底的位置;越靠近栈底,内存地址越小。
一个名为stack pointer(简称SP)的寄存器保存栈的栈底地址,称为栈地址;
/*
* 栈帧
*/
即每个函数所使用的栈空间是一个栈帧,所有的栈帧就组成了这个进程完整的栈。
fp就是栈基址寄存器,指向当前函数栈帧的栈底,sp则指向当前函数栈帧的栈顶。通过sp和fp所指出的栈帧可以恢复出母函数的栈帧
/*
* 出入栈的顺序
*/
在ARM指令系统中是地址递减栈,入栈操作的参数入栈顺序是从右到左依次入栈,而参数的出栈顺序则是从左到右的你操作。包括push/pop和LDMFD/STMFD等。
push {fp, sp, lr, pc} @ pc被首先入栈存在高地址,从右到左依次入栈,fp存在低地址
参数是通过寄存器进行传值(ARM上是通过r0,r1,r2,r3),而当参数多于4个时,多出的参数压入栈中进行传递(其实在函数调用过程中也会把
r0,r1,r2,r3传递的参数压入栈)
/*
* 满堆栈与空堆栈简明理解
*/
“满堆栈”就是一个满的堆栈,不能再存储数据了;而”空堆栈”就是一个空的堆栈,没有被使用的堆栈,呵呵,这样理解的话那就错了。
实际上”满堆栈”和”空堆栈”确切的说应该是”满栈”或者是”空栈”,我们只是习惯了把栈叫做堆栈。
而二者深层的意思是说的”位置”或者”地址”,而不是”堆栈”。如果叫”满位置”或者”空位置”更容易理解一些。
满堆栈(full stack,”F”)是指堆栈指针指向堆栈的最后一个已使用的地址或者满位置(也就是sp指向堆栈最后一个数据项位置)。
空堆栈(empty stack,”E”)是指sp指向堆栈的第一个没有使用的地址或者空位置(也就是说sp指向堆栈最后一个数据项的下一个位置)。
满堆栈的关键词是最后一个已使用的地址,空堆栈是第一个没有使用的地址。