收藏 分享(赏)

第五讲-ARM汇编语言程序设计.ppt

上传人:Facebook 文档编号:2426444 上传时间:2018-09-15 格式:PPT 页数:63 大小:699KB
下载 相关 举报
第五讲-ARM汇编语言程序设计.ppt_第1页
第1页 / 共63页
第五讲-ARM汇编语言程序设计.ppt_第2页
第2页 / 共63页
第五讲-ARM汇编语言程序设计.ppt_第3页
第3页 / 共63页
第五讲-ARM汇编语言程序设计.ppt_第4页
第4页 / 共63页
第五讲-ARM汇编语言程序设计.ppt_第5页
第5页 / 共63页
点击查看更多>>
资源描述

1、ARM 的指令系统,授课教师:蔡卫明E-mail: 二O一一年八月杭州汇文教育咨询有限公司,ARM源程序文件,使用简单的文本编辑器或者其他的编程开发环境进行编辑.,1 汇编语言源程序格式,1.1 汇编语言程序的结构 汇编源程序示例1(test0源程序),汇编源程序示例2,汇编源程序示例3,ARM的汇编语言程序一般由几个段组成,每个段均由AREA伪操作定义。 段可以分为多种,如代码段、数据段、通用段,每个段又有不同的属性,象代码段的默认属性为READONLY,数据段的默认属性为READWRITE。 本程序定义了两个段, 第一个段为代码段codesec; 第二个段为数据段constdatasec。

2、 程序如何结束?(loop源程序),汇编语言的行构成,格式: 标签 指令/伪操作 操作数 ;语句的注释 所有的标签必须在一行的开头顶格写,前面不能留空格,后面也不能跟C语言中的标签一样加上“:”;ARM汇编器对标识符的大小写敏感,书写标号及指令时字母的大小写要一致; 注释使用“;”符号,注释的内容从“;”开始到该行的结尾结束。 例: Labeladd add r0,r0,r1 Str1 SETS “This is a string.” ;给字符串Str1赋值,汇编语言的行构成,标签: 标签是一个符号,可以代表指令的地址、变量、数据的地址和常数。 一般以字母开头,由字母、数字、下划线组成。 标签

3、不能采用关键字。指令/伪操作 指令/伪操作是指令的助记符或者定义符,它告诉ARM的处理器应该执行什么样的操作或者告诉汇编程序伪指令语句的伪操作功能。,汇编语言的常量,数字常量: 十进制数,如1、2、123 十六进制数,如 0x123,0xabc 字符常量:由单引号及中间的字符组成,包括C语言中的转义字符,如a,n 字符串常量:由一对双引号及中间的字符串表示,中间也可以使用C语言中的转义字符,比如:“abcdef0xarn” 逻辑常量:TRUE,FALSE,注意带大括号,伪指令,没有相对应的操作码或者机器码,通常称为伪指令,它们所完成的操作称为伪操作。 作用是为完成汇编程序作各种准备工作的,由汇

4、编程序在源程序的汇编期间进行处理,仅在汇编过程中起作用。 符号定义伪指令 数据定义伪指令 汇编控制伪指令,符号定义伪指令,用于定义ARM汇编程序中的变量、对变量赋值以及定义寄存器的别名等。 符号定义有如下几种伪指令: 用于定义局部变量的LCLA、LCLL、LCLS; 用于定义全局变量的GBLA、GBLL、GBLS ; 用于对变量赋值的SETA、SETL、SETS ;,符号定义伪指令,1. LCLA、LCLL、LCLS 格式:LCLA/LCLL/LCLS 局部变量名 伪指令用于定义一个汇编程序中的局部变量,并初始化,其中: LCLA定义一个局部的数字变量,初始化为0; LCLL定义一个局部的逻辑

5、变量,初始化为F; LCLS定义一个局部的字符串变量,初始化为空串; 这三条伪指令用于声明局部变量,在其局部作用范围内变量名必须唯一。,例如:LCLA num1 ;声明一个局部的数字变量,变量名为num1 LCLL l2 ;声明一个局部的逻辑变量,变量名为l2 LCLS str3 ;定义一个局部的字符串变量,变量名为str3 num1 SETA 0xabcd ;将该变量赋值为0xabcd l2 SETL FALSE ;将该变量赋值为真 str3 SETS “Hello!” ;将该变量赋值为“Hello!” 在宏内定义局部变量后,则在宏外使用该指令时编译会出错。,符号定义伪指令,2. GBLA、

