汇编写启动代码之设置栈和调用C语言1

1、C语言运行时需要和栈的意义
”C语言运行时(runtime)“需要一定条件,这些条件由汇编来提供,C语言运行时主要是需要栈。

C语言与栈的关系:C语言中的局部变量都是用栈来实现的,如果我们汇编部分没有给C部分预先设置合理合法的栈地址,那么C代码中定义的局部变量就会落空,整个程序就死掉了。

我们平时在编写单片机程序(譬如51单片机)或者编写应用程序时并没有去设置栈,但是C程序还是可以运行的。原因是:在单片机中由硬件初始化时提供了一个默认可用的栈,在应用程序中我们编写的C程序其实并不是全部,编译器(gcc)在链接的时候会帮我们自动添加一个头,这个头就是一段引导我们的C程序能够执行的一段汇编实现的代码,这个代码中就帮我们的C程序设置了栈及其他的运行时需要。
2、CPU模式和各种模式下的栈
栈实际上就是SP指针指向的那块内容。在ARM中37个寄存器中,每种模式下都有自己的独立的sp寄存器(r13),为什么这么设计?

如果各种模式都使用同一个SP,那么就意味着整个程序(操作系统内核程序、用户自己的应用程序)都是用一个栈的。你的应用程序如果一旦出错(譬如栈溢出),就会连累操作系统的栈也损坏,整个操作系统的程序就会崩溃。这样的操作系统设计是非常脆弱的,不合理。
解决方案就是各种模式下用不同的栈。我的操作系统内核使用自己的栈,每个应用程序也使用自己独立的栈,这样各是各的,一个损坏不会连累他人。
我们现在要设置栈,不可能也懒的而且也没有必要去设置所有的栈(因为我们是裸机程序),我们先要找到自己的模式(查数据手册看处在那个模式下我们在SVC下),然后设置自己的模式下的栈到合理合法的位置,即可。
注意:系统默认复位(启动后)进入SVC(管理)模式的
我们怎么去访问SVC模式下的SP呢?很简单?先把模式设置为SVC,再直接操作SP。我们上电启动后已经默认是SVC模式了。所以可以直接设置SP。
3、查阅文档并设置栈指针至合法位置
栈(因为栈要为C语言提供存放局部变量)必须是当前一段可用的内存(可用的意思是这个地方必须有被初始化过可以访问的内存,而且这个内存只会被我们用作栈,不会被其他程序征用)
当前CPU刚复位(启动),外部的DRRAM尚未初始化,目前可用的内存只有内部的SRAM(因为它不需要初始化即可使用这是SRAM的特性)。因此我们只能在SRAM中找一段内存来作为SVC的栈。
栈有四种:满减栈 满增栈 空减栈 空增栈
满栈:进栈:先移动指针再存;出栈:先出数据再移动指针
空栈:进栈:先存数据再移动指针;出栈:先移动指针再移动数据
减栈:进栈:指针向下移动;出栈:指针向上移动
增栈:进栈:指针向上移动;出栈:指针向下移动
注:这里的难点主要是(满空增减)这4个字的意思。满是指当前SP指向的地址里有数据,空是指SP当前指向的地址里没有数据是空的。增减是栈起始从高地址开始还低地址开始。

满栈(full stack):栈指针指向最后压入栈的数据,数据入栈时,sp先减一(或加一)再入栈。
空栈(empty stack):栈指针指向下一个将要放入数据的位置,数据入栈时,先入栈sp再减一(或加一)。
增、减栈区别:根据栈从高地址开始存还是从低地址开始存数据(即栈生成方向不同)就像大端小端区别一样。
递增栈(ascending stack):栈由低地址向高地址生长。
递减栈(secending stack):栈由高地址向低地址生长。

在ARM中,ATPCS(ARM关于程序应该怎么实现的一个规范)要求使用满减栈。
结合下图iROM(SRAM)地址规划。可知SVC栈应该设置为0xD0037D80
4、汇编程序和C程序互相调用
bl cfuncion 在这里用BL调用C语言的一个函数来实现。(这里思考为什么调用函数用BL而不用B)原因是函数调用需要返回,而用b跳转实现的情况是根本就没想着在回来。死循环就用b来调用前面的标号。代码实现见下一节。

SP在各种模式下的示意图(来源网络下载):
图片来源网络

iROM(SRAM)地址规划图:
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值