汇编程序调用C语言

Posted 代二毛

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了汇编程序调用C语言相关的知识,希望对你有一定的参考价值。

1. C语言和汇编在启动时哪个先被调用

程序运行时先由汇编代码去做初始化的一些操作,比如为C语言提供可用的栈空间,然后C语言才能运行。这个可以从程序的编译链接过程来理解:高级语言->汇编语言->二进制的可执行程序。从CPU的角度来看,一切都是二进制数据,越往上越接近人的思维模式,封装的程度也越高。越是高级的语言,就封装的越多,很多运行条件不需要程序员去考虑,这些都被编译器代为处理了。越是上层的语言越重视逻辑,越是底层的语言越重视性能。

2.C语言的运行为什么需要设置栈

2.1保存现场/恢复现场

在C语言中,函数调用是基本的操作,调用函数就会由函数跳转,涉及到保存上下文。和CPU直接进行数据交互的是寄存器,当前正在运行某个函数时调用了另一个函数,那当前运行的这个函数产生的数据保存在寄存器中,而调用另一个函数时也需要使用寄存器,然而Soc里的寄存器是有限的,只能把寄存器让出来给被调用的函数用,之前在运行的函数产生的数据就从寄存器里可拷贝出来存放到栈里,这是保护现场。当函数调用返回时再把数据从栈里恢复到寄存器里,这叫恢复现场。

2.2 函数传参

调用函数时可以传给被调用函数一些参数,那这些参数就得找地方存放,否则就不能传递给被调用函数。这里分为两种情况:1.参数不多于4个,可以直接通过寄存器传递。在保存现场后,寄存器里的值都已经做好备份,此时寄存器是空闲的,我们可以用来传参;2.参数多余4个时,就要利用栈来传递,因为寄存器数量不够。

2.3临时变量保存在栈中

这里指的变量不是静态的局部变量,指的是普通的局部变量,生命周期和函数一样的变量,当函数运行结束变量的生命周期也就结束,这也是为什么不能把普通局部变量的地址传递出去使用。我们在函数里定义变量,就是在内存地址里找一块相应大小内存,然后把内存和变量名进行绑定。申请内存可以分为栈和堆,临时变量是申请的栈内存,对堆和栈有不理解的可以参考《C语言与堆栈的理解》。为什么要申请一段栈内存来供定义临时变量使用,我的理解有两点:1.数据总归是要找地方存放的,要么存在内存要么存在寄存器里,寄存器不够那只能存在内存里。2.C语言定义临时变量是很常见的,定义一个临时变量就去申请一块内存,一会就释放,频繁申请释放容易造成内存碎片,所以干脆申请一段内存给C语言作为栈空间使用,每次都从栈空间申请释放,这样就避免内存碎片问题。

3.为什么我们写C语言代码没有设置C语言的栈

正如前面所说,C语言是高级语言,一些细节已经封装起来,不再需要C语言程序员考虑。比如在用gcc编译代码时,编译器在链接时自动为我们添加一个头,这个头就是能够执行一段汇编实现的代码,去设置C语言的运行条件。

4.ARM芯片(S5PV210)里的栈设置

4.1CPU模式和各种模式下的栈

ARM芯片有7中模式,每种模式都有自己的栈,互相不影响。其中有个SP寄存器,就是栈寄存器,存放的就是栈的地址。详细内容可以参考《ARM的37个寄存器和异常处理机制详解》

4.2以设置SVC模式的栈为例:

4.2.1 SVC模式的栈空间

在这里插入图片描述

上图是SPV210的数据手册里关于IRAM的描述,其中SVC Stack就是专门给SVC模式使用的栈内存。SVC模式就是管理模式,当程序复位或者重启时就是SVC模式。在我们设置好SVC的栈之前是不能调用C程序的。可知SVC模式的SP寄存器应该设置为0xd0037D80,因为ARM是用的满减栈。

4.2.2 设置SVC的栈

	#define SVC_STACK	0xd0037d80

	// 设置SVC栈
	ldr sp, =SVC_STACK
	
	//调用C语言函数
	bl xxx //xxx是代表函数名,也就是函数的地址,这里代表的函数是不需要传参时候的调用	

以上是关于汇编程序调用C语言的主要内容,如果未能解决你的问题,请参考以下文章

SDRAM和重定位---开始在汇编代码中调用 C 语言

VBS 环境下如何调用EXCEL内置函数

C语言100个经典算法源码片段

Qt编程遇到的问题,我在qt中直接使用C语言的程序片段,有问题 ,求解

22.java方法的定义

C语言调用CMD名后如何获取执行结果