6、GBLL、GBLS 格式:GBLA/GBLL/GBLS 变量名 伪操作定义一个汇编程序中的全局变量,并初始化,其中: GBLA定义一个全局数字变量,并初始化为0; GBLL定义一个全局逻辑变量,并初始化为“F”; GBLS定义一个全局字符串变量,并初始化为空串; 这三条伪指令用于定义全局变量,因此在整个程序范围内变量名必须唯一。,例如:GBLA num1 ;定义一个全局的数字变量num1 num1 SETA 0xabcd; GBLL l2 ; 定义一个全局的逻辑变量,变量名为l2 l2 SETL FALSE;将该变量赋值为假 GBLS str3 ; 定义一个全局的字符串变量str3 str3

7、SETS “Hello!”;,符号定义伪指令,3. SETA、SETL、SETS 格式:变量名 SETA/SETL/SETS 表达式 说明: SETA:给一个数字变量赋值; SETL:给一个逻辑变量赋值; SETS:给一个字符串变量赋值; 格式中的变量名必须为已经定义过的全局或局部变量,表达式为将要赋给变量的值。,举例:,LCLA num1 ; num1 SETA 0x1234; LCLS str3 ; str3 SETS “Hello!”;,变量代换,如果在字符串变量的前面有一个$字符,在汇编时编译器将用该字符串变量的内容代替该串变量。 例: LCLS str1 LCLS str2 str1

8、 SETS “book” str2 SETS “It is a $str1” 则在汇编后,str2的值为”It is a book”。 如果在数字变量前面有一个代换操作符“$”,编译器会将该数字变量的值转换为十六进制的字符串,并用该十六进制的字符串代换“$”后的数字变量。,例如: No1 SETA 10 Str1 SETS “The number is $No1”则汇编后Str1的值为”The number is 0000000A”. 如果需要将“$”字符 加入到字符串中,可以用“$”代替,此时编译器将不再进行变量代换,而是把“$”看作一个“$”. 例如: Str SETS “The char

9、acter is $” 则编译后Str字符串的值为”The character is $”使用“.”来表示字符串中变量名的结束。,汇编程序的变量代换,数据定义伪指令(test2源程序),用于为数据分配存储单元,同时也可完成已分配存储单元的初始化。 DCB DCW/DCWU DCD/DCDU SPACE FIELD MAP,数据定义伪指令,1. DCB: 标号/变量 DCB 表达式 DCB用于分配一块字节单元并用伪指令中指定的表达式进行初始化。 表达式可以为使用双引号的字符串或0-255的数字,DCB可用“=”代替。 例: Array1 DCB 1,2,3,4,5 ;数组 str1 DCB “Y

10、our are welcome!” ;构造字符串并分配空间。,2. DCW/DCWU: 标号/变量 DCW/DCWU 表达式 DCW分配一段半字存储单元并用表达式值初始化,它定义的存储空间是半字对齐的。 DCWU功能跟DCW类似,只是分配的字存储单元不严格半字对齐。 例如: Arrayw1 DCW 0xa,-0xb,0xc,-0xd;构造固定数组并分配半字存储单元。,3. DCD/DCDU: 标号/变量 DCD/DCDU 表达式DCD伪指令用于分配一块字存储单元并用伪指令中指定的表达式初始化,它定义的存储空间是字对齐的。DCD也可用“该字单元存放str1的地址,7. SPACE: 标号 SPA

11、CE 表达式 说明:SPACE用于分配一片连续的存储区域并初始化为0,表达式为要分配的字节数,SPACE也可用“”代替。 例如: Freespace SPACE 1000 ;分配1000字节的存储空间。,8. MAP: MAP 表达式 ,基址寄存器MAP定义一个结构化的内存表的首地址, “”可以用来代替MAP。 表达式可以为程序中的标号或数学表达式,基址寄存器为可选项,当基址寄存器选项不存在时,表达式的值即为内存表的首地址,当该选项存在时,内存表的首地址为表达式的值与基址寄存器的和。 MAP可以与FIELD伪操作配合使用来定义结构化的内存表。 例如: MAP 0x130,R2 ;内存表首地址为

