一、概念解析
1.1 概念 - 栈
栈是一种具有 后进先出性质的数据组织方式,也就是说后存放的先取出,先存放的后取出。 栈底是第一个进栈的数据所处的位置, 栈顶是最后一个进栈的数据所处的位置。
1.2 概念 - 满 / 空栈
根据 SP指针指向的位置,栈可以分为 满栈和空栈。
1. 满栈:当堆栈指针 SP总是指向最后压入堆栈的数据
2. 空栈:当堆栈指针 SP总是指向下一个将要放入数据的空位置
ARM 采用满栈!
1.3 概念 - 升 / 降栈 根据 SP指针移动的方向,栈可以分为升栈和降栈。
1. 升栈:随着数据的入栈, SP指针从低地址 ->高地址移动
2. 降栈:随着数据的入栈, SP指针从高地址 ->低地址移动
ARM 采用降栈!
阅读(30) | 评论(0) | 转发(0) |
<script>window._bd_share_config={"common":{"bdSnsKey":{},"bdText":"","bdMini":"2","bdMiniList":false,"bdPic":"","bdStyle":"0","bdSize":"16"},"share":{}};with(document)0[(getElementsByTagName('head')[0]||body).appendChild(createElement('script')).src='http://bdimg.share.baidu.com/static/api/js/share.js?v=89860593.js?cdnversion='+~(-new Date()/36e5)];</script>
1.1 概念 - 栈
栈是一种具有 后进先出性质的数据组织方式,也就是说后存放的先取出,先存放的后取出。 栈底是第一个进栈的数据所处的位置, 栈顶是最后一个进栈的数据所处的位置。
1.2 概念 - 满 / 空栈
根据 SP指针指向的位置,栈可以分为 满栈和空栈。
1. 满栈:当堆栈指针 SP总是指向最后压入堆栈的数据
2. 空栈:当堆栈指针 SP总是指向下一个将要放入数据的空位置
ARM 采用满栈!
1.3 概念 - 升 / 降栈 根据 SP指针移动的方向,栈可以分为升栈和降栈。
1. 升栈:随着数据的入栈, SP指针从低地址 ->高地址移动
2. 降栈:随着数据的入栈, SP指针从高地址 ->低地址移动
ARM 采用降栈!
1.4
概念
-
栈帧
简单的讲 ,栈帧 (stack frame)就是一个函数所使用的那部分栈,所有函数的栈帧串起来就组成了一个完整的栈。栈帧的两个边界分别由 fp(r11) 和 sp(r13)来限定。
妈蛋,这张图有问题。这张图是使用的升栈,所以ARM的降栈,PC应该是在LR的下面。
二、 栈作用
1.保存局部变量
dump后,有这样一段:
2.传递参数
dump后,有这样一段:
在c语言中如果一个函数的参数小于或等于4个,那么会用寄存器r0、r1、r2、r3、r4。如果超过4个,就是用栈传递参数
。
3.保存寄存器值
dump后,有这样一段:
三、 初始化堆栈
简单的讲 ,栈帧 (stack frame)就是一个函数所使用的那部分栈,所有函数的栈帧串起来就组成了一个完整的栈。栈帧的两个边界分别由 fp(r11) 和 sp(r13)来限定。
妈蛋,这张图有问题。这张图是使用的升栈,所以ARM的降栈,PC应该是在LR的下面。
二、 栈作用
1.保存局部变量
- #include <stdio.h>
-
- int main()
- {
- int a;
-
- a++;
-
- return a;
- }
- 0000834c <main>:
- #include <stdio.h>
-
- int main()
- {
- 834c: e52db004 push {fp} ; (str fp, [sp, #-4]!) 将数据压入栈,等同于str fp, [sp #-4]!将fp压入栈(sp指针向下以一“格”的位置),sp同时也指向下一格。
- 8350: e28db000 add fp, sp, #0 ; 0x0 将sp中的内容赋值给fp
- 8354: e24dd00c sub sp, sp, #12 ; 0xc 将sp向下移动3“格”
- int a;
-
- a++;
- 8358: e51b3008 ldr r3, [fp, #-8] 将fp向下2“格”中的数据提取到r3
- 835c: e2833001 add r3, r3, #1 ; 0x1 将r3加上立即数1
- 8360: e50b3008 str r3, [fp, #-8] 存回fp向下2“格”中
-
- return a;
- 8364: e51b3008 ldr r3, [fp, #-8] 将fp继续提取出来
- }
2.传递参数
- #include <stdio.h>
-
- void func1(int a,int b,int c,int d,int e,int f) 这里定义了6个参数
- {
- int k;
- k=e+f;
- }
-
- int main()
- {
- func1(1,2,3,4,5,6); 传递了6个参数
- return 0;
- }
- #include <stdio.h>
-
- void func1(int a,int b,int c,int d,int e,int f)
- {
- 834c: e52db004 push {fp} ; (str fp, [sp, #-4]!) 依然是压入栈,sp指向fp.(下移了一“格”)
- 8350: e28db000 add fp, sp, #0 ; 0x0 fp指向了sp所指
- 8354: e24dd01c sub sp, sp, #28 ; 0x1c sp向下移动了7“格”
- 8358: e50b0010 str r0, [fp, #-16] r0存到fp的下4“格”中
- 835c: e50b1014 str r1, [fp, #-20] r1存到fp的下5“格”中
- 8360: e50b2018 str r2, [fp, #-24] r2存到fp的下6“格”中
- 8364: e50b301c str r3, [fp, #-28] r3存到fp的下7“格”中
- int k;
- k=e+f;
- 8368: e59b3004 ldr r3, [fp, #4] 将fp上面一“格”,(main中的数值5)存到r3
- 836c: e59b2008 ldr r2, [fp, #8] 将fp上面2“格”,(main中的数值6)存到r2
- 8370: e0833002 add r3, r3, r2 r3 = r3 +r2
- 8374: e50b3008 str r3, [fp, #-8] 将r3存到下面3“格”
- }
- 8378: e28bd000 add sp, fp, #0 ; 0x0
- 837c: e8bd0800 pop {fp}
- 8380: e12fff1e bx lr
-
- 00008384 <main>:
-
- int main()
- {
- 8384: e92d4800 push {fp, lr} 将fp和lr压入栈,sp指向lr
- 8388: e28db004 add fp, sp, #4 ; 0x4 fp是sp的上面一”格“
- 838c: e24dd008 sub sp, sp, #8 ; 0x8 sp向下移动2“格“
- func1(1,2,3,4,5,6);
- 8390: e3a03005 mov r3, #5 ; 0x5 设置r3为5
- 8394: e58d3000 str r3, [sp] 将r3保存到sp指向的位置(数5)
- 8398: e3a03006 mov r3, #6 ; 0x6 将r3设为6
- 839c: e58d3004 str r3, [sp, #4] 将r3保存到sp上面一“格”(数6)
- 83a0: e3a00001 mov r0, #1 ; 0x1 设置r0为1(数1)
- 83a4: e3a01002 mov r1, #2 ; 0x2 设置r1为2(数2)
- 83a8: e3a02003 mov r2, #3 ; 0x3 设置r2为3(数3)
- 83ac: e3a03004 mov r3, #4 ; 0x4 设置r3为4(数4)
- 83b0: ebffffe5 bl 834c <func1> 跳转到func1处
- return 0;
- 83b4: e3a03000 mov r3, #0 ; 0x0
- }
3.保存寄存器值
- #include <stdio.h>
-
- void func2(int a,int b)
- {
- int k;
- k = a+b;
- }
-
- void func1(int a,int b)
- {
- int c;
- func2(3,4);
- c = a+b;
- }
-
- int main()
- {
- func1(1,2);
- return 0;
- }
- #include <stdio.h>
-
- void func2(int a,int b)
- {
- 834c: e52db004 push {fp} ; (str fp, [sp, #-4]!) 压入了fp,sp指向fp
- 8350: e28db000 add fp, sp, #0 ; 0x0 fp指向了sp所指
- 8354: e24dd014 sub sp, sp, #20 ; 0x14 sp向下移动5格
- 8358: e50b0010 str r0, [fp, #-16] r0存到fp下面4格
- 835c: e50b1014 str r1, [fp, #-20] r1存到fp下面5格
- int k;
- k = a+b;
- 8360: e51b3010 ldr r3, [fp, #-16] 提取r3到fp下面4格
- 8364: e51b2014 ldr r2, [fp, #-20] 提取r2到fp下面5格
- 8368: e0833002 add r3, r3, r2 r3 = r1 + r2
- 836c: e50b3008 str r3, [fp, #-8] 保存r3到fp下面2格
- }
- 8370: e28bd000 add sp, fp, #0 ; 0x0
- 8374: e8bd0800 pop {fp}
- 8378: e12fff1e bx lr
-
- 0000837c <func1>:
-
- void func1(int a,int b)
- {
- 837c: e92d4800 push {fp, lr} 又压入了fp,lr,sp指向lr
- 8380: e28db004 add fp, sp, #4 ; 0x4 再次赋值fp
- 8384: e24dd010 sub sp, sp, #16 ; 0x10 sp向下移动4“格”
- 8388: e50b0010 str r0, [fp, #-16] 将r0存到fp下面4格
- 838c: e50b1014 str r1, [fp, #-20] 将r1存到fp下面5格
- int c;
- func2(3,4);
- 8390: e3a00003 mov r0, #3 ; 0x3 设置r0为3(数1)
- 8394: e3a01004 mov r1, #4 ; 0x4 设置r1为4(数1)
- 8398: ebffffeb bl 834c <func2> 跳转到func2
- c = a+b;
- 839c: e51b3010 ldr r3, [fp, #-16] 提取fp下面4格
- 83a0: e51b2014 ldr r2, [fp, #-20] 提取fp下面5格
- 83a4: e0833002 add r3, r3, r2 r3 = r3+r2
- 83a8: e50b3008 str r3, [fp, #-8] 将r3存到fp下面3格
- }
- 83ac: e24bd004 sub sp, fp, #4 ; 0x4
- 83b0: e8bd4800 pop {fp, lr}
- 83b4: e12fff1e bx lr
-
- 000083b8 <main>:
-
- int main()
- {
- 83b8: e92d4800 push {fp, lr} 将fp和lr压入栈,sp指向lr
- 83bc: e28db004 add fp, sp, #4 ; 0x4 fp指向sp上面一“格”
- func1(1,2);
- 83c0: e3a00001 mov r0, #1 ; 0x1 设置r0为1(数1)
- 83c4: e3a01002 mov r1, #2 ; 0x2 设置r1为2(数1)
- 83c8: ebffffeb bl 837c <func1> 跳转到func1
- return 0;
- 83cc: e3a03000 mov r3, #0 ; 0x0
- }
三、 初始化堆栈
- init_stack:
- ldr sp, =0x34000000 初始化sp指针,默认为内存起始地址的64MB位置
- mov pc, lr 返回bl init_stack
给主人留下些什么吧!~~
评论热议