一、栈初始化
1、概念解析
1.1栈
栈是一种具有后进先出性质的数据组织方式,也就是说后存放的先取出,先存放的后取出。栈底是第一个进栈的数据所处的位置,栈顶是最后进栈数据所处的位置。
1.2满栈和空栈
根据SP指针指向的位置,栈可以分为满栈和空栈。
1、满栈:当堆栈指针SP总是指向最后压入堆栈的数据
2、空栈:当堆栈指针SP总是指向下一个将要放入数据的空位置
ARM采用的是满栈
1.3、升/降栈
1、升栈:随着数据的入栈,SP指针从低地址->高地址移动
2、降栈:随着数据的入栈,SP指针从高地址->低地址移动
ARM采用的是降栈。有时候我们会说ARM采用的是满降栈。
1.4、栈帧
简单的讲,栈帧(stack frame)就是一个函数所使用的那部分栈,所有函数的栈帧串起来就组成了一个完整的栈。栈帧的两个边界分别由fp(r11)和sp(r13)来界定。
2、栈的作用
2.1、保存局部变量
#include <stdio.h>
int main()
{
int a;
a++;
return a;
}
反汇编后代码:
stack1: file format elf32-littlearm
Disassembly of section .text:
00000000 <main>:
#include <stdio.h>
int main()
{
0: e52db004 push {fp} ; (str fp, [sp, #-4]!)
4: e28db000 add fp, sp, #0 ; 0x0
8: e24dd00c sub sp, sp, #12 ; 0xc
int a;
a++;
c: e51b3008 ldr r3, [fp, #-8] //显然变量a存放在了栈中。
10: e2833001 add r3, r3, #1 ; 0x1
14: e50b3008 str r3, [fp, #-8]
return a;
18: e51b3008 ldr r3, [fp, #-8]
}
1c: e1a00003 mov r0, r3
20: e28bd000 add sp, fp, #0 ; 0x0
24: e8bd0800 pop {fp}
28: e12fff1e bx lr
从反汇编代码可以看出:局部变量a存放在了栈中。
2.2、参数传递
#include <stdio.h>
void func1(int a,int b,int c,int d,int e,int f)
{
int k;
k=e+f;
}
int main()
{
func1(1,2,3,4,5,6);
return 0;
}
反汇编代码:
stack2: file format elf32-littlearm
Disassembly of section .text:
0000