汇编程序调⽤C语⾔
1. C语⾔和汇编在启动时哪个先被调⽤
程序运⾏时先由汇编代码去做初始化的⼀些操作,⽐如为C语⾔提供可⽤的栈空间,然后C语⾔才能运⾏。这个可以从程序的编译链接过程来理解:⾼级语⾔->汇编语⾔->⼆进制的可执⾏程序。从CPU的⾓度来看,⼀切都是⼆进制数据,越往上越接近⼈的思维模式,封装的程度也越⾼。越是⾼级的语⾔,就封装的越多,很多运⾏条件不需要程序员去考虑,这些都被编译器代为处理了。越是上层的语⾔越重视逻辑,越是底层的语⾔越重视性能。
2.C语⾔的运⾏为什么需要设置栈
2.1保存现场/恢复现场
在C语⾔中,函数调⽤是基本的操作,调⽤函数就会由函数跳转,涉及到保存上下⽂。和CPU直接进⾏数据交互的是寄存器,当前正在运⾏某个函数时调⽤了另⼀个函数,那当前运⾏的这个函数产⽣的数据保存在寄存器中,⽽调⽤另⼀个函数时也需要使⽤寄存器,然⽽Soc⾥的寄存器是有限的,只能把寄存器让出来给被调⽤的函数⽤,之前在运⾏的函数产⽣的数据就从寄存器⾥可拷贝出来存放到栈⾥,这是保护现场。当函数调⽤返回时再把数据从栈⾥恢复到寄存器⾥,这叫恢复现场。
2.2 函数传参
调⽤函数时可以传给被调⽤函数⼀些参数,那这些参数就得地⽅存放,否则就不能传递给被调⽤函数。这⾥分为两种情况:1.参数不多于4个,可以直接通过寄存器传递。在保存现场后,寄存器⾥的值都已经做好备份,此时寄存器是空闲的,我们可以⽤来传参;2.
参数多余4个时,就要利⽤栈来传递,因为寄存器数量不够。
2.3临时变量保存在栈中
这⾥指的变量不是静态的局部变量,指的是普通的局部变量,⽣命周期和函数⼀样的变量,当函数运⾏结束变量的⽣命周期也就结束,这也是为什么不能把普通局部变量的地址传递出去使⽤。我们在函数⾥定义变量,就是在内存地址⾥⼀块相应⼤⼩内存,然后把内存和变量名进⾏绑定。申请内存可以分为栈和堆,临时变量是申请的栈内存,对堆和栈有不理解的可以参考。为什么要申请⼀段栈内存来供定义临时变量使⽤,我的理解有两点:1.数据总归是要地⽅存放的,要么存在内存要么存在寄存器⾥,寄存器不够那只能存在内存⾥。2.C语⾔定义临时变量是很常见的,定义⼀个临时变量就去申请⼀块内存,⼀会就释放,频繁申请释放容易造成内存碎⽚,所以⼲脆申请⼀段内存给C语⾔作为栈空间使⽤,每次都从栈空间申请释放,这样就避免内存碎⽚问题。
3.为什么我们写C语⾔代码没有设置C语⾔的栈
正如前⾯所说,C语⾔是⾼级语⾔,⼀些细节已经封装起来,不再需要C语⾔程序员考虑。⽐如在⽤gcc编译代码时,编译器在链接时⾃动为我们添加⼀个头,这个头就是能够执⾏⼀段汇编实现的代码,去设置C语⾔的运⾏条件。
4.ARM芯⽚(S5PV210)⾥的栈设置
4.1CPU模式和各种模式下的栈
ARM芯⽚有7中模式,每种模式都有⾃⼰的栈,互相不影响。其中有个SP寄存器,就是栈寄存器,存放的就是栈的地址。详细内容可以参考。
4.2以设置SVC模式的栈为例:
4.2.1 SVC模式的栈空间
上图是SPV210的数据⼿册⾥关于IRAM的描述,其中SVC Stack就是专门给SVC模式使⽤的栈内存。SVC模式就是管理模式,当程序复位或者重启时就是SVC模式。在我们设置好SVC的栈之前是不能调⽤C程序的。可知SVC模式的SP寄存器应该设置为
0xd0037D80,因为ARM是⽤的满减栈。
c语言中文网汇编语言4.2.2 设置SVC的栈
#define SVC_STACK 0xd0037d80
// 设置SVC栈
ldr sp,=SVC_STACK
//调⽤C语⾔函数
bl xxx //xxx是代表函数名,也就是函数的地址,这⾥代表的函数是不需要传参时候的调⽤
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论