12、0x130R2。,9. FILED: 标号 FIELD 字节数FIELD用于定义一个结构化内存表中的数据 域,“#” 可用来代替FILED。 FIELD常与MAP配合使用来定义结构化的内存表:FIELD伪指令定义内存表中的各个数据域,MAP则定义内存表的首地址,并为每个数据域指定一个标号以供其他的指令引用。 注意:MAP和FIELD伪指令仅用于定义数据结构,并不分配存储单元。,例如: MAP 0xF10000 ;定义结构化内存表首地址为0xF10000。 count FIELD 4;定义count的长度为4字节,位置为0xF10000 x FIELD 4 ;定义x的长度为4字节,位置为0xF1

13、0004 y FIELD 4 ;定义y的长度为4字节,位置为0xF10008,汇编控制伪指令,汇编控制伪操作用于指引汇编程序的执行流程:IF、ELSE、ENDIFWHILE、WEND,1. IF、ELSE、ENDIF IF 逻辑表达式代码段1 ELSE代码段2 ENDIF 说明:IF、ELSE、ENDIF伪操作能根据逻辑表达式的成立与否决定是否在编译时加入某个指令序列。 如果IF后面的逻辑表达式为真,则编译代码段1,否则编译代码段2。 ELSE及代码段2也可以没有,这时,当IF后面的逻辑表达式为真,则加入代码段1,否则继续编译后面的指令。,IF、ELSE、ENDIF伪指令可以嵌套使用。例如:

14、GBLL isbig;声明一个全局的逻辑变量,变量名为isbigisbig SETL IF isbigadd r0,r0,1 ELSEsub r0,r0,1 ENDIF,2. WHILE、WEND: WHILE 逻辑表达式代码段 WEND WHILE和WEND伪指令能根据逻辑表达式的成立与否决定是否循环执行这个代码段。当WHILE后面的逻辑表达式为真,则执行代码段,该代码段执行完毕后,再判断逻辑表达式的值,若为真则继续执行,一直到逻辑表达式的值为假。 WHILE、WEND伪指令可以嵌套使用。,例如: GBLA num ;声明全局的数字变量numnum SETA 9 ;由num控制循环次数 WH

15、ILE num 0sub r0,r0,1add r1,r1,1 num seta num-1 WEND,1. AREA: AREA 段名 属性, AREA用于定义一个代码段、数据段或者特定属性的段。 属性部分表示该代码段/数据段的相关属性,多个属性可以用“,”分隔。 常见属性如下:,其他伪指令,DATA:定义数据段。CODE:定义代码段。 READONLY:表示本段为只读。 READWRITE:表示本段可读写。 一个汇编程序至少应该包含一个段,当程序太长时,也可以将程序分为多个代码段和数据段。 例如: AREA test,CODE,READONLY AREA |.text|, CODE, RE

16、ADONLY,2. CODE16、CODE32: CODE16/CODE32CODE16伪操作指示编译器后面的代码为16位的Thumb指令。CODE32伪操作指示编译器后面的代码为32位的ARM指令。 如果在汇编源代码中同时包含Thumb和ARM指令时,可以用“CODE32”通知编译器其后的指令序列为32位的ARM指令,用“CODE16”伪指令通知编译器其后的指令序列为16位的Thumb指令。 在使用ARM指令和Thumb指令混合编程的代码里,这两条伪指令后面的代码类型是不同的,但它们并不能对处理器进行状态的切换。,例如:CODE32 ; 32位的ARM指令 AREA |.text|,CODE

17、,READONLY LDR R0,0x8500 ;BX R0 ;程序跳转,并将处理器切换到Thumb状态 CODE16 ;16位的Thumb指令ADD R3,R3,1 END ;源文件结束,3. ENTRY: ENTRYENTRY用于指定汇编程序的入口。在一个完整的汇编程序中至少要有一个ENTRY,程序中也可以有多个。 下面的代码使用了ENTRY: AREA subrout, CODE, READONLYENTRY ; mark first instruction start MOV r0, #10 MOV r1, #3,BL doaddstop MOV r0, #0x18 LDR r1, =

