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

发布者:Mengyun最新更新时间:2016-07-06 来源: eefocus关键字:ARM  汇编  混合编程 手机看文章 扫描二维码
随时随地手机看文章
在嵌入式系统开发中,目前使用的主要编程语言是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

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之间进行一些数据的传递,最简便的办法就是使用全局变量。

 

#include

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是一致的。

 

#include

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

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

 

int cFun(int a, int b, int c)

{

return a + b + c;

}

  在汇编中调用C的函数,参数的传递也是通过ATPCS来实现的。需要指出的是当函数的参数个数大于4时,要借助stack,具体见ATPCS规范。

       小结

  以上通过几个简单的例子演示了嵌入式开发中常用的C和汇编混合编程的一些方法和基本的思路,其实最核心的问题就是如何在C和汇编之间传值,剩下的问题就是各自用自己的方式来进行处理。以上只是抛砖引玉,更详细和复杂的使用方法要结合实际应用并参考相关的资料。

说明

  以上代码在ADS 1.2的工程中编译,并在对应的AXD中软件仿真通过。

在C和汇编混合编程的时候,存在C语言和汇编语言的变量以及函数的接口问题。
在C程序中定义的变量,编译为.asm文件后,都被放进了.bss区,而且变量名的前面都带了一个下划线。在C程序中定义的函数,编译后在函数名前也带了一个下划线。例如:

extern int num就会变成 .bss _num, 1
extern float nums[5]就会变成.bss _nums, 5
extern void func ( )就会变成 _func,

一    汇编和C的相互调用可以分以下几种情况:

(1) 汇编程序中访问c程序中的变量和函数。
在汇编程序中,用_XX就可以访问C中的变量XX了。访问数组时,可以用_XX+偏移量来访问,如_XX+3访问了数组中的XX[3]。

     在汇编程序调用C函数时,如果没有参数传递,直接用_funcname 就可以了。如果有参数传递,则函数中最左边的一个参数由寄存器A给出,其他的参数按顺序由堆栈给出。返回值是返回到A寄存器或者由A寄存器给出的地址。同时注意,为了能够让汇编语言能访问到C语言中定义的变量和函数,他们必须声明为外部变量,即加extern 前缀。

(2) c程序中访问汇编程序中的变量

如果需要在c程序中访问汇编程序中的变量,则汇编程序中的变量名必须以下划线为首字符,并用global使之成为全局变量。

如果需要在c程序中调用汇编程序中的过程,则过程名必须以下划线为首字符,并且,要根据c程序编译时使用的模式是stack-based model还是register argument model来正确地编写该过程,使之能正确地取得调用参数。

(3) 在线汇编

在 C程序中直接插入 asm(“   ***   ”),内嵌汇编语句,需要注意的是这种用法要慎用,在线汇编提供了能直接读写硬件的能力,如读写中断控制允许寄存器等,但编译器并不检查和分析在线汇编语言,插入在线汇编语言改变汇编环境或可能改变C变量的值可能导致严重的错误。

二 汇编和C接口中寻址方式的改变:

需要注意的是,在C语言中,对于局部变量的建立和访问,是通过堆栈实现的,它的寻址是通过堆栈寄存器SP实现的。而在汇编语言中,为了使程序代码变得更为精简,TI在直接寻址方式中,地址的低7位直接包含在指令中,这低7位所能寻址的具体位置可由DP寄存器或SP寄存器决定。具体实现可通过设置ST1寄存器的CPL位实现,CPL=0,DP寻址,CPL=1,SP寻址。在DP寻址的时候,由DP提供高9位地址,与低7位组成16位地址;在SP寻址的时候,16位地址是由SP(16位)与低7位直接相加得来。

由于在C语言的环境下,局部变量的寻址必须通过SP寄存器实现,在混合编程的时候,为了使汇编语言不影响堆栈寄存器SP,通常的方式是在汇编环境中使用DP方式寻址,这样可以使二者互不干扰。编程中只要注意对CPL位正确设置即可。

关键字:ARM  汇编  混合编程 引用地址:ARM中C和汇编混合编程及示例ARM中C和汇编混合编程及示

上一篇:移植MySQL到嵌入式ARM平台
下一篇:ARM汇编示例—按键LED(循环)

推荐阅读最新更新时间:2024-03-16 14:59

