电子工程专辑互动社区>自由讨论>可编程逻辑器件应用专区>ARM中C和汇编混合编程及示例
大家在做什么
作者 问题:

ARM中C和汇编混合编程及示例

发布时间:2016-5-6 上午11:08

作者: 安然幸福

等级: 遁门入道

积分: 216分

发帖数: 28次

网站总积分: 216分

经验值: 0.0

查看用户的所有发言

查看用户的个人e空间

需要确认注册邮箱后才能下载,立即确认我的邮箱
回复后可下载附件 关闭
ARM中C和汇编混合编程及示例
这个之前学ARM时看的,本人觉得讲得不错,大家可以参考下.ARM中C和汇编混合编程及示例
在嵌入式系统开发中,目前使用的主要编程语言是C和汇编,C++已经有相应的编译器,但是现在使用还是比较少的。在稍大规模的嵌入式软件中,例如含有OS,大部分的代码都是用?C编写的,
主要是因为?C语言的结构比较好,便于人的理解,而且有大量的支持库。尽管如此,很多地方还是要用到汇编语言,例如开机时硬件系统的初始化,包括?CPU状态的设定,中断的使能,主频的设定,以及?RAM的控制参数及初始化,一些中断处理方面也可能涉及汇编。另外一个使用汇编的地方就是一些对性能非常敏感的代码块,这是不能依靠?C编译器的生成代码,而要手工编写汇编,达到优化的目的。而且,汇编语言是和?CPU的指令集紧密相连的,作为涉及底层的嵌入式系统开发,熟练对应汇编语言的使用也是必须的。单纯的?
C或者汇编编程请参考相关的书籍或者手册,这里主要讨论?C和汇编的混合编程,包括
相互之间的函数调用。下面分四种情况来进行讨论,暂不涉及?C++。

1.在?C语言中内嵌汇编
在?C中内嵌的汇编指令包含大部分的?ARM和?Thumb指令,不过其使用与汇编文件中的指令有些不同,存在一些限制,主要有下面几个方面:
a.?不能直接向PC寄存器赋值,程序跳转要使用?B或者?BL指令?
b.?在使用物理寄存器时,不要使用过于复杂的?C表达式,避免物理寄存器冲突?
c.?R12和R13可能被编译器用来存放中间编译结果,计算表达式值时可能将?
R0到?R3、R12及?R14用于子程序调用,因此要避免直接使用这些物理寄存器
d.?一般不要直接指定物理寄存器,而让编译器进行分配
内嵌汇编使用的标记是?__asm或者?asm关键字,用法如下:?
__asm?
{?
instruction?[;?instruction]?
...?
[instruction]

}
asm("instruction?[;?instruction]");
下面通过一个例子来说明如何在?
C中内嵌汇编语言,

#include?<stdio.h>
void?my_strcpy(const?char?*src,?char?*dest)
{?
char?ch;?
__asm?
{
loop:

ldrb?ch,?[src],?#1?
strb?ch,?[dest],?#1?
cmp?ch,?#0?
bne?loop?
}?
}
int?main()
{?
char?*a?=?"forget?it?and?move?on!";?
char?b[64];?
my_strcpy(a,?b);
printf("original:?%s",?a);?
printf("copyed:?%s",?b);?
return?0;
}
在这里?
C和汇编之间的值传递是用?C的指针来实现的,因为指针对应的是地址,所以汇编中也可以访问。

2.在汇编中使用?
C定义的全局变量内嵌汇编不用单独编辑汇编语言文件,比较简洁,但是有诸多限制,当汇编的代码较多时一般放在单独的汇编文件中。这时就需要在汇编和?C之间进行一些数据的传递,最简便的办法就是使用全局变量。

/*?cfile.c
*?定义全局变量,并作为主调程序?
*/?
#include?<stdio.h>?
int?gVar_1?=?12;?
extern?asmDouble(void);
int?main()
{?
printf("original?value?of?gVar_1?is:?%d",?gVar_1);?
asmDouble();
printf("?modified?value?of?gVar_1?is:?%d",?gVar_1);?
return?0;?
}
对应的汇编语言文件

;called?by?main(in?C),to?double?an?integer,?a?global?var?defined?in?C?is?used.
AREA?asmfile,?CODE,?READONLY?
EXPORT?asmDouble?
IMPORT?gVar_1
asmDouble?
ldr?r0,?=gVar_1?
ldr?r1,?[r0]?
mov?r2,?#2?
mul?r3,?r1,?r2?
str?r3,?[r0]?
mov?pc,?lr?
END
3.在?
C中调用汇编的函数
在?C中调用汇编文件中的函数,要做的主要工作有两个,一是在?C中声明函数原型,并加?
extern关键字;二是在汇编中用?EXPORT导出函数名,并用该函数名作为汇编代码段的标识,最后用?mov?pc,?lr返回。然后,就可以在?C中使用该函数了。从?C的角度,并不知道该函数的实现是用?C还是汇编。更深的原因是因为?C的函数名起到表明函数代码起始地址的左右,这个和汇编的?label是一致的。

/*?cfile.c
*?in?C,call?an?asm?function,?asm_strcpy?
*?Sep?9,?2004?
*/?
#include?<stdio.h>
extern?void?asm_strcpy(const?char?*src,?char?*dest);
int?main()
{?
const?char?*s?=?"seasons?in?the?sun";?
char?d[32];
asm_strcpy(s,?d);?
printf("source:?%s",?s);

printf("?destination:?%s",d);?
return?0;?
}
;asm?function?implementation?
AREA?asmfile,?CODE,?READONLY?
EXPORT?asm_strcpy
asm_strcpy?
loop

www.2beanet.com
ldrb?r4,?[r0],?#1?address?increment?after?read?
cmp?r4,?#0?
beq?over?
strb?r4,?[r1],?#1?
b?loop
over?
mov?pc,?lr
END
在这里,C和汇编之间的参数传递是通过?ATPCS(ARM?Thumb?Procedure?Call?Standard)的规定来进行的。简单的说就是如果函数有不多于四个参数,对应的用?R0-R3来进行传递,多于4个时借助栈,函数的返回值通过?R0来返回。
4.在汇编中调用?
C的函数在汇编中调用?C的函数,需要在汇编中?IMPORT对应的?C函数名,然后将?C的代码放在一个独立的?C文件中进行编译,剩下的工作由连接器来处理。

;the?details?of?parameters?transfer?comes?from?ATPCS
;if?there?are?more?than?4?args,?stack?will?be?used?
EXPORT?asmfile?
AREA?asmfile,?CODE,?READONLY?
IMPORT?cFun?
ENTRY?
mov?r0,?#11?
mov?r1,?#22?
mov?r2,?#33?
BL?cFun
END
/*C?file,?called?by?asmfile?*/

int?cFun(int?a,?int?b,?int?c)
{
return?a?+?b?+?c;?
}
在汇编中调用?C的函数,参数的传递也是通过?ATPCS来实现的。需要指出的是当函数的参数个数大于?4时,要借助?stack,具体见?ATPCS规范。
小结
以上通过几个简单的例子演示了嵌入式开发中常用的?C和汇编混合编程的一些方法和基本的思路,其实最核心的问题就是如何在?C和汇编之间传值,剩下的问题就是各自用自己的方式来进行处理。
单片机,嵌入式ARM,linux,Java,PCB,FPGA,汇编C,Android,cortex-m3等课程的学习,请咨询方老师:电话13242993585,QQ2116084661
民治:深圳市宝安区龙华民治大道民德路民德大厦2楼(地铁民治D出口)
南山:深圳南山区南新路与桃园路交汇处苏豪名厦705室(B地铁)
西乡:深圳宝安区宝安大道新中泰大厦8楼(地铁固戍A出口)
广州:白云区黄石街强盛商务大楼623
郑州:郑州金水区文化路82号数码银座B座401室
???标签: 建议
引用 回复 鲜花 ( 0) 臭鸡蛋 ( 0) 有新回复时发送邮件通知

与?建议?相关的话题
?
快速回复
用户名:?
美国的游客?????? (您将以游客身份发表,请登陆 | 注册 ) ?
标题: * 你还可以输入80
评论: * 你还可以输入10000
分享到: 新浪微博?? qq空间?? qq微博?? 人人网?? 百度搜藏??
验证码: ?*?
维护专业、整洁的论坛环境需要您的参与,请及时举报违规帖子,如果举报属实,我们将给予相应的积分奖励。
谢谢您的热心参与!
返回可编程逻辑器件应用专区 | 返回自由讨论
本论坛仅陈述专家或个人观点,并不代表电子工程专辑网站立场。
返回论坛页首
有问题请反馈