ARM 栈

  • Post author:
  • Post category:其他


/*

* 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指向堆栈最后一个数据项的下一个位置)。

满堆栈的关键词是最后一个已使用的地址,空堆栈是第一个没有使用的地址。



版权声明:本文为xiaozhiwise原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。