中国移动、ARM、Cavium和Enea就开放NFV测试实验室合作签署协议
2017年5月4日,ARM,Cavium和Enea宣布签署开放NFV 测试实验室合作协议,此次合作将使用基于OPNFV的商用Enea NFV核心平台和Cavium的基于ARM的ThunderX工作负载优化的数据中心服务器处理器。 中国移动的开放NFV 测试实验室,将作为中国移动电信综合云(TIC)的一部分提供测试平台。其工作内容将包括验证各种NFV测试案例 - vCPE,vBRAS,vEPC,vIMS - 同时支持开放网络自动化平台(ONAP)项目的开发和集成。 ARM公司业务部门网络和服务器副总裁兼总经理Noel Hurley表示:“ARM及其合作伙伴的生态系统一直致力于使OPNFV能够为世界上的数据网络带来高效且具有成本效
[网络通信]
【51单片机】STC89C52点亮LED灯,含C代码(2)
1.参考教程:清翔51单片机教程 2.基本原理 : 通过控制通过控制右边输出端高低电频,来控制灯的亮和熄灭。灯左边5V电压,右边若是赋予逻辑0(0V),有电压差,则灯有电流通过,被点亮。 3.具体软件操作步骤在第一篇: 4.程序和结果 在.c文件里写入程序 以点亮1号灯为例, 编译后烧录结果 同理多盏灯同时点亮 结果
[单片机]
【51单片机】STC89<font color='red'>C</font>52点亮LED灯,含<font color='red'>C</font>代码(2)
爱特梅尔推出全新ARM9 微控制器 大幅增加内部数据带宽
·基于ARM926EJ-S技术   ·内部数据带宽达41.6 Gbps  ·结合人机接口和联网功能 爱特梅尔公司 (Atmel Corporation) (美国纳斯达克交易代号:ATML) 现已为SAM9 系列产品增添最新型号。AT91SAM9263 内嵌了一个性能达200 MIPS的 ARM926EJ-STM 微控制器,解决了传统ARM9TM 微控制器在数据密集的图形界面应用 (如联网式医疗监控设备和GPS导航系统)中所遇到的瓶颈问题。AT91SAM9263具有27个DMA通道,包括爱特梅尔的18 通道外设DMA控制器 (PDC);一个9层的总线阵列;以及两个用于数据和指令紧密耦合存储器 (TCM) 的附加总线,以提升CPU
[新品]
S3C44B0X应用设计 - 存储器接口设计
介 绍 三星的 S3C44B0X 16/32 位 RISC 处理器被设计来为手持设备等提供一个低成本高性能的方案。 S3C44B0X 提供以下配置: 2.5V ARM7TDMI 内核带有 8KB cache(高达 75MHZ 的 SAMBA总线结构) ; 可选的 internal SRAM; 外部储存控制器(FP/EDO/SDRAM 控制、片选逻辑); LCD Controller(最大支持 256 色 STN),带专用 DMA的 LCD 控制器(最大支持 256 色 DSTN); 两个通用的 DMA通道,两个带外部请求引脚的外围 DMA通道; 两个 UART/一个 SIO(IRDA1.0,16 字节的 FIF
[单片机]
S3<font color='red'>C</font>44B0X应用设计 - 存储器接口设计
基于ARM处理器的 PC/1 04处理器模块的开发
  PC/104是一种专门为嵌入式应用而定义的总线 ,lEEE会将它定义IEEE—P996 1,信号定义和PC/AT基本一致 ,但气和机械规范却完全不同,是一种优化的、小型 、堆栈式结构嵌入式系统 。基于PC/104结构的模块由于开发方便 、品种富、结构简单等优势在工业控制领域有着广泛的应用。   ARM(Advanced RISC Machine)公司成立于 1990年月,是苹果电脑 ,Acorn电脑集团和 VLSI Technology的合资业 。ARM首创了CHlPLESS的模式 ,该公司只设计出高效ARM内核,通过将 ARM内核授权给半导体公司 ,由半导体公根据实际的应用情况加上各种外围的功能比如Flash、串RTC等构
[单片机]
基于<font color='red'>ARM</font>处理器的 PC/1 04处理器模块的开发
基于ARM9的媒体播放器设计
1 引言 计算机多媒体技术和网络技术飞速发展使得基于流媒体的多媒体应用也被运用在多种领域,特别是网络可视电话、远程监控、视频点播领域。伴随着计算机多媒体压缩技术的成熟和网络传输技术的发展,开发实时可靠、多功能、数字化、操作简单的基于计算机网络通讯技术和多媒体应用的网络化流媒体播放器已成为计算机、通信、消费电子产品领域(3C 产业-Computer、Communication、Consumer Electronics)技术发展的主要方向之一。 2 系统硬件设计 本文使用TQ2440 开发板作为硬件平台。 S3C2440AL 是控制核心,负责控制所有辅助设备。存储器采用SDRAM 和Flash 两种类型,能满足系统运行和调试的
[单片机]
基于<font color='red'>ARM</font>9的媒体播放器设计
用VC++.NET实现C167CR单片机与PC的串行通信
1 引言 PC与单片机构成的上位机、下位机分布式控制系统是一种常见的工业控制系统,单片机作为下位机可进行现场数据采集和就地控制,并可将采集到的数据或者状态 信息传送到上位 PC 机,以做进一步的分析处理。在实际应用中,上位机与下位机的通信问题是首要解决的问题之一,串行通信以其高效率、可靠、标准统一的优点 成为重要的通信手段,本文即在 WINDOWS XP 环境下,使用 Visual C++.NET 中的 MSComm 控件实现 C167CR 单片机与 PC 之间的串行通信,其通信线路通过 RS232 连接(距离小于 15m )。 2 C 167CR 单片机串行接口简介 C167CR单片机是
[单片机]
μC/OS-II定时器算法分析与测试
引 言 μC/OS-II操作系统是建立在微内核基础上的实时操作系统,抢占式多任务、微内核、移植性好等特点,使其在诸多领域都有较好的应用。 在μC/OS-II 2.83及其以后的版本中,一个较大的变化就是增加了对软件定时器的支持。这使得μC/OS实时操作系统的功能更加完善,在其上的应用程序开发与移植也更加方便。在实时操作系统中一个好的软件定时器实现要求有较高的精度、较小的处理器开销,且占用较少的存储器资源。本文在对μC/OS-II定时器算法分析的基础上,对定时精度和处理器占用情况进行了分析与测试,其结果在实时系统的设计与应用中具有借鉴意义。 1 定时器实现架构 在μC/OS-II操作系统内部,任务的延时功能及软件定时器
[测试测量]
μ<font color='red'>C</font>/OS-II定时器算法分析与测试
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
随便看看
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved