18.9 有关设置栈指针sp寄存器r13
为什么在调用C程序时,要在汇编(.S)文件中设置栈指针sp(Stack Pointer) r13?设置栈指针的时候赋的值是多少,如何确定?
.text
.global _start
_start: /*设置内存: sp栈*/
ldr sp, = /* nand启动 */
// ldr sp, =0x40000000+ /* nor启动 */ /* 调用main */
bl main
halt:
b halt
1.SDRAM的地址是 0x3000 0000 ~ 0x4000 0000。
2.Nand启动时,片内4K RAM基地址为0(在0地址处),NOR Flash不可访问。
3.NOR启动时,片内RAM地址为0x4000 0000,片内RAM在0x4000 0000后面的4K,此时的栈顶可以设置到内存的上限0x40000000 + 4K(4096)。
4.调用C函数时,返回地址、局部变量一般都保存在栈里,所以调用C程序时要设置栈指针。
5.之所以设成4096,是由于S4C2410、S3C2440从NAND Flash启动时,它的内部4K RAM的地址为0~4095,所以把栈指针指向最后(其实可以指向0~4096的任意位置,只要不破坏代码就可以)。
18.9.1 C语言及ARM中堆栈指针SP设置的理解
1.什么是栈
栈是一种特殊的线性表,是一种只允许在表的一端进行插入或删除操作的线性表。表中允许进行插入、删除操作的一端称为栈顶。表的另一端称为栈底。栈顶的当前位置是动态的,对栈顶当前位置的标记称为栈顶指针。当栈中没有数据元素时,称之为空栈。栈的插入操作通常称为进栈或入栈,栈的删除操作通常称为退栈或出栈。
简易理解:
客栈,即临时寄存的地方,计算机中的堆栈主要用来保存临时数据,局部变量和中断/调用子程序程序的返回地址。程序中,栈主要是用来存储函数中的局部变量以及保存寄存器参数的,如果你用了操作系统,栈中还可能存储当前进线程的上下文。设置栈大小的一个原则是,保证栈不会下溢出到数据空间或程序空间。CPU在运行C程序时,会自动的使用堆栈,所以堆栈指针SP就必须要在调用C程序前设定。
CPU的内存RAM空间存放规律一般是分段的,从低地址向高地址,依次为:程序段(.text),BSS段,上面还可能会有堆空间,然后最上面才是堆栈段,这样安排堆栈,是因为堆栈的特点决定的。所以堆栈的指针SP初始化一般在堆栈段的高地址,也就是内存的高地址,然后让堆栈指针向下增长(就是递减)。这样做的好处就是堆栈空间远离了其他段,不会跟其他段重叠,造成修改其他段数据,而引起不可预料的后果,还有设置堆栈大小的原则,要保证栈不会下溢出到数据空间或者程序空间。所谓堆栈溢出,是指堆栈指针SP向下增长到其他段空间,如果栈指针向下增长到其他段空间,称为堆栈溢出。堆栈溢出会修改其他空间的值,严重情况下可造成死机.
2.堆栈指针的设置
开始将堆栈指针设置在内部RAM,是因为不是每个板上都有外部RAM,而且外部RAM的大小也不相同,而且如果是SDRAM,还需要初始化,在内部RAM开始运行的一般是一个小的引导程序,基本上不怎么使用堆栈,因此将堆栈设置在内部RAM,但这也就要去改引导程序不能随意使用大量局部变量。
片内4K的SRAM,SDRAM大小64M,从0x30000000到0x33FFFFFF,当程序在片内SRAM运行的时候,sp的值设置为4096,当程序在SDRAM内运行的时候sp设置为0x34000000,当然当程序在内部SRAM运行,若已经初始化SDRAM,此时也可以将堆栈指针设置为0x34000000,更加防止了堆栈溢出。
3.栈的整体作用
1)保存现场;
现场,意思就相当于案发现场,总有一些现场的情况,要记录下来的,否则被别人破坏掉之后,你就无法恢复现场了。而此处说的现场,就是指CPU运行的时候,用到了一些寄存器,比如r0,r1等等,对于这些寄存器的值,如果你不保存而直接跳转到子函数中去执行,那么很可能就被其破坏了,因为其函数执行也要用到这些寄存器。因此,在函数调用之前,应该将这些寄存器等现场,暂时保持起来(入栈push),等调用函数执行完毕返回后(出栈pop),再恢复现场。这样CPU就可以正确的继续执行了。保存寄存器的值,一般用的是push指令,将对应的某些寄存器的值,一个个放到栈中,把对应的值压入到栈里面,即所谓的压栈。然后待被调用的子函数执行完毕的时候,再调用pop,把栈中的一个个的值,赋值给对应的那些你刚开始压栈时用到的寄存器,把对应的值从栈中弹出去,即所谓的出栈。其中保存的寄存器中,也包括lr的值(因为用bl指令进行跳转的话,那么之前的PC的值是存在lr中的),然后在子程序执行完毕的时候,再把栈中的lr的值pop出来,赋值给PC,这样就实现了子函数的正确的返回。
2)传递参数
C语言进行函数调用的时候,常常会传递给被调用的函数一些参数,对于这些C语言级别的参数,被编译器翻译成汇编语言的时候,就要找个地方存放一下,并且让被调用的函数能够访问,否则就没发实现传递参数了。对于找个地方放一下,分两种情况。一种情况是,本身传递的参数不多于4个,就可以通过寄存器r0~r3传送参数。因为在前面的保存现场的动作中,已经保存好了对应的寄存器的值,那么此时,这些寄存器就是空闲的,可以供我们使用的了,那就可以放参数。另一种情况是,参数多于4个时,寄存器不够用,就得用栈了。
3)临时变量保存在栈中
包括函数的非静态局部变量以及编译器自动生成的其他临时变量。
18.9 有关设置栈指针sp寄存器r13的更多相关文章
- android学习笔记18——dpi、dp、sp、xp......
参考:http://www.cnblogs.com/greatverve/archive/2011/12/28/android-dip-dp-sp-pt-px.html http://www.360 ...
- Ubuntu 18.04 Server 设置静态IP
一.背景 Netplan是Ubuntu 17.10中引入的一种新的命令行网络配置实用程序,用于在Ubuntu系统中轻松管理和配置网络设置.它允许您使用YAML抽象来配置网络接口.它可与NetworkM ...
- GPIO——端口位设置/清除寄存器BSRR,端口位清除寄存器BRR
端口位设置/复位寄存器BSRR: 注:如果同时设置了BSy和BRy的对应位,BSy位起作用. 位31:16 BRy: 清除端口x的位y (y = 0…15) 这些位只能写入并只能以字(16 ...
- Ubuntu 18.04 LTS 设置代理(系统代理;http 代理;sock5 代理;apt 代理 ...)
1. 设置系统代理 1.1 设置 http 代理 1.1.1 只在当前 shell 生效 export http_proxy="http://<user>:<passwor ...
- centos7 安装 nginx-1.18.0 并设置开机自启动
一.到官网下载nginx Mainline version: nginx主力版本,为开发版 Stable version: 稳定版,在生产环境中选择此版本进行安装 Legacy versions: ...
- Unity3D脚本18:可视化辅助设置类 Gizmos
Gizmos 类 Gizmos用于场景中给出一个可视化的调试或辅助设置. 所有的Gizmos绘制都必须在脚本的OnDrawGizmos或OnDrawGizmosSelected函数中完成. OnD ...
- 第16月底18天 phpstudy设置
1.phpstudy设置-端口常规设置 E:\phpStudy\Apache\bin>httpd.exeAH00526: Syntax error on line 14 of E:/phpStu ...
- Ubuntu 18.04 上设置桌面程序开机自启动
需求 在新安装的 Ubuntu 18.04 系统上,将有些不可描述的程序开机之后自动启动 Startup Applications Preferences 打开 Startup Application ...
- Ubuntu Server 18.04 网络设置不生效的解决
在Ubuntu18.04中,传统的配置/etc/network/interfaces已无用https://www.cnblogs.com/dunitian/p/6658578.html 新方法:修改 ...
随机推荐
- HTML+css基础认识
标签:<div><span ...
- day14 内置函数二
lamda 语法: 函数名 = lambda 参数: 返回值注意: 1. 函数的参数可以有多个. 多个参数之间⽤逗号隔开 2. 匿名函数不管多复杂. 只能写⼀⾏, 且逻辑结束后直接返回数据 3. 返回 ...
- vim安装
vim的下载与安装 在线安装 sudo yum install vim 源码编译安装 1) 下载源码 git clone https://github.com/vim/vim.git 2) 编 ...
- 语言模型(N-Gram)
问题描述:由于公司业务产品中,需要用户自己填写公司名称,而这个公司名称存在大量的乱填现象,因此需要对其做一些归一化的问题.在这基础上,能延伸出一个预测用户填写的公司名是否有效的模型出来. 目标:问题提 ...
- mysql无法安装,报 The older version of MySQL Installer - Community cannot be removed. Contact your technical support group
解决办法: C:\Users\Administrator>msiexec /i C:\Users\Administrator\Downloads\mysql-installer-web-comm ...
- 胜利大逃亡,bfs,广度优先搜索
题目描述: Ignatius被魔王抓走了,有一天魔王出差去了,这可是Ignatius逃亡的好机会.魔王住在一个城堡里,城堡是一个A*B*C的立方体,可以被表示成A个B*C的矩阵,刚开始Ignatius ...
- Aforge.net识别简易数字验证码问题
参考:https://www.bbsmax.com/A/rV57LjWGdP/ https://blog.csdn.net/louislong007/article/details/47683035 ...
- Groovy学习笔记-Java 5新特性支持
1.枚举enum enum CoffeeSize{ SHORT, SMALL, MEDIUM, LARGE, MUG } def orderCoffee(size){ print "Coff ...
- 代码精简工具lombok
Lombok是一种通过注解的方式减少JAVA实体类中大量冗余代码,诸如get.set以及构造方法等的Java库 一.安装Lombok 步骤一 项目引入lombok插件 1 - 非maven依赖托管项目 ...
- WPF popup自动关闭
var tileMore = new Tile { Height = , Width = , Background = , , )), Title = "更多...", }; ti ...