18、0x20026 SWI 0x123456 ; ARM semihosting SWIdoadd ADD r0, r0, r1 ; Subroutine code MOV pc, lr ; Return from subroutine. END ; Mark end of file,4. END: END说明:“END”告诉编译器已经到了源程序的结尾。 例如: AREA constdata,DATA,READONLY END ;结尾 7. EQU: 名称 EQU 表达式,类型 EQU用于将程序中的数字常量、标号、基于寄存器的值赋予一个等效的名称,这一点类似于C语言中的define,可用“*”代替

19、EQU。,如果表达式为32位的常量,我们可以指定表达式的数据类型,类型域可以有以下三种:CODE16/CODE32/DATA 例如: num1 EQU 1234 ;定义num1为1234 addr5 EQU str1+0x50 ; d1 EQU 0x2400,CODE32 ;定义d1的值为0x2400,且该处为32位的ARM指令。,5. EXPORT: EXPORT 标号,WEAKEXPORT 在程序中声明一个全局标号,其他文件中的代码可以引用该标号。用户也可以用GLOBAL代替EXPORT。 ,WEAK可选项声明其他文件有同名的标号,则该同名标号优先于该标号被引用。 例如: AREA |.t

20、ext|,CODE,READONLY main PROCENDP EXPORT main ;声明一个可全局引用的函数main END,6. IMPORT: IMPORT 标号 ,WEAKIMPORT告诉编译器这个标号要在当前源文件中使用,但标号是在其他的源文件中定义的。不管当前源文件是否使用过该标号,这个标号都会加入到当前源文件的符号表中。 ,WEAK选项表示如果所有的源文件都没有找到这个标号的定义,编译器也不会提示错误信息。编译器在多数情况下将该标号置为0,如果这个标号被B或BL指令引用,则将B或BL指令替换为NOP操作。 例如:AREA mycode,CODE,READONLYIMPORT

21、 _printf END,7. EXTERN: EXTERN 标号 ,WEAK说明:EXTERN告诉编译器所使用的标号要在当前源文件中引用,但该标号是在其他的源文件中定义的。与IMPORT不同的是,如果当前源文件实际上没有引用该标号,该标号就不会被加入到当前文件的符号表中。 ,WEAK选项意义同IMPORT。 例如: AREA |.text|,CODE,READONLY EXTERN _printf ;告诉编译器当前文件要引用标号;如果找不到,则不提示错误 END,8. RN: 名称 RN 表达式,说明:RN用于给一个寄存器定义一个别名,以便程序员记忆该寄存器的功能。其中,名称为给寄存器定义的

22、别名,表达式为寄存器的编码。,9. GET/INCLUDE:GET 文件名说明:GET将一个源文件包含到当前的源文件中,并将被包含的源文件在当前位置展开进行汇编处理。INCLUDE和GET作用等效的。我们通常这样使用这个伪指令:在某源文件中定义一些宏指令,用MAP和FIELD定义结构化的数据类型,用EQU定义常量的符号名称,然后用GET/INCLUDE将这个源文件包含到其他的源文件中。,10. INCBIN: INCBIN 文件名INCBIN将一个数据文件或者目标文件包含到当前的源文件中,编译时被包含的文件不作任何变动的存放在当前文件中,编译器从后面开始继续处理。 例如: AREA const

23、data,DATA,READONLY INCBIN data1.dat INCBIN E:DATAdata2.bin END,ARM汇编程序组成,ARM汇编语言源程序中语句由指令、伪操作和宏指令组成 在ARM汇编语言程序中,有一些特殊指令助记符,这些助记符没有相应的操作码,他们所完成的操作称为伪操作。在源程序中的作用是为完成汇编程序作各种准备工作的。 宏是一段独立的程序代码,在程序中通过宏指令调用该宏,常用的伪操作,AREA伪操作用于定义一个代码段或数据段 AREA 段名 ,属性1 ,属性2 一个大的程序可以包括多个代码段和数据段。一个汇编程序至少包含一个段 AREA Example1,COD

