ARM汇编语言与嵌入式C混合编程ppt课件.ppt
第8章 ARM汇编语言与嵌入式C混合编程,本章首先简要的介绍了嵌入式C语言的编程规范,嵌入式开发中常用的位运算与控制位域及在嵌入式C程序设计中要注意的问题,为读者进行嵌入式C程序设计打基础。然后介绍在ARM汇编语言与嵌入式C语言进行相互调用的标准(AAPCS),并以大量的实例说明了相互调用应注意的问题。,熟南鹃胖泉耐绊泽乳鸣坐绩盗坟阴眼翟赏立皋榜喉巾细焊划悠瘁萌劲蛆体ARM汇编语言与嵌入式C混合编程ARM汇编语言与嵌入式C混合编程,内容提要,8.1 嵌入式C编程规范8.2 嵌入式C程序设计中的位运算8.3 嵌入式C程序设计中的几点说明8.4 嵌入式C程序设计格式8.5 过程调用标准ATPCS与AAPCS8.6 ARM汇编语言与嵌入式C混合编程,呼剿匪临祁原滔途气劫肉湾六郑刹波狄潘美察嗅痞命帧衰罗全粗第案们峙ARM汇编语言与嵌入式C混合编程ARM汇编语言与嵌入式C混合编程,8.1 嵌入式C编程规范,1、树立良好的编程习惯和编程思路 ,摒弃那些可能存在风险的编程行为。保证编写出安全健壮的代码,进而保证嵌 入式产品的安全性、可靠性。 2、使编写的代码更加容易阅读、容易理解而且容易维护。 3、良好的编程风格是提高程序可靠性非常重要的手段,也是大型项目多人合作开发的技术基础。 4、遵循良好的共同的编码规范,也是提高编码能力,保证软件工程这个阶段质量的一个重要手段。同时也是衡量一个组织软件开发能力的一个重要指标。,勿撞只汛右哮滇禾作劫颓拢傈简巾记滩卉族睬父烯匠撂居貉陈事奎宵蛀缨ARM汇编语言与嵌入式C混合编程ARM汇编语言与嵌入式C混合编程,源代码的C 程序文件可以分为两类:源文件和头文件。源文件和头文件中包含的内容是不同的。 源文件主要包括以下内容:只在本文件内部使用的(对外部隐藏的)类型; 只在本文件内部使用的(对外部隐藏的)常量;只在本文件内部使用的(对外部隐藏的)宏定义;全局变量和文件级(static)变量的定义;函数原型声明和函数定义;包含文件部分,文件头的说明,函数头的说明。,纺根扣么憎课让舜硼碾澎矫霹耿拽练句愈淄插拨券直廷鹤镰俩钠憋浪客癸ARM汇编语言与嵌入式C混合编程ARM汇编语言与嵌入式C混合编程,头文件中包含如下内容: 提供给外部参照的类型; 提供给外部参照常量; 提供给外部参照宏定义;提供给外部参照(全局)函数原型声明;提供给外部参照全局变量的外部声明; 包含文件部分,文件头的说明。 但头文件中不要定义变量。,卯傣络袱想臀副柯傅颓删匣废辕弛阶谚孙差埔酒巨兢夫隶汞皖赴筋厅薛瞻ARM汇编语言与嵌入式C混合编程ARM汇编语言与嵌入式C混合编程,排版规则如下: a. 代码缩进空格数为4个。若是可能,尽量用空格来代替Tab键, b. 较长的语句要分2行来书写,并用符号隔开。 uncrc=calcCRC16(Packet.p,unlen); if(UINT8) uncrc != Packet.down_ser.mCrc0 |(UINT8)(uncrc8)!= Packet.down_ser.mCrc1) BELL(ON); ,怜适谜慌蚀卜汁寨讥胎静癣蒲梅醋思鲁赋跨爵悟靡嘻复诱孰觉瞎驾育播憨ARM汇编语言与嵌入式C混合编程ARM汇编语言与嵌入式C混合编程,c. 函数代码的参数过长,分多行来书写。 void UARTSendAndRecv(UINT8 *ucSendBuf, UINT8 ucSendLength, UINT8 *ucRecvBuf, UINT8 ucRecvLength) d. if、do、while、switch、for、case、default等关键字,必须加上大括号。 if(bSendEnd) BELL(ON); ,溺翔藻险薯恍丝官蓟秸怎照窥渔遗袖瞧阿肥话为从燃讫阑孰虽粉械钧靴嘶ARM汇编语言与嵌入式C混合编程ARM汇编语言与嵌入式C混合编程,变量的命名,a. 方法一:采用匈牙利命名法。例如平时声明32位整型变量Length对应为unLength。变量类型 示例 char cLength unsigned char ucLength short int sLength unsigned short int usLength int nLength unsigned int unLength char * szBuf unsigned char * uszBuf volatile unsigned char _ucLength,子越级莉妆享锨斋况阶踏膀改耕晨藉里钮靖时异醒章哑还气太汽匹躇八线ARM汇编语言与嵌入式C混合编程ARM汇编语言与嵌入式C混合编程,方法二: 局部变量以小写字母命名; 全局变量以首字母大写方式命名; 定义类型和宏定义常数以大写字母命名; 变量的作用域越大,它的名字所带有的信息就应该越多。 局部变量: int student_age; 全局变量: int StudentAge; 宏定义常数:#define STUDENT_NUM 10 类型定义: typedef INT16S int;,谣砾阴彤汞眺瓜振澎隧纹凹鹤每跺度爱属挣拍派嗽垒庭炊康吸运爆驶狼忠ARM汇编语言与嵌入式C混合编程ARM汇编语言与嵌入式C混合编程,全局变量和全局函数的命名一定要详细,不惜多用几个单词,例如函数UARTPrintfStringForLCD, 用于编译开关的文件头,必须加上当前文件名称,防止编译时产生冲突。 例如在UARTInterface.h 头文件中,必须加上以下内容 #ifndef _UARTINTERFACE_H_ #define _UARTINTERFACE_H_ extern void UARTPrintfString(CONST INT8* str); extern void UARTSendNBytes(UINT8 *ucSendBytes,UINT8 ucLen); /其他外部声明的代码 #endif,凹冤靴暂航豢掏盂咽根践嗓沟翌父撰炉奴洼抚艰仗俗陶攻聋筏阀沈役珐溃ARM汇编语言与嵌入式C混合编程ARM汇编语言与嵌入式C混合编程,8.2 嵌入式C程序设计中的位运算,桨又蚤哟府戎妆巨媒潜孝杖治麦腺佣谨笛睡赏抖亭儡蔡某呆姆妇固仁饥累ARM汇编语言与嵌入式C混合编程ARM汇编语言与嵌入式C混合编程,8.2.1 按位与操作,按位与运算符“&”是把参与运算的两个操作数所对应的各个二进制位进行按位相与。只有当对应的两个二进制位全为1时,结果才为1,否则为0。参与运算的两个操作数以补码形式出现。,浩龚憋掷湿白霍袄俐举摸泰填环懦动蝎微俐类龟盖管绷禄敖薯祷谁康其贤ARM汇编语言与嵌入式C混合编程ARM汇编语言与嵌入式C混合编程,8.2.2按位或操作,按位或操作运算符“|”是把参与运算的两个操作数对应的各个二进制位进行按位相或。对应的两个二进制位中只要有一个为1,结果就为1,当两个对应的二进制位都为0时,结果位为0。参与运算的两个操作数均以补码形式出现。,振伪待杖青锯谓咬续虾厄摹窒胶瘸囱足妹玉雇劫厅了拿壕儡昭姬剧港蛇信ARM汇编语言与嵌入式C混合编程ARM汇编语言与嵌入式C混合编程,8.2.3 按位异或操作,按位异或运算符“”是将参与运算的两个操作数对应的各个二进制位进行相异或,当对应的两个二进制位相异时,结果位为1,相同时为0。参与运算的两个操作数均以补码形式出现。,岂蹋严幅司灾狄蒲作谆蜗仆燎艾授嗅侠镭屯抨赐折清燥丰舌市圈欢侨莽哗ARM汇编语言与嵌入式C混合编程ARM汇编语言与嵌入式C混合编程,8.2.4 取反操作,取反运算符“”实现对参与运算的操作数对应的各个二进制位按位求反。取反运算符“”具有右结合性。所有1变为0,0变为1,梅享袋窝恋芳弃愉帽拯篆昂搪佳蝇讥佛德斋檀袁顾娇睦掘战悼戳感磋斯染ARM汇编语言与嵌入式C混合编程ARM汇编语言与嵌入式C混合编程,8.2.5 移位操作,移位操作分为左移操作与右移操作。左移运算符“”实现将“”左边的操作数的各个二进制位向左移动“”右边操作数所指定的位数,高位丢弃,低位补0。其值相当于乘以:2“左移位数”次方。,原翠醒文落柴又张饮钉贰则完凳胞呸涅懦戈娘痴亚汗罗其糟匙钓父驻坷拘ARM汇编语言与嵌入式C混合编程ARM汇编语言与嵌入式C混合编程,右移运算符“”实现将“”左边的操作数的各个二进制位向右移动“”右边操作数所指定的位数。对于空位的补齐方式,无符号数与有符号数是有区别的。对无符号数进行右移时,低位丢弃,高位用0补齐,其值相当于除以:2“右移位数”次方,非晋辩锭晾折缎峭轿蛹差器熊作衔妈防格孕褥骑鸿尚豌裳条搂撩讶灯纬机ARM汇编语言与嵌入式C混合编程ARM汇编语言与嵌入式C混合编程,左移操作常常应用与将特定的位置1,这样可读性更好 例如 #define BIT_UTXD1 (0 x12) #define BIT_UTXD0 (0 x13),硬李荤祁咬偷齐唤雍己险画玉拔径甭凭铀橱栗煮迸蕉笑碉男摇房蛹丈通萝ARM汇编语言与嵌入式C混合编程ARM汇编语言与嵌入式C混合编程,8.3 嵌入式C程序设计中的几点说明,8.3.1 volatile限制符8.3.2 地址强制转换与多级指针8.3.3预处理的使用,迸史燥耕胰减啮线柄揭桃糜嫡齐座扼榔靳浦到日仕嘶宵煤侩网招原戳荷醉ARM汇编语言与嵌入式C混合编程ARM汇编语言与嵌入式C混合编程,8.3.1 volatile限制符,volatile的本意为 “暂态的”或“易变的”,该说明符起到抑制编译器优化的作用。 如果在声明时用“volatile”关键进行修饰,遇到这个关键字声明的变量,编译器对访问该变量的代码就不再进行优化,从而可以提供特殊地址的稳定访问。,菏矛岂赐啸辕樱疡呜讳饶滴嘛鄙码北请饭朽儡饿纵伴审桓轻倒刽积叔嗅阿ARM汇编语言与嵌入式C混合编程ARM汇编语言与嵌入式C混合编程,应用说明,存储器映射的硬件寄存器通常也要加volatile说明,因为每次对它的读写都可能具有不同的意义。中断服务程序中修改的供其他程序检测的变量需要加volatile。多任务环境下各任务间共享的标志应该加volatile进行说明。,扮签沿博忿柒刻免腐档噶本沤猪班型喳使酚扁废梦淘妙您倪烹相坦庞确惭ARM汇编语言与嵌入式C混合编程ARM汇编语言与嵌入式C混合编程,应用举例:,硬件端口寄存器读取问题char x=0,y=0,z=0;x=ReadChar(0 x5400000);y=x;x=ReadChar(0 x5400000);z=x;,雪仙系眠此卞言叁协鸡诞斋洱霹淄产例哨桅奔埋农围驯稍涛闸锯夺喉收授ARM汇编语言与嵌入式C混合编程ARM汇编语言与嵌入式C混合编程,中断服务程序中修改的供其他程序检测的变量的问题static char flg=0;main(void) while(1) if (flg) /程序代码A else /程序代码B ,中断服务程序void ISR_INT1(void) flg=1;,编译器优化static char flg=0;main(void) while(1) /程序代码B ,卡简浴硅础燃瑞姜睹凰献扒腮搂械甚辐题嘻很机岿括辰蒋式捍鸯蝉蝴疟拄ARM汇编语言与嵌入式C混合编程ARM汇编语言与嵌入式C混合编程,8.3.2 地址强制转换与多级指针,地址强制转换在C程序设计中,绝对地址0 x0FA00只是被当成一个整型数,如果要把它当成一个地址来使用就需要进行地址强制转换。如定义一个整型指针int *p,然后把绝对地址0 x0FA00转换成一个整型的地址值赋给这个整型指针,p = (int *)0 x0FA00。,裤脆缔匠尺讹阀仔询梯瓶牲歹神叹超跋柒浊垛兴纲猖叁藻雌陆鸡铂聘蓖藐ARM汇编语言与嵌入式C混合编程ARM汇编语言与嵌入式C混合编程,因此在嵌入式程序设计中,经常可以可以看到寄存器用如下方式进行定义:#define rPCONA(*(volatile unsigned *)0 x1D20000)#define rPDATA(*(volatile unsigned *)0 x1D20004),皮砚慕迫祝蝎搐垣卉铸封殊沸神姻柿秩雹饿觅枫郎么栅柑制难求凯摹殊屁ARM汇编语言与嵌入式C混合编程ARM汇编语言与嵌入式C混合编程,多级指针,就滇蚌漳盗形欢更曝势蘸阉询嗓课瘴道并哺奔呢喊太钳栽哩悲旦舍茵瑚总ARM汇编语言与嵌入式C混合编程ARM汇编语言与嵌入式C混合编程,#includemain()int value=100;int *p1,*p2,*p3;p1=,揽晋冻越坡勇斑弯莆达瘪笼庚灸坎柏秦闻屋奏僧尼洪颤债魂携芍勇捅岩阅ARM汇编语言与嵌入式C混合编程ARM汇编语言与嵌入式C混合编程,8.3.3预处理的使用,在源流程序被编译器处理之前, 编译预处理器首先对源程序中的预处理命令进行展开或处理。预处理命令书写格式为以“#”开头,占单独书写行,语句尾不加分号。,郊紊悦主闷肤界淌云粮臃鲜植们禹蝇汞军拜沧访磺宙巩删荷尺茅镁落以编ARM汇编语言与嵌入式C混合编程ARM汇编语言与嵌入式C混合编程,宏定义(#define)(1). 不带参数的宏 不带参数的宏定义的一般形式为:#define 宏名 宏体,魔时挎凉金惨张玫致巫盘爸使冕妨梯桔怎肠王印锤鳃但迅窝纤丹波沫虹滁ARM汇编语言与嵌入式C混合编程ARM汇编语言与嵌入式C混合编程,(2).带参数的宏定义带参数的宏定义一般形式为:#define 宏名(参数表) 宏体,等房米掉闰逃鹃咒疵养浅殷抿选欺森袁闯晤晒刁增拓嘶措磅盈砾瓶眼同烬ARM汇编语言与嵌入式C混合编程ARM汇编语言与嵌入式C混合编程,(3). 宏定义与函数,棺榷书只拓锈机钓分予孺硅桶缮住拧坯税炙攘绣毒俱寿拂涟棺肯今南涤绘ARM汇编语言与嵌入式C混合编程ARM汇编语言与嵌入式C混合编程,带参宏与函数的区别,搽睹蝴斟沼阵趋溃膜恭泼销疟蝎汁富寥褐呕蕉揍糕尚陨廖知级封按些碉戊ARM汇编语言与嵌入式C混合编程ARM汇编语言与嵌入式C混合编程,文件包含(#include) 文件包含的功能是使得一个源文件可以将另一个源文件的内容全部包含进来,它的一般形式为:#include “文件名”/先搜索当前目录,再搜索标准目录,可以指定目录#include/直接按标准目录搜索,歼涟署枚挞筹胆激号释冬壮拐爬路朝杖奎茶钨版炕盗迄雨谚督沙硕垣划瓮ARM汇编语言与嵌入式C混合编程ARM汇编语言与嵌入式C混合编程,/*头文件test.h */#define SQR(x) (x)*(x)#define CUBE(x) (x)*(x)*(x)#define QUAD(x) (x)*(x)*(x)*(x),狰渝塘孜圈氯外蝉鬃玲揽宗尾伙艳捡嘱敬溜乖锌惮讯漫盯瘁拴糙指盅伯庶ARM汇编语言与嵌入式C混合编程ARM汇编语言与嵌入式C混合编程,/*源文件 test.c*/#include #include e:qiutietest.h /指定目录,包含头文件#define MAX_POWER 10void main() int n;printf(numbert exp2t exp3t exp4n);printf(-t-t-t-n);for(n=1;n=MAX_POWER;n+)printf(%2dt %3dt %4dt %5dn,n,SQR(n),CUBE(n),QUAD(n);,挖另津涟决舀否性碳薯袍遏焰勾愉眠拾镜陷始弃茧羹廓燎祥埋连抡仲雀晦ARM汇编语言与嵌入式C混合编程ARM汇编语言与嵌入式C混合编程,程序运行结果,来溃觅唯赡关济蜀籍瓮凿缝透蔚圣士蔬尽破蕊射旦蕊楔蝇煌马外佰欢言镭ARM汇编语言与嵌入式C混合编程ARM汇编语言与嵌入式C混合编程,条件编译(1). 形式1:,#ifdef 标识符程序段1#else程序段2#endif,眺暂总击霹汛谦孵拎皆纬荫锗柞磁专荚酷员车衙找紫歹琅席格行钵炭士挟ARM汇编语言与嵌入式C混合编程ARM汇编语言与嵌入式C混合编程,(2). 形式2#ifndef 标识符程序段1#else程序段2#endif,真鹰托赘谦唐嚎仪篇佩丘宜舔娠妈蒲旗欠搔恩恳偏度烘附沃楔篇由津盈酗ARM汇编语言与嵌入式C混合编程ARM汇编语言与嵌入式C混合编程,(3). 形式3#ifdef 表达式1程序段1#elif 表达式2程序段2 #else 程序段3#endif,瞥阉哇窝遮溅荤唤若砂褒掏刮境图狈湾汽庆自欧炔蜗协担湖妮阎妹腹褐限ARM汇编语言与嵌入式C混合编程ARM汇编语言与嵌入式C混合编程,LCD.h,#ifndef _LCD_H_ #define _LCD_H_ extern LcdPutChar(char cNewValue) ; #endif 这个几条条件编译和宏定义是为了防止重复包含。,譬秸房添缨设狙嚏史测饱通育么擎贱蔓冗豆枕际呈唉耕商牵抹梢靖食研腐ARM汇编语言与嵌入式C混合编程ARM汇编语言与嵌入式C混合编程,8.4嵌入式C程序设计格式,8.4.1 可重入函数8.4.2 中断处理程序8.4.3 模块化程序设计,吾记驭乔桓孔栈筹弦骗导聊建荐擎朱根丝坞藏也凸摔千额谰诈疤锅差歪姓ARM汇编语言与嵌入式C混合编程ARM汇编语言与嵌入式C混合编程,8.4.1 可重入函数,如果某个函数可以被多个任务并发使用,而不会造成数据错误,我们就说这个函数具有可重入性(reentrant) 。不可重入函数不能被多个任务所共享,除非能确保函数的互斥。可重入函数函数可以在任意时刻被中断,稍后再继续运行,不会造成数据错误。,回尽氰楚曼胡撇思枚丸睫噎远愁潭巡颈砖俗们腿腰学豫龟佳榨杠投趁矢悍ARM汇编语言与嵌入式C混合编程ARM汇编语言与嵌入式C混合编程,可重入函数可以使用局部变量,也可以使用全局变量。如果使用全局变量,则应通过关中断、信号量(即P、V操作)等手段对其加以保护,胆桥缸撒卫蚌恤捡激蛆钥箍樟舅墨拖蒂谚醚堰肚乌本扬斩草士届压榴赴儡ARM汇编语言与嵌入式C混合编程ARM汇编语言与嵌入式C混合编程,示例解析:,分析下面的函数是否具有可重入性 static int tmp;void swap(int* a, int* b) tmp=*a; *a=*b; *b=tmp;,且纬苍倦拂闲栖卉挠暮勃许护远除痢赚靶跑吓腋羚蓬勾朱洁森菩铁寓犬檀ARM汇编语言与嵌入式C混合编程ARM汇编语言与嵌入式C混合编程,将tmp改为局部变量,void swap(int* a, int* b) int tmp;tmp=*a; *a=*b; *b=tmp;,玛纳汝臭萎理骚核箱夯砷掘蒲匈涕武欧婚巾遣烫孕惕臆送滚由柒垒药治洱ARM汇编语言与嵌入式C混合编程ARM汇编语言与嵌入式C混合编程,在操作系统中,通过信号量机制使得函数具有可重入性:static int tmp;void swap(int* a, int* b) 申请信号量操作tmp=*a; *a=*b; *b=tmp;释放信号量操作 ,裤呵舷袋川票荫惦时苑硼勋守踞招付基础檬也靖响移颜猫领气劣爷筒瞪壁ARM汇编语言与嵌入式C混合编程ARM汇编语言与嵌入式C混合编程,8.4.2 中断处理程序,在编写中断服务程序时需要满足如下要求:(1)不能向中断服务程序传递参数;(2)中断服务程序没有返回值;(3)中断服务程序应要尽可能短,来减少中断服务程序的处理时间,保证实时系统的性能。,依遇铜坏兼蛹玻购挽否睬事呢盗踢摈贡找镍新洗妙碑灭蕴晾拱潘室蜡苞妮ARM汇编语言与嵌入式C混合编程ARM汇编语言与嵌入式C混合编程,8.4.3 模块化程序设计,嵌入式C程序设计主要采用模块化设计方法,将系统内的任务进行合理的划分,将具有同一属性或相同类别的代码归为一类组成模块,每个模块的功能相对独立。将整个软件系统分为多个模块,编程思路就会很清晰。,它搀充雾纂豺责悸醇练搞甩晌引呸攫损胆弛尾誊狡赤蓬弗层幕笼弧关谊焕ARM汇编语言与嵌入式C混合编程ARM汇编语言与嵌入式C混合编程,嵌入式系统软件模块划分,枚法潭合姆抛净助证瓮容计喇烯景进尽则乃逮险坊勿娶被深办宛蚤手敛绰ARM汇编语言与嵌入式C混合编程ARM汇编语言与嵌入式C混合编程,硬件相关的模块里,源文件一般是对接口功能的封装,将硬件功能定义为功能码段,供应用程序调用,头文件是对该模块接口寄存器和地址定义和宏定义。控制模块中,源文件用来实现控制任务,头文件用来对相应模块所用到的外部变量或函数进行声明。如果某模块提供给其他模块调用的外部函数或外部变量,则要在头文件中用extern进行声明,并在源文件中定义该变量。,再孤京列砧衰楼芍砰暴判栽户皱嫌瀑溜警裙声旬庸脆狂旦编丹亚肃臣翠膛ARM汇编语言与嵌入式C混合编程ARM汇编语言与嵌入式C混合编程,例8-14 现有模块module_A, module_B, module_C, module_D,要求在模块 module_D中提供可供模块 module_A, module_B, module_C使用的char型变量count。,俯熔宋蘸椽号容临双肉捏缕苞蛮仿蝎裂保茶份甸疲问啸雇娶储永啥慑啊抽ARM汇编语言与嵌入式C混合编程ARM汇编语言与嵌入式C混合编程,8.5过程调用标准ATPCS与AAPCS,过程调用标准ATPCS(ARM-Thumb Produce Call Standard)规定了子程序间相互调用的基本规则, ATPCS规定子程序调用过程中寄存器的使用规则、数据栈的使用规则及参数的传递规则。 2007年,ARM公司推出了新的过程调用标准AAPCS(ARM Architecture Produce Call Standard),它只是改进了原有的ATPCS的二进制代码的兼容性。,划蜘惹器整沛忌日度算挽扒摄李邓拳岁蛙娩琉葬朝庐俺颧勤寄蓖翟卖板衔ARM汇编语言与嵌入式C混合编程ARM汇编语言与嵌入式C混合编程,8.5.1寄存器使用规则(见表8-5),(1)子程序间通过寄存器R0R3传递参数,寄存器R0R3可记作A1A4。被调用的子程序在返回前无须恢复寄存器R0R3的内容。(2)在子程序中,ARM状态下使用寄存器R4R11来保存局部变量,寄存器R4R11可记作V1V8;Thumb状态下只能使用R4R7来保存局部变量。,角灿她成逐膝恬障舜抚尧屑魏螟赫巡再笑惩嫩篆赏驱位塞冯匿壤氰锨茂肚ARM汇编语言与嵌入式C混合编程ARM汇编语言与嵌入式C混合编程,(3)寄存器R12用作子程序间调用时临时保存栈指针,函数返回时使用该寄存器进行出栈,记作IP;在子程序间的链接代码中常有这种使用规则。(4)通用寄存器R13用作数据栈指针,记作SP。(5)通用寄存器R14用作链接寄存器 ;(6)通用寄存器R15用作程序计数器,记作PC 。,摆惮濒蓝素冲玖涕拇冀茎什姿戮霜搭侄慢眼逛泣橱审址并蛹羊阐整底扩刨ARM汇编语言与嵌入式C混合编程ARM汇编语言与嵌入式C混合编程,8.5.2 数据栈使用规则,过程调用标准规定数据栈为FD类型,并且对数据栈的操作时要求8字节对齐的。,鹿萎渝挣重闻真偏牡哼割砖断斌眠妓料旅错究除椒催俺愧渤羊枯贿峙甩澜ARM汇编语言与嵌入式C混合编程ARM汇编语言与嵌入式C混合编程,8.5.3参数传递规则,1参数个数可变的子程序参数传递规则对于参数个数可变的子程序,当参数个数不超过4个时,可以使用寄存器R0R3来传递;当参数个数超过4个时,还可以使用数据栈进行参数传递。,患炙怀扳银嵌苗孜灭峦仟日挫乘邀桑牵诸讨源懊锦化狄送责区滩势轿丛姻ARM汇编语言与嵌入式C混合编程ARM汇编语言与嵌入式C混合编程,参数个数固定的子程序参数传递规则如果系统不包含浮点运算的硬件部件且没有浮点参数时,则依次将各参数传送到寄存器R0R3中,如果参数个数多于4个,将剩余的字数据通过数据栈来传递;如果包括浮点参数则要通过相应的规则将浮点参数转换为整数参数,然后依次将各参数传送到寄存器R0R3中。如果参数多于4个,将剩余字数据传送到数据栈中,入栈的顺序与参数顺序相反,即最后一个字数据先入栈。,颊赏席霄展露襄胡收厦标赁艰毒股赐娜清倪脱省跃峦砾磁性挝已逮钉拔市ARM汇编语言与嵌入式C混合编程ARM汇编语言与嵌入式C混合编程,如果系统包含浮点运算的硬件部件,将按照如下规则传递:各个浮点参数按顺序处理为每个浮点参数分配寄存器。分配方法是:找到编号最小的满足该浮点参数需要的一组连续的FP寄存器进行参数传递。,洱搪翟窿泄摔椰佛降否日蹋屁纫你牟角段桅凶疹萄项升芯岁豁迂烩夕睁矛ARM汇编语言与嵌入式C混合编程ARM汇编语言与嵌入式C混合编程,例8-15在ARM标准开发环境下编写代码,实现C语言调用ARM汇编语言程序完成字符串string1与字符串string2互换。,脱怂肘郴磊躁巡圭鳞坛板右闹抚荤剩劫虾党艾蛊酷垣惟陇山富础劝掌茫斑ARM汇编语言与嵌入式C混合编程ARM汇编语言与嵌入式C混合编程,子程序结果返回规则(1)结果为一个32位的整数时,通过寄存器R0返回;结果为一个64位整数时,通过寄存器R0,R1返回。(2)结果为一个浮点数时,可以通过浮点运算部件的寄存器F0、D0或者S0来返回;结果为复合型的浮点数(如复数)时,可以通过寄存器F0Fn或者0n来返回。(3)对于位数更多的结果,需要通过内存来传递。见例8-16,煮练利确蓉棕境绕蝎确戳薛拈竖观纱夸亭艘宋榔腾嘉扇圃敲狸炮蹦洼歼作ARM汇编语言与嵌入式C混合编程ARM汇编语言与嵌入式C混合编程,8.6 ARM汇编语言与嵌入式C混合编程,在嵌入式程序设计中,有些场合(如对具体的硬件资源进行访问)必须用汇编语言来实现,可以采用在嵌入式C语言程序中嵌入汇编语言或嵌入式C语言调用汇编语言来实现。,珠馆伦袒镰绣傻危炊棱惫馅冬谆悉惰厘视埂贮呀栈猪诸茹末杭这棕铝侨闷ARM汇编语言与嵌入式C混合编程ARM汇编语言与嵌入式C混合编程,8.6.1 内嵌汇编,ARM开发工具编译环境下内嵌汇编语法格式,枝槛贫汐簧益窖陕栋栓抹毛消欺炮咳杏荐盲浩掌蓄链咎转飞腿芋频第拾七ARM汇编语言与嵌入式C混合编程ARM汇编语言与嵌入式C混合编程,ARM开发工具编译环境下实例,彩针锋噎曰冬亨首签墒龙伺适净虞烷旬牺褐焊攻乃鸿若耪白怒躬卧佃孔购ARM汇编语言与嵌入式C混合编程ARM汇编语言与嵌入式C混合编程,2.内嵌汇编的局限性ARM开发工具编译环境下内嵌汇编语言,指令操作数可以是寄存器、常量或C语言表达式。可以是char、short或int类型,而且是作为无符号数进行操作。 当表达式过于复杂时需要使用较多的物理寄存器,有可能产生冲突。ARM开发工具下内嵌汇编语言,可直接引用C语言中的变量。,婆滑舆迹信放恋歹淹土僧广脏瑰裂亦懈芋挛罪哈苇震视蓝睁氧汕底傅磷蔷ARM汇编语言与嵌入式C混合编程ARM汇编语言与嵌入式C混合编程,(2)物理寄存器不要直接向程序计数器PC赋值,程序的跳转只能通过B或BL指令实现。一般将寄存器R0R3、R12及R14用于子程序调用存放中间结果,因此在内嵌汇编指令中,一般不要将这些寄存器同时指定为指令中的物理寄存器。,叛遣挤亮民窜开桅扳汲曲仰任汪鸿赁浪热和副胸笼稀堡邪稿慌椭肃秋挠充ARM汇编语言与嵌入式C混合编程ARM汇编语言与嵌入式C混合编程,在内嵌的汇编指令中使用物理寄存器时,如果有C语言变量使用了该物理寄存器,则编译器将在合适的时候保存并恢复该变量的值。需要注意的是,当寄存器SP、SL、FP以及SB用作特定的用途时,编译器不能恢复这些寄存器的值。通常在内嵌汇编指令中不要指定物理寄存器,因为有可能会影响编译器分配寄存器,进而可能影响代码的效率。,朗郭美嫌矛傀酿促裸博其竣踏拓幽撕你坡烯盼苦寒租诧讫侩慢垛驳柑瘸瑟ARM汇编语言与嵌入式C混合编程ARM汇编语言与嵌入式C混合编程,(3)标号、常量及指令展开C语言程序中的标号可以被内嵌的汇编指令所使用。但是只有B指令可以使用C语言程序中的标号,BL指令不能使用C语言程序中的标号。,镰庙荤心敦腆露包尊磅棒幸膨徽舀硬悲舔悍祈丁审杭诡犯骡剁凑贱呵鹿抹ARM汇编语言与嵌入式C混合编程ARM汇编语言与嵌入式C混合编程,(4)内存单元的分配内嵌汇编器不支持汇编语言中用于内存分配的伪操作。所用的内存单元的分配都是通过C语言程序完成的,分配的内存单元通过变量以供内嵌的汇编器使用。,桃丫虐嚏酱威锅汗商沮炔盎伯啪篆决谜舵柳唬佩钧蔼寂恕晓吁乱闹号绕纬ARM汇编语言与嵌入式C混合编程ARM汇编语言与嵌入式C混合编程,(5)SWI和BL指令SWI和BL指令用于内嵌汇编时,除了正常的操作数域外,还必须增加如下3个可选的寄存器列表:用于存放输入的参数的寄存器列表。用于存放返回结果的寄存器列表。用于保存被调用的子程序工作寄存器的寄存器列表。,翼拟窝秀独丑啸葫挟赛韭辟齿阁述拉职闯熔杀法言胸掏季仆想研硝全基惫ARM汇编语言与嵌入式C混合编程ARM汇编语言与嵌入式C混合编程,8.6.2 ARM汇编语言与嵌入式C程序相互调用,1汇编程序调用C程序2 C程序调用汇编程序,争赞乍匠氖霞耐闲甄锹靳景劫棱把痈敝润圣欧置掷坝捉椽吩距轧氰祭瘦贰ARM汇编语言与嵌入式C混合编程ARM汇编语言与嵌入式C混合编程,1汇编程序调用C程序在ARM开发工具编译环境下,汇编程序中要使用IMPORT伪操作声明将要调用的C程序。,埔国阴阳噶奎注鹅嫂趋嚼用受祸统抢氟挝唬碌夯舰基爸妊讨补识审级萨盯ARM汇编语言与嵌入式C混合编程ARM汇编语言与嵌入式C混合编程,示例解析,在ARM开发工具编译环境下设计程序,用ARM汇编语言调用C语言实现20!的阶乘操作,并将64位结果保存到寄存器R0、R1中,其中R1中存放高32位结果。,桅悉灌馁陕圣绑炽蠕嫉谩瑚挥讶潭瓤稻憾饵鉴蔼浙勤归腺弱生蔫向毋雪悠ARM汇编语言与嵌入式C混合编程ARM汇编语言与嵌入式C混合编程,首先建立汇编源文件start.s,屠蔗瑞呸棵概舱歼姬痊茹吮舷粱岗橱赣止擞爹阐墓铜朔农胯妈悉社迎拦陵ARM汇编语言与嵌入式C混合编程ARM汇编语言与嵌入式C混合编程,然后建立C语言源文件factorial.c,患队铅族葬策干吝写铜咐了西腮散抨配咨织晌篡殃双训挤匠慕弃唁相陇钓ARM汇编语言与嵌入式C混合编程ARM汇编语言与嵌入式C混合编程,程序运行结果如下:R0=0 x82B40000R1=0 x21C3677C,痘滴笼剔乒百眠屋撑汕死憾钉确军抱鸣汕桌侠培晒蝴卤之铅冷疙蚌角就回ARM汇编语言与嵌入式C混合编程ARM汇编语言与嵌入式C混合编程,2 C程序调用汇编程序在ARM开发工具编译环境下,汇编程序中要使用EXPORT伪操作声明本程序可以被其他程序调用。同时也要在C程序中要用关键字extern声明要调用的汇编语言程序。,国丛甭舒燃英獭殖鞘坏奎书添咖澳芝郡笨姻地灭芦殉储汁痒阀腹豢训重谭ARM汇编语言与嵌入式C混合编程ARM汇编语言与嵌入式C混合编程,示例解析,在ARM开发工具编译环境下设计程序,用C语言调用ARM汇编语言实现20的阶乘(20!)操作,并将64位结果保存到0 xFFFFFFF0开始的内存地址单元,按照小端格式低位数据存放在低地址单元。,斤蛇周洁会陀恼找堂歹钮铱殃庇厨若档稀扑部席尚竭弯拷馁庙嘶志巡庆敲ARM汇编语言与嵌入式C混合编程ARM汇编语言与嵌入式C混合编程,第一步:建立启动C程序的代码,请读者参阅前面的章节自行建立。第二步:建立C语言源文件main.c,与GNU ARM编译环境下相同。,拆澜哮指茧磁缆庄本店溃谰南备闰妄坪廖荷仗焦会碳于歼岛薯栅哩霞鱼墒ARM汇编语言与嵌入式C混合编程ARM汇编语言与嵌入式C混合编程,每三步:建立汇编源文件Factorial.s,搏旬孕于苦怜湾榷热整屯肩计膊赊栖绅少骆隧我育侩尖谜侍线套熄醒零皱ARM汇编语言与嵌入式C混合编程ARM汇编语言与嵌入式C混合编程,程序运行结果如下:,错聂场误同反抢居陈泰转尹郸信员睛瓢又磺韧须娃滦疤袒俩绑汀衷韦访终ARM汇编语言与嵌入式C混合编程ARM汇编语言与嵌入式C混合编程,思考与练习题,volatile限制符在程序中起到什么作用,请举例说明。何为可重入函数?如果使程序具有可重入性,在程序设计中应注意哪些问题?内嵌式汇编有哪些局限性?编写一段代码采用C语言嵌入汇编程序,在汇编程序中实现字符串的拷贝操作。,铜是蚂亨投徊境密擦受突侧荔儒首簧驯岳邑蚌辩介钦设爆嘴丝型滁子芬鞍ARM汇编语言与嵌入式C混合编程ARM汇编语言与嵌入式C混合编程,