1 ARM规范库介绍
ADS供给了ANSI C和C 规范库,本文仅评论ANSI C库,该库包含下面几个部分:
◇IS0 C库规范所界说的函数;
◇在Semihosted 环境下用来完结C库函数和方针相关的函数;
◇C和C 编译器要运用的helper函数。
该库供给的比如文档输入输出之类的设备,运用了规范的ARM semihosted履行环境(semihosting是针对ARM方针机的一种机制,他可以根据运用程式代码的输入/输出恳求,和运转有调度功用的主机通讯,这种技能答应主机为一般没有输入和输出功用的方针硬件供给主机资源)。ARMulator、Angel和Multi-lCE都支撑这个环境,可以运用ADs中供给的研制东西研制运用程式,然后在ARMulator或是研制板上运转和调试该程式。假设要使运用体系独自于这个环境,则有必要从头完结C库中依赖于这个环境的相关函数,根据用户体系的运转环境对C库进行恰当的削减。 ..
运用ANSI规范C库进行程式研制,不光可以进步研制功率而且可以增强程式的可移植性。在程式中运用库函数,有必要先树立一个库函数可以履行的环境,这些作业都由库中的函数完结。当运用程式链接了C库中的函数时,C库中的函数将完结:
◇创立C程式所需的履行环境(树立栈,假设需求创立一个堆,初始化程式运用的部分库);
◇调用main()函数开端履行C程式;
◇支撑程式运用的Is0界说的函数;
◇捕获运转时的过错和信号,假设需求,根据过错停止履行或程式退出。版权声明:本站文章均来自网络,本站一切转载文章言辞不代表本站观念
2 削减ARM规范C函数库
规范库中包含了部分依赖于ARM semihosted履行环境的函数,这部分函数的函数名中包含有单个或两个下划线“-”,需求从头完结这部分函数。假设在程式中界说这些函数,则编译器就会运用新界说的函数,这个进程称为库函数的削减。一般情况下,只需求从头界说很少的几个函数就可以运用C库。
ARM运用体系开端履行用户运用程式,有必要先将运用程式加载到履行域,树立运用程式的履行环境。运用C库时,这些繁琐的作业就大部分由c函数来完结了。汇编程式完结体系初始化后,跳转到C程式的人口_main () (留意:不是main(),当C程式中界说了main()主函数时,编译器就会生成_main 代码)。由_main()引导库函数完结C履行环境的初始化,详细进程如下:
◇将非发动代码的RO和RW履行域代码从加载域地址复制到履行域地址;
◇将ZI段 清零;
◇跳转到_rt_entry。
◇调用_rt_stackheap_init()树立堆和栈;
◇调用_rt_lib_init()初始化引证的库函数;假设需求,树立main()函数的参数argc和argv等;
◇调用main()函数,履行运用程式,可以运用库函数;
◇用main()函数的回来值作参数调用exit()。
_rt_entry并不是C函数,他是用ARM C库编程的起始点。_rt_entry不能用C言语宴现,由于这时候仓库还没有树立,仓库由_ rt_stackheap_init()来树立。
上面简略介绍了C程式运用库函数时的调用进程,由_rt—stackheap_init()树立C库运用的内存模型--堆和栈。由于ARM库是树立在 semihosted履行环境的,他完结的内存模型是根据这个环境的,所以有必要修正这个内存模型树立机制。表1列出了需求从头完结的函数,完结了这些函数,运用程式就可以脱离宿主机环境独自运转了。其间,有必要从头完结的是_user initial_stackheap(),由于默许的完结是根据semihosted履行环境的,该函数被_n_stackheap_init()调用创立内存模型,其他两个函数没有默许的完结。 .
表1
函数
__user_initial_stackheap()
__user_heap_extend()
__user_stack_slop()
完结该函数,有必要满意下面的条件:
◇运用不超越96字节的栈空间;
◇除了R12(ip)外不要污染其他寄存器;
◇将堆基址、栈基址、堆鸿沟和栈鸿沟别离存在RO~R3作为回来参数;
◇堆有必要坚持8个字节对齐。
完结例程如下:
#include
__value_in-regs struct __initial_stackheap __user_initial-sta ckheap(
{
}
为了进步运用程式研制功率和可移植性,期望在方针体系上运用ARM库供给的规范输人输出库函数。
高层输入输出函数是不依赖于方针体系环境的,可是高层输入输出函数有必要调用依赖于方针体系的底层函数,才干完结运用体系的输入输出。根据方针体系硬件环境从头界说这些底层函数,就可以运用库供给的规范input/output库函数了。下面以削减ARM规范库供给的printf系列输出函数为例来作阐明。
规范I/O库中最常用的是printf系列函数,包含_printf()、printf()、_fprintf()、fprintf()、 vprintf()和vfprintf()。任何这些函数非透明地运用_FILE,而且仅依赖于fputc()和ferror()两个函数。函数 _printf()和_fprintf()和printf()和fprintf()的差异仅在于前两个函数不能格式化浮点值。只需界说了自己的_FILE 版别和fputc()、ferror()函数,外加界说一个具有FILE类型的_stdout变量,就可以不作任何修正地运用printf系列、 fwrite()、fputs()和puts()函数了。