24、E, READONLYAREA Example2,DATA, READWRITE,常用的伪操作,EQU伪操作用于为程序中的常量、标号等定义一个等效的字符名称 名称 EQU 表达式,类型 abcd EQU 50;定义标号abcd的值为50 名称为EQU伪操作定义的字符名称,当表达式为32位的常量时,可以指定表达式的数据类型,可以有以下三种类型: CODE16 CODE32 DATA Addr EQU 0x54, CODE32; 定义Addr的值为0x54,且该处为32位的ARM指令。,常用的伪操作,ENTRY和END ENTRY用于指定汇编程序的入口 每一个汇编源程序都包含END为操作,以告诉本

25、源程序的结束 AREA Example1,CODE, READONLY ENTRYEND,常用的伪操作,EXPORT或GLOBAL EXPORT用于在程序中声明一个全局的标号,该标号可在其他的文件中引用,可用GLOBAL代替。 AREA Example, CODE, READONLY EXPORT DoAdd ;下面的函数名称DoAdd可以被其他源文件引用 DoAdd ADD r0, r0, r1,常用的伪操作,CODE16及CODE32 若在汇编源程序中同时包含 ARM 指令和 Thumb 指令时,可用 CODE16 伪指令通知编译器其后的指令序列为 16 位的 Thumb 指令, CODE

26、32 伪指令通知编译器其后的指令序列为 32 位的 ARM 指令。因此,在使用 ARM 指令和 Thumb 指令混合编程的代码里,可用这两条伪指令进行切换,但注意他们只通知编译器其后指令的类型,并不能对处理器进行状态的切换。 AREA Example, CODE, READONLY CODE32 ;通知编译器后面的指令为32位的 ARM指令 LDR R0, =start+1 BX R0 CODE16 StartMOV R1, #10,常用的伪操作,IMPORT 伪操作告诉编译器当前的符号不是在本源文件中定义的,而是在其他源文件中定义的,在本源文件中可能引用该符号 IMPORT Main ;通知

27、编译器当前文件要引用标号Main,但Main在其他文件中定义,宏定义,使用宏定义可以提高程序的可读性,简化程序代码和同步修改。ARM宏定义与标准C的#define相似。 宏定义从MACRO伪指令开始,到MEND结束,并可以使用参数。 宏要先定义,然后再使用,使用时直接书写宏名,并根据对应的宏定义格式设置输入参数或书写标号等,当源程序被汇编时,汇编编译器将展开每一个宏调用,用宏定义体代替程序中的宏调用,并使用实际的参数值代替宏定义时的形式参数。 MACRO $label macroname $parameter,$parameter MEND,AREA Add, CODE, READONLY ;

28、程序起始定义ENTRY ;第一条指令的标示符,只能有一个;下面是程序主体 StartMOV r0, #1MOV r1, #2BL doadd ;调用子程序 doaddADD r0,r0,r1 ;r0=r0+r1MOV pc, lrEND ;END伪指令必须和ENTRY配对使用,C语言与汇编语言,在应用系统的程序设计中,若所有的编程任务均用汇编语言来完成,其工作量是可想而知的,同时不利于系统升级或应用软件移植 ARM体系结构支持C/C+以及与汇编语言的混合编程,在一个完整的程序设计中,除了初始部分用汇编语言完成以外,其主要的编程任务一般都用C/C+完成,从汇编程序中访问C变量,从C程序中调用汇编

29、程序,试分析下面几段ARM汇编程序的执行结果: (1) AREA Example, CODE, READONLYEXPORT test1IMPORT testENTRY testLDR R1, =testLDR R0, R1ADD R0, R0, #1STR R0, R1MOV PC, LREND,思考题,(2) AREA CDO, CODE, READONLY CODE32 ADD_SIXGLOBAL ADD_SIXSTMFD R13, R4, R5LDR R4, R13 LDR R5, R13, #4ADD R0, R0, R1ADD R0, R0, R2ADD R0, R0, R3ADD R0, R0, R4ADD R0, R0, R5SUB R3, R13, #8LDMFD R13, R4, R5 MOV R15, R14END,课后作业 通过调用C运行时库函数,采用汇编语言实现打印“Welcome to HuiWen”。 要求提交完整工程源文件。 作业发到邮箱:,

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > 中等教育 > 小学课件

本站链接:文库   一言   我酷   合作


客服QQ:2549714901微博号:道客多多官方知乎号:道客多多

经营许可证编号: 粤ICP备2021046453号世界地图

道客多多©版权所有2020-2025营业执照举报