4-嵌入式系统原理及应用教程第4章.ppt

上传人:1931953****qq.com 文档编号:3194149 上传时间:2020-07-18 格式:PPT 页数:131 大小:892.50KB
返回 下载 相关 举报
4-嵌入式系统原理及应用教程第4章.ppt_第1页
第1页 / 共131页
4-嵌入式系统原理及应用教程第4章.ppt_第2页
第2页 / 共131页
点击查看更多>>
资源描述

《4-嵌入式系统原理及应用教程第4章.ppt》由会员分享,可在线阅读,更多相关《4-嵌入式系统原理及应用教程第4章.ppt(131页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。

1、主讲内容,第1章 嵌入式系统概述 第2章 ARM微处理器概述与编程模型 第3章 ARM9指令系统 第4章 嵌入式程序设计基础 第5章 嵌入式内部可编程模块 第6章 嵌入式接口技术应用 第7章 软件开发环境,第4章 嵌入式程序设计基础,基于ARM的编译器一般都支持汇编语言的程序设计、C/C+语言的程序设计及两者的混合编程。 本章介绍ARM的嵌入式程序的基础知识 伪指令 汇编语言的语句格式 汇编语言 C/C+语言的混合编程.,4.1 伪指令,在ARM汇编语言程序里,有一些特殊指令助记符,这些助记符与指令系统的助记符不同,没有相对应的操作码,通常称这些特殊指令助记符为伪指令,他们所完成的操作称为伪操

2、作。 伪指令在源程序中的作用是既要把正常的程序用指令表达给计算机以外,又要把程序设计者的意图表达给编译器. 例如:要告诉编译器程序段的开始和结束,需要定义数据等.,在ARM的汇编程序中,我们把伪指令分为三部分介绍: 通用伪指令 与ARM指令相关的伪指令 与Thumb指令相关的伪指令,4.1 伪指令,4.1.1 通用伪指令,通用伪指令包括: 符号定义伪指令 数据定义伪指令 汇编控制伪指令 及其他一些常用伪指令等。,4.1.1 通用伪指令,1.符号定义伪指令 符号定义伪指令用于声明ARM汇编程序中的变量、对变量赋值以及定义寄存器的名称等操作。 常见的符号定义伪指令有如下几种: (1)GBLA、GB

3、LL和GBLS 语法格式: GBLA(GBLL或GBLS)全局变量名 GBLA、GBLL和GBLS伪指令是声明全局变量的伪指令,用于定义一个ARM程序中的全局变量,并将其初始化。,4.1.1 通用伪指令,其中: GBLA用于声明一个全局的数字变量,并初始化为0; GBLL伪指令用于声明一个全局的逻辑变量,并初始化为F(假); GBLS伪指令用于声明一个全局的字符串变量,并初始化为空;对于全局变量来说,变量名在源程序中必须是唯一的。,1.符号定义伪指令 符号定义伪指令用于声明ARM汇编程序中的变量、对变量赋值以及定义寄存器的名称等操作。 常见的符号定义伪指令有如下几种: (1)GBLA、GBLL

4、和GBLS,4.1.1 通用伪指令,指令示例: GBLADATE1 ;声明一个全局数字变量DATE1 GBLLDATE1 ;声明一个全局逻辑变量DATE2 GBLSDATA3 ;声明一个全局的字符串变量DATE3 DATE3SETS“Testing” ;将该变量赋值为“Testing”,4.1.1 通用伪指令,(2)LCLA、LCLL和LCLS 语法格式: LCLA(LCLL或LCLS)局部变量名 LCLA、LCLL和LCLS伪指令是声明局部变量伪指令,用于定义一个ARM程序中的局部变量,并将其初始化。 其中: LCLA用于声明一个局部的数字变量,并初始化为0; LCLL用于声明一个局部的逻辑

5、变量,并初始化为F(假); LCLS用于声明一个局部的字符串变量,并初始化为空。对于局部变量来说,变量名在使用的范围内必须是唯一的,范围限制在定义这个变量的宏指令程序段内。,4.1.1 通用伪指令,指令示例: LCLADATE4 ;声明一个局部数字变量DATE4 LCLLDATE5 ;声明一个局部的逻辑变量DATE5 DATA4SETL 0 x10 ;为变量DATE4赋值为0 x10 LCLSDATA6 ;声明一个局部的字符串变量DATA6,4.1.1 通用伪指令,(3)SETA、SETL和SETS 语法格式: 变量名 SETA(SETL或SETS)表达式 SETA、SETL、SETS是变量赋

6、值伪指令,用于给一个已经定义的全局变量或局部变量赋值。 其中: SETA用于给一个数学变量赋值; SETL用于给一个逻辑变量赋值; SETS用于给一个字符串变量赋值;,4.1.1 通用伪指令,指令示例: GBLA EXAMP1 ;先声明一个全局数字变量EXAMP1 EXAMP1 SETA0 xaa ;将变量EXAMP1赋值为0 xaa LCLL EXAMP2 ;声明一个局部的逻辑变量EXAMP2 EXAMP1 SETLTRUE ;将变量EXAMP1赋值为TRUE GBLA EXAMP3 ;先声明一个全局字符串变量EXAMP3 EXAMP3 SETS“string” ;将变量EXAMP3赋值为s

7、tring,4.1.1 通用伪指令,(4)RLIST 语法格式: 名称 RLIST 寄存器列表 RLIST伪指令是定义通用寄存列表伪指令,通用寄存器列表定义主要应用在堆栈操作或多寄存器传送中,即使用该伪指令定义的名称可在ARM指令LDM/STM中使用。 在LDM/STM指令中,列表中的寄存器访问次序为根据寄存器的编号由低到高,而与列表中的寄存器排列次序无关。,4.1.1 通用伪指令,指令示例: RegListRLISTR0-R5,R8 ;定义寄存器列表为RegList 在程序中使用: STMFD SP!,RegList ;存储列表到堆栈 LDMIA R5,RegList ;加载列表,4.1.1

8、 通用伪指令,2.数据定义伪指令 数据定义伪指令一般用于为特定的数据分配存储单元,同时可完成已分配存储单元的初始化。常见的数据定义伪指令有如下几种: (1)DCB 语法格式: 标号 DCB表达式 DCB伪指令是字节分配内存单元伪指令,用来分配一片连续的字节存储单元并用伪指令中指定的数值或字符初始化。其中,数值范围为0255,DCB也可用“=”代替。,4.1.1 通用伪指令,指令示例: String DCB“This is a test!” ;分配一片连续的字节存储单元并初始化。 DATA2 DCB 15,25,62,00 ;为数字常量15,25,62,00分片内存单元,4.1.1 通用伪指令,

9、(2)DCW(或DCWU) 语法格式: 标号DCW(或DCWU)表达式 DCW(或DCWU)伪指令是为半字分配内存单元,其中,表达式可以为程序标号或数字表达式。 伪指令DCW用于为半字分配一段半字对准的内存单元,并用指定的数据初始化;伪指令DCWU用于为半字分配一段可以非半字对准的内存单元,并用指定的数据初始化。,4.1.1 通用伪指令,指令示例: DATA1 DCW 1,2,3 ;分配一片连续的半字存储单元并初始化为1,2,3。 DATA2 DCWU 45,0 x2a*0 x2a ;分配一片非半字对准存储单元并初始化。,4.1.1 通用伪指令,(3)DCD(或DCDU) 语法格式: 标号 D

10、CD(或DCDU)表达式 DCD(或DCDU)伪指令是为字分配内存单元伪指令,其中,表达式可以为程序标号或数字表达式。DCD也可用“加载给R0 ADR R1,LOOP+0 x40*2 ;把LOOP+0 x40*2处 ;绝对地址加载给R1 ALIGN LOOP ADD R2,R0,R1 ,4.1.3 与Thumb指令相关的伪指令,2. LDR伪指令 语法格式 : LDRcondRd, =数值表达式;加载数字常量 LDRcondRd, =语句标号+数值表达式 ;加载地址 LDR伪指令是把一个数字常量或一个地址加载到低端寄存器伪指令。如果所加载的是一个32位的数字常量,则编译程序就可以把这条语句编译

11、成一条MOV指令,如果不能用MOV指令来表达,则编译成一条LDR指令。如果所加载的是地址的话,编译程序会把这条语句编译成LDR指令。,4.1.3 与Thumb指令相关的伪指令,在使用LDR指令替代伪指令时,编译程序先把数据(或地址)存放在数据缓冲区内,在执行LDR指令时,从缓冲区读出这个数据加载到寄存器中去。因此,在使用这条伪指令时,要为程序创建数据缓冲区。 指令示例: LDR R1, =0 xFFE ;加载0 xFFE到R1中 ;汇编器汇编成MOV R1,# 0 xFFE LDR R1, =START ;加载START处的地址到R1中,4.1.3 与Thumb指令相关的伪指令,3. NOP

12、语法格式: NOP NOP伪指令是空操作指令,在汇编时将被编译成一条无效指令,如MOV R0,R0,占用32位代码空间。,4.2 汇编语言的语句格式,汇编语言的源程序主要组成: 指令 伪指令 语句标号 注释,4.2.1 书写格式,ARM(Thumb)汇编语言的语句格式为: 语句标号 指令或伪指令 ;注释 1.语句标号 语句标号可以大小写字母混合使用,可以使用数字和下划线。语句标号不能与指令助记符、寄存器、变量名同名。 2.指令和伪指令 指令助记符和伪指令助记符可以大写,也可以小写,但不能大小写混合使用。指令助记符和后面的操作数寄存器之间必须有空格,不可以在这之间使用逗号。 3. 注释 汇编器在

13、编译时,当发现一个分号后,把后面的内容解释为注释,不予以编译。,4.2.1 书写格式,举例: AREA EXAMPLE1,CODE,READONLY ;EXAMPLE1程序段代码段,只读属性,4.2.2 汇编语言中表达式和运算符,在汇编语言程序设计中,经常使用各种符号代替地址、变量和常量等,以增加程序的可读性。 1. 变量 ARM(Thumb)汇编程序所支持的变量形式有3种: 数字变量 逻辑变量 字符串变量 变量在编译过程中可能被改变。,4.2.2 汇编语言中表达式和运算符,(1)数字变量用于在程序的运行中保存数字值,数字变量的取值范围不能超过一个32位数所能表达的范围。 全局数字变量使用伪指

14、令GBLA定义; 局部数字变量使用伪指令LCLA定义; 数字变量使用伪指令SETA赋值。,4.2.2 汇编语言中表达式和运算符,(2)逻辑变量用于在程序的运行中保存逻辑值,逻辑值只有两种取值情况:真或假。 全局逻辑变量使用伪指令GBLL定义; 局部逻辑变量使用伪指令LCLL定义; 逻辑变量使用伪指令SETA赋值。,4.2.2 汇编语言中表达式和运算符,(3)字符串变量用于在程序的运行中保存一个字符串. 全局串变量使用伪指令GBLS定义; 局部串变量使用伪指令LCLS定义; 串变量使用伪指令SETS赋值。 串变量需要使用双引号包含。,4.2.2 汇编语言中表达式和运算符,(4)变量代换 程序中的

15、变量可通过代换操作取得一个常量。 代换操作符为“$”。 如果在数字变量前面有一个代换操作符“$”,编译器会将该数字变量的值转换为十六进制的字符串,并将该十六进制的字符串代换“$”后的数字变量; 如果在逻辑变量前面有一个代换操作符“$”,编译器会将该逻辑变量代换为它的取值(真或假); 如果在字符串变量前面有一个代换操作符“$”,编译器会将该字符串变量的值代换“$”后的字符串变量。,4.2.2 汇编语言中表达式和运算符,指令示例: LCLSString1 ;定义局部字符串变量String1和String2 LCLSString2 String1 SETS “pen!” String2 SETS “

16、This is a $ String1” ;字符串变量S2的值为“This is a Test!”,4.2.2 汇编语言中表达式和运算符,2. 数字表达式及运算符 数字表达式包括数字、数字常量、数字变量、数字运算符和括号构成。表达式的结果不能超过一个32位数的表达范围。 (1)数字形式可以: 十进制 十六进制 N进制 ASCII,4.2.2 汇编语言中表达式和运算符,若是十进制,在表达的时候可以直接表达, 例如:1234、56789。 若是十六进制,有两种表达方法。 一种是在数值前加“0 x” 另一种是在数值前加“ instruction 汇编语言程序段以及注释 instruction 其中,

17、如果一行中有多个汇编指令,指令之间使用分号“;”隔开;如果一条指令占多行,使用续行符号”表示接续;在汇编指令段中可以使用C语言的注释语句。 在ARM C/C+程序中还可以使用关键词asm来内嵌一段汇编程序,其格式如下: asm(“instruction ; instruction”); 其中,asm后面括号中必须是一条汇编语句,且其不能包含注释语句。,4.4.2 C/C+与汇编语言的混合编程应用,这里主要讨论C/C+和汇编的混合编程,包括相互之间的函数调用。下面分五种情况来进行讨论。 1在C语言中内嵌汇编 在C中内嵌的汇编指令包含大部分的ARM和Thumb指令,不过其使用与汇编文件中的指令有些

18、不同,存在一些限制,主要有下面几个方面: (1)不能直接向PC寄存器赋值,程序跳转要使用B或者BL指令。 (2)在使用物理寄存器时,不要使用过于复杂的C表达式,避免物理寄存器冲突。 (3)R12和R13可能被编译器用来存放中间编译结果,计算表达式值时可能将R0R3、R12及R14用于子程序调用,因此要避免直接使用这些物理寄存器。,4.4.2 C/C+与汇编语言的混合编程应用,(4)一般不要直接指定物理寄存器,而让编译器进行分配。 下面通过一个例子来说明如何在C中内嵌汇编语言: #include void my_strcpy(const char *src, char *dest) /声明一个函

19、数 char ch; /声明一个字符型变量 _asm /调用关键词_asm LOOP ;循环入口 LDRB CH,SRC,#1 ;Thumb指令,chsrc+1.将无符 ;号src地址的数+1送入ch STRB CH,dest,#1 ;Thumb指令, dest+1 ch, ;将无符号CH数据送入dest+1存储 CMP CH, #0;比较CH是否为零,否则循环。 ;总共循环256次 BNE LOOP;B 指令跳转,NE为Z位清零不相等 ,4.4.2 C/C+与汇编语言的混合编程应用,int main();C语言主程序 char *a = forget it and move on!;/声明字

20、符型指针变量 char b64;/字符型数组 my_strcpy(a, b);/调用子函数,进行复制 printf(original: %s, a);/屏幕输出,a的数值 printf(copyed: %s, b);/屏幕输出,b的数值 return 0; 在这里C和汇编之间的值传递是用C的指针来实现的,因为指针对应的是地址,所以汇编中也可以访问。,4.4.2 C/C+与汇编语言的混合编程应用,2在汇编中使用C程序全局变量 内嵌汇编不用单独编辑汇编语言文件,比较简洁,但是有诸多限制,当汇编的代码较多时一般放在单独的汇编文件中。这时就需要在汇编和C之间进行一些数据的传递,最简便的办法就是使用全局

21、变量。具体的汇编程序中访问方法如下: (1)使用IMPORT伪操作声明该全局变量。 (2)使用LDR指令读取该全局变量的内存地址,通常该全局变量的内存地址值存放在程序的数据缓冲池中(Literal pool)。 (3)根据该数据的类型,使用相应的LDR/STR指令读取/修改该全局变量的值。,4.4.2 C/C+与汇编语言的混合编程应用,下面通过一个例子来说明如何在汇编程序中访问C程序全局变量。 AREA asmfile,CODE,READONLY ;建立一个汇编程序段 EXPORT asmDouble ;声明可以被调用的汇编函数asmDouble IMPORT gVar_1 ;调用C语言中声明

22、的全局变量 asmDouble ;汇编子函数入口 LDR R0,=gVar_1 ;将等于gVar_1地址的数据送入R0寄存器 LDR R1,R0 ;将R0中的值为地址的数据送给R1。 MOV R2, #10 ;将立即数2送给R2 ADD R3, R1, R2 ;R3=R1+R2,实现了gVar_1= gVar_1+10 STR R3,R0 ;将R3中的数据送给R0 MOV PC, LR ;子程序返回 END,4.4.2 C/C+与汇编语言的混合编程应用,3C程序中调用汇编的函数 在C程序中调用汇编文件中的函数,主要工作有两个:一是在C中声明函数原型,并加extern关键字;二是在汇编中用EXP

23、ORT导出函数名,并用该函数名作为汇编代码段的标识,最后用MOV PC,LR返回。然后,就可以在C程序中使用该函数了。 下面是一个C程序调用汇编程序的例子,其中汇编程序strcpy实现字符串复制功能,C程序调用strcpy完成字符串复制的工作。,4.4.2 C/C+与汇编语言的混合编程应用,/* C程序*/ #include extern void asm_strcpy(const char *src, char *dest); /声明可以被调用的函数 int main() /C语言主函数 const char *s = seasons in the sun; /声明字符型指针变量 char

24、d32;/声明字符型数组 asm_strcpy(s,d);/调用汇编子函数 printf(source: %s,s);/屏幕显示,S的值 printf( destination: %s,d);/屏幕显示,d的值。 return 0; ,4.4.2 C/C+与汇编语言的混合编程应用,; 汇编语言程序段 AREA asmfile,CODE,READONLY ;声明汇编语言程序段 EXPORT asm_strcpy ;声明可被调用函数名称 asm_strcpy ;函数入口地址 LOOP ;循环标志条 LDRB R4, R0, #1 ;R0的地址加1后送给R4 CMP R4, #0 ;比较R4是否为零

25、 BEQ OVER ;为零跳转到结束 STRB R4, R1, #1;R4的值送入R1加1地址 B LOOP ;跳转到循环位置 OVER ;跳出标志位 MOV PC, LR ;子函数返回 END,4.4.2 C/C+与汇编语言的混合编程应用,4在汇编程序中调用C的函数 在汇编中调用C的函数,需要在汇编中使用伪指令IMPORT 声明将要调用的C函数。 下面是一个汇编程序调用C程序的例子。其中在汇编程序中设置好各参数的值,本例有5个参数,分别使用寄存器R0存放第1个参数,R1存放第2个参数,R2存放第3个参数。,4.4.2 C/C+与汇编语言的混合编程应用,EXPORT asmfile ;可被调用

26、的汇编段 AREA asmfile,CODE,READONLY;声明汇编程序段 IMPORT cFun;声明调用C语言的cFun函数 ENTRY;主程序起始入口 MOV R0, #11;将11放入R0 MOV R1, #22;将22放入R1 MOV R2, #33;将33放入R2 BL cFun;调用C语言子函数 END /*C 语言函数, 被汇编语言调用 */ int cFun(int a, int b, int c)/声明一个函数 return a + b + c;/返回a+b+c的值 ,4.4.2 C/C+与汇编语言的混合编程应用,5C+嵌入式系统中应用 C+和C是可以互相调用的,并且可

27、以灵活的进行汇编语言、C语言、C+语言的混合调用。 前面讲述了C语言与汇编语言的互相调用,在这里我们将讨论C+和C语言的互相调用。当C+与C互相调用是必须使用伪指令“extern “C”.”,例如,extern “C”include “cHeadfile.h”。 extern C包含双重含义,其一:被它修饰的目标是“extern”的;其二:被它修饰的目标是“C”的。 (1)被extern “C”限定的函数或变量是extern类型的 extern是C/C+语言中表明函数和全局变量作用范围(可见性)的关键字,该关键字告诉编译器,其声明的函数和变量可以在本模块或其他模块中使用。,4.4.2 C/C+

28、与汇编语言的混合编程应用,例如:extern int a;此语句仅仅是在声明一个变量,并不是定义变量a,并未为a分配内存空间。变量a在所有模块中作为一种全局变量只能被定义一次,否则会出现连接错误。 通常,在模块的头文件中对模块提供给其他模块引用的函数和全局变量以关键字extern声明。例如,如果模块B欲引用该模块A中定义的全局变量和函数时只需包含模块A的头文件即可。这样,模块B中调用模块A中的函数时,在编译阶段,模块B虽然找不到该函数,但是并不会报错,它会在连接阶段中从模块A编译生成的目标代码中找到此函数。,4.4.2 C/C+与汇编语言的混合编程应用,与extern对应的关键字是static

29、,被它修饰的全局变量和函数只能在本模块中使用。因此,一个函数或变量只可能被本模块使用时,其不可能被extern “C”修饰。 (2)被extern C修饰的变量和函数是按照C语言方式编译和连接的。 作为一种面向对象的语言,C+支持函数重载,而过程式语言C则不支持。函数被C+编译后在符号库中的名字与C语言的不同。例如,假设某个函数的原型为:void foo(int x, int y);,4.4.2 C/C+与汇编语言的混合编程应用,该函数被C编译器编译后在符号库中的名字为_foo,而C+编译器则会产生像_foo_int_int之类的名字(不同的编译器可能产生的名字不同,但是都采用了相同的机制)。

30、_foo_int_int这样的名字包含了函数名、函数参数数量及类型信息,C+就是靠这种机制来实现函数重载的。例如,在C+中,函数void foo(int x, int y)与void foo(int x, float y)编译产生的符号是不相同的,后者为_foo_int_float。,4.4.2 C/C+与汇编语言的混合编程应用,(3)extern C的惯用法 在C+中引用C语言中的函数和变量,在包含C语言头文件(假设为cExample.h)时,需进行下列处理: extern C #include cExample.h ,4.4.2 C/C+与汇编语言的混合编程应用,而在C语言的头文件中,对其

31、外部函数只能指定为extern类型,C语言中不支持extern C声明,在.c文件中包含了extern C时会出现编译语法错误。 在C中引用C+语言中的函数和变量时,C+的头文件需添加extern C,但是在C语言中不能直接引用声明了extern C的头文件,应该仅将C文件中将C+中定义的extern C函数声明为extern类型。,4.4.2 C/C+与汇编语言的混合编程应用,例如: /C+头文件 cppExample.h #ifndef CPP_EXAMPLE_H #define CPP_EXAMPLE_H extern C int add(int x, int y); #endif /C

32、+实现文件 cppExample.cpp #include cppExample.h int add(int x, int y) return x+y; ,4.4.2 C/C+与汇编语言的混合编程应用,/*C实现文件cFile.c /*这样会编译出错:#include cppExample.h*/ extern int add(int x, int y); int main(int argc, char *argv)/C 语言主程序入口 add(2,3); return 0; ,4.5 本章小结,本章介绍了ARM汇编语言程序设计中常见的通用伪指令、与ARM指令相关的伪指令、与Thumb指令相关的伪指令及汇编语言的基本语句格式和基本结构等,同时简单介绍了C/C和汇编语言的混合编程的语法格式及应用等。 通过本章的学习,要求基本掌握伪指令、表达式和运算符的含义及用法,能够编写出汇编语言程序及掌握与C/C+的混合编程方法。,

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 教育专区 > 大学资料

本站为文档C TO C交易模式,本站只提供存储空间、用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。本站仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知淘文阁网,我们立即给予删除!客服QQ:136780468 微信:18945177775 电话:18904686070

工信部备案号:黑ICP备15003705号© 2020-2023 www.taowenge.com 淘文阁