完整word版ARM教材第5章ARM汇编程序设计_第1页
完整word版ARM教材第5章ARM汇编程序设计_第2页
完整word版ARM教材第5章ARM汇编程序设计_第3页
完整word版ARM教材第5章ARM汇编程序设计_第4页
完整word版ARM教材第5章ARM汇编程序设计_第5页
已阅读5页,还剩18页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、第5章ARM汇编程序设计ARM编译器,如ADS集成开发环境,一般都支持汇编语言的程序设计。本章介绍ARM程序设计的一些基本概念,如 ARM汇编语言的伪指令、汇编语言的语句格式和汇编语言的 程序结构等到,并在些基础上介绍一些常用的ARM汇编子程序的设计。4.1 ARM伪指令ARM汇编程序由汇编指令、伪指令和宏指令组成,伪指令不介汇编指令那样在处理器 的运行期间执行,而是在汇编器对汇编程序进行汇编时处理。宏是一段独立的汇编程序代码,它是通过伪指令定义的,在程序中宏指令即调用宏指令。当程序被汇编时,汇编程序对每个宏调用进行展开,用宏定义代汇编程序中的宏指令。由于指令也发球汇编伪指令的一部分, 因此本

2、书将宏指令放在汇编伪一起介绍。与单片机汇编程序设计一样,在ARM汇编语言程序里,有一些特殊指令助记符,这些助记符与指令系统的助记符不同,它们没有相对应的操作友码,通常称这些特殊指令助记符为伪指令,它们所完成的操作称为伪操作。伪指令在源程序中的作用是为完成汇编程序做各种准备工作,这些伪指令仅在汇编过程中起作用,一旦汇编结束,伪指令的使命就完成了。 在ARM的光荣称号程序中,有如下几种伪指令:符号定义伪指令、数据定义伪指令、汇编 控制伪指令以及其他伪指令。4.1.1 符号定义(Symbol Definition )伪指令符号定义伪指令用于定义 ARM汇编程序中的变量、对变量赋值以及定义寄存器的别名

3、 等。常见的符号定义伪指令有以下几种:用于宝玉局变量的 GBLA、GBLL和GBLS ; 用于定义局部变量的 LCLA、SETL、LCLS ; 用于对变量赋值的 SETA、SETL、SETS ; 为通用寄存器列表定义名称的RLIST ;为一个协处理器的寄存器定义名称的伪指令CN ;为一个协处理器定义名称的伪指令CP;为一个CFP寄存器定义名称的伪指令DN和SN;FN。1.GBLA、GBLL 和 GBLS 语法格式:GBLA(GBLL 或 GBLS)GBLA其中:为一个FPA浮点寄存器定义名称的伪指令全局变量名、GBLL和GBLS伪指令用于定义一个 ARM程序中的全局变量, 并半其初始化。GBL

4、AGBLLGBLS伪指令用于定义一个全局的数字变量,并初始化为0;伪指令用于定义一个全局的逻辑变量,并初始化为F (假);伪指令用于定义一个全局的字符串变量,并初始化为空。由于以上三条伪指令用于定义全局变量,因此在整个程序范围内变量名必须唯一。使用示例:GBLANumber1;定义一个全局的数字变量,变量名为Number1Number1SETA Oxaa;将Number1变量赋值为0xaaGBLLTrue1;定义一个全局的逻辑变量,变量名为True1True1SETLTRUE;将True1变量赋值为真GBLSStri ng1;定义一个全局的字符串变量,变量名为Stri ng1Stri ng1S

5、ETS “ Testi ng”;将String1变量赋值为“Testi ng”2.LCLA、LCLL 和 LCLS语法格式:LCLA ( LCLL 或 LCLS)局部变量名并将其初始化,LCLALCLLLCLS伪指令用于定义一个局部的数字变量,并初始化为 伪指令用于定义一个局部的逻辑变量,并初始化为 伪指令用于定义一个局部的字符串变量,并初始化为空。使用示例:0 ;F (假);LCLANumber2;声明一个局部的数字变量,变量名为Number2Number2SETA 0xaa;将Number2变量赋值为0xaaLCLLLogic2;声明一个局部的逻辑变量,变量名为Logic2Logic2SE

6、TLTRUE;将Logic2变量赋值为真LCLSStri ng2;定义一个局部的字符串变量,变量名为Stri ng2以上三条伪指令用于声明局部变量,在其作用范围内变量名必须唯一。LCLA、LCLL和LCLS伪指令用于定义一个 ARM程序中的局部变量, 其中:SETS “ Test ing”;将 Stri ng2 变量赋值为“ Testi ng”Stri ng23.SETA、SETL 和 SETS语法格式:变量名 SETA( SETL或SETS) 表达式伪指令SETA、SETL、SETS用于给一个已经定义的全局变量或局部变量赋值。SETA伪指令用于给一个数学变量赋值;SETL伪指令用于给一个逻辑

7、变量赋值;SETS伪指令用于给一个字符串变量赋值。其中,变量名是已经定义地的全局变量或局部变量,表达式是将要赋给变量的值。示例:LCLANumber3;声明一个局部的数字变量,变量名为Number3Number3SETA 0xaa;将Number3变量赋值为 OxaaLCLLLogic3;声明一个局部的逻辑变量,变量名为Logic3Logic3SETLTRUE 了;将Logic3变量赋值为真使用4. RLIST语法格式: 名称 RLIST寄存器列表RLIST伪指令可用于对一个通用寄存器列表定义名称,使用该伪指令定义的名称可在ARM指令LDM/STM中使用。在LDM/STM 指令中,列表中的寄存

8、器访问次序为根据寄存 器的编号由低到高,而与列表中的寄存器排列次序无关。使用示例:RegList RLISTR0-R5,R8,R10;将寄存器列表名称定义为RegList,可在 ARMSTMDSP !,RegList;指令LDM/STM中通过该名称访问寄存器列表 ;保存寄存器列表 RegList到堆栈CP、DN由于在编程过程中,协处理器汇编伪指令使用的情况比较少,因此本书不对 和SN以及FN等协处理器伪指令进行介绍。4.1.2数据定义(DATA Definition)伪指令同时可完成对已分配存储单元的数据定义伪指令一般用于为特定的数据分配存储单元, 初始化。常见的数据定义伪指令有如下几种:DC

9、B用于分配一片连续的字节存储单元并用指定的数据初始化; DCW(DCWU )用于分配一片连续的半字节存储单元并用指定的数据初始化;DCD( DCDU )用于分配一片连续的字存储单元并用指定的数据初始化;DCFS( DCFSU)用于为双精度的浮点数分配一片连续的字存储单元并用指 定的数据初始化;DCQ( DCQU )用于分配一片以 8字节个为单位的连续的存储单元并用指 定的数据初始化;DCDO用于分配一段字的内存单元,将每个单元的内容初始化为该单元相 对于基址寄存器的偏移量;DCI用于分配一段字的内丰单元,并用单精度的浮点数据初始化,指定内 存单元存放的是代码,而不是数据;SPACE用于分配一片

10、连续的存储单元;MAP用于定义一个结构化的内存表首地址;FIELD用于定义一个结构化的内在表的数据域;LTORG用于声明一个文字池。1.语法格式:标号 DCB 表达式DCB伪指令用于分配一片连续的字节存储单元并用伪指令中的表达式初始化。其中, 表达式可以为0 255的数字或字符吕,DC也可用“=”代替。使用示例:标号 DCB 表达式DCB伪指令用于分配一片连续的字节存储单元并用伪指令中指定的表达式初始化。其 中,表达式可以为 0 255的数字或字符串,DCB也可用“=”代替。使用示例:Stri ng DCB “ This is a test!”Parameter DCB 0x33,0x44,D

11、CB -1,-2,0,1,2,2.DCW (或 DCWU)语法格式:标号 DCW (或DCWU);分配一片连续的字节存储单元并初始化0x55表达式;分配一片连续的字节存储单元并初始化DCW (或DCWU )伪指令用于为双精度的浮点数分配一片连续的字节存储单元,并用 伪指令中指定的表达式初始化。每个双精度的浮点数占据两个字单元,用DCFD分配的字存储单元是字对齐的,而用DCFDU分配的字存储单元并不严格字对齐。使用示例:Fdata DCFD 0,2E115。-5E7;分配一片连续的字存储单元并初始化为指定的双精度数5. DCFS (或 DCFSU)语法格式:标号 DCFS (或DCFSU) 表达

12、式DCFS (或DCFSU )伪指令用于为单精度的浮点数分配一片连续的字存储单元,并用伪指令中指定的表达式初始化。每个单精度的浮点数占据一个字单元, 用DCFS分配的字存储 单元是字对齐的,而用 DCFSU分配的字存储单元并不严格对齐。使用示例:Sdata DCFS 1 , 2E5, -5E7;分配一片连续的字存储单元并初始化为指定的单精度数6. DCQ (或 DCQU )语法格式:标号 DCQ (或DCQU ) 表达式DCQ (或DCQU )伪指令用于分配一片以 8个字节为单位的连续存储区域,并用伪指 令中指定的表达式初始化。用DCQ分配的存储单元是字对齐的,而用DCQU分配的存储单元并不严

13、格对齐。使用示例:Data DCQ 100, 1000;分配一片连续的存储单元并初始化为指定的值7.DCDO语法格式:标号 DCDO 表达式DCDO用于分配一段字内存单元,并将每个单元的内容初始化为该单元相对于表态基 址寄存器的偏移量。DCDO伪指令作为表态基址寄存器 R9的偏移量分配内在单元,该指令 需要内在字对齐。使用示例:IMP ORT externsysData DCDO externnsys;分配32位的字单元,其值勤为标号externnsys基于R9的偏移量8.DCI语法格式:标号 DCI表达式并用伪指令中指定的表达式初始化。指定内在单兀代码中,DCI分配的是半字节的内存代码单元。

14、使用DCI用于分配一段字节的内在单元, 存放的是代码而不是数据,在 Thumb 示例:newinstr Rd , Rm定义为相应的机器指令MACRO ;这个宏指令将指令Newinstr $Rd, $RmDCI 0Xe15f0f10 : CR: (8$Rd: SHL : 12): OR; $Rm ;这是存放的是指令 MEND9.S PACE语法格式:标号 SP ACE 表达式0。其中,表达式是要分配的字SPACE伪指令用于分配一片连续的存储区域并初始化为节数,SPACE也可用“ ”代替。使用示例:DataSpace SPACE 1000 ;分配连续1000B的存储单元并初始化为 010.MA P

15、语法格式:MAP 表达式,基址寄存器MAP伪指令用于定义一个结构化的内存表的首地址,MAP也可用“ A ”代替。表达式可以是程序中的标号或数学表达式,基址寄存器为可选项,当基址寄存器选项不存在时,表达式的值即为内存表的首地址,当该选项存在时,内存表的首地址为表达式的值与基址寄存器的和。MAP伪指令通常与FIELD伪指令配合使用来定义结构化的内存表。使用示例:Ox1O+ROMAP 0x10,R0;定义结构化内存表首地址的值为11.FIELD语法格式:标号 FIELD 表达式FIELD也可用“ #”代替,表达 伪指令常与MAP伪指令配合使用来FIELD伪指令定义内存表中的各注意MAP和FIELD伪

16、指FIELD伪指令用于定义一个结构化内存表中的数据域。 式的值是当前数据域在内存表中所占的字节数。FIELD定义结构化的内存表,MAP伪指令定义内存表的首地址, 个数据域,并可以为每个数据域指定一个标号供其他的指令引用。 令仅用于定义数据结构,并不实际分配存储单元。使用示例:MAP0x100AFIELD16BFIELD32SFIELD256;定义结构化内存表首地址的值为为0x100;定义A的长度为16B,位置为0x100;定义B的长度为32B,位置为0x110( 0x100的存放了 ;16个字节);定义S的长度为256B,位置为0x130( 0x100后存放了 ;32个字节)12.LTORG语

17、法格式:LTORGLTORG用于声明一个文字池。在使用LDR伪指令时,要在适当的地址加入LTORG声明文字池,这样就会把要加载的数据保存在文字池中,再用ARM的加载指令读出数据。如果没有使用LTORG声明文字池,则汇编器会在程序末尾自动声明,使用LTORG声明文字池的目的可以在程序代码的任何位置存储加载的数据。使用示例:LDR R0,=0x12345ADD R1,MOV PC,LTORGR1 ,LRRO;声明文字池,此处存放0x12345;其他代码4.1.3汇编控制(Assembly Control)伪指令汇编控制伪指令用于控制汇编程序的执行流程,包括以下常用的汇编控制伪指令:IF、ELSE、

18、ENDIFWHILE、WENDMACRO、MENDMEXIT1.IF、ELSE、ENDIF语法格式:IF逻辑表达式指令序列1ELSE指令序列2ENDIFIF1,否则执行指令序列 2。其中,ELSE及指令序 则执行指令序列1,否则继续执行后使用示例:变量名为 VersionIF、ELSE、ENDIF伪指令能够根据条件的成立与否决定是否执行某个指令序列。若 后面的逻辑表达式为真,则执行指令序列 列2可以没有,此时,若 IF后面的逻辑表达式为真, 面的指令。IF、ELSE、ENDIF伪指令可以嵌套使用。GBLS Version;定义一个全局的字符串变量,IF Versio n= “ V1 ”指令序列

19、1ELSE指令序列2ENDIFWEND2. WHILE、WHILE逻辑表达式指令序列语法格式:WENDWHILE、WEND伪指令能够根据条件的成立与否决定是否循环执行某个指令序列。若 WHILE后面的逻辑表达式为真,则执行指令序列,该指令序列执行完毕后,再判断逻辑表 达式的值,若为真则继续执行,一直到逻辑表达式的值为假。WHILE、WEND伪指令可以嵌套使用。使用示例如下:GBLA Cou nter器;声明一个全局的的数字变量,变量名为Cou nter,作为循环计数WHILE Cou nter 、X=YXYX=YX=YX/=YXY“/= ”“ ”运算符Y表示两个逻辑表达式,以上的运算符代表运算

20、如下: 表示 表示 表示 表示 表示“=”等于丫 大于丫 小于丫 大于等于 小于等于表示X不等于丫表示X不等于丫“LAND ”、“LOR ”、“LNOT ”及“ LEOR ”运算符 以X和丫表示两个逻辑表达式,以上的逻辑运算符代表运算如下: 表示将X和丫作逻辑与的操作 表示将X和丫作逻辑或的操作 表示将将丫作逻辑非的操作表示将X和丫按位作逻辑异或的操作X: LAND : YX : LOR : Y:LNOT : YX : LEOR: Y3)字符串表达式及运算符字符串表达式一般由字符串常量、字符串变量、运算符和括号构成, 编译器所支持的字符串最大长度为512B。常用的字符串表达式相关的运算符如下:

21、LEN运算符LEN运算符返回字的长度(字符数),以X表示字符串表达式,其语法格式如下::LEN : XCHR运算符M表示某一个整数,其语法CHR运算符将0 255之间的整数转换为一个字符,以 格式如下::CHR: MSTR运算符对于数字表达式,STRSTR运算符将其转换为STR运算符将一个数字表达式或逻辑表达式转换为一个字符串。 运算符将其转换为一个十六进制格式的字符串;对于逻辑表达式, 字符串T或F,其语法格式如下::STR: X其中,X为一个数字表达式或逻辑表达式。LEFT运算符LEFT运算符返回某个字符串左端的规定长度的一个子串,其语法格式如下:X : LEFT : Y其中,X为源字符串

22、,丫为一个整数,表示要返回的字符个数。CC运算符CC运算符用于将两个字符串连接成一个字符串,其语法格式如下:X: CC: Y其中,X为源字符串1,Y为源字符串2,CC运算符将丫连接到X的后面。4)与寄存器和程序计数器(PC)相关的表达式及运算符如下:BASE运算符BASE运算符返回基于寄存器的表达式中寄存器的编号,其语法格式如下::BASE : X其中,X为与寄存器相关的表达式。INDEX运算符INDEX运算符返回基于寄存器的表达式中相对于其基址寄存器的偏移量,其语法格式 如下::INDEX : X其中,X为与寄存器相关的表达式。55)其他常用运算符?运算符?运算符返回基某代码行所生成的可执行

23、代码的长度,例如:? X返回定义符号X的代码行所生成的可执行代码的字节数。DEF运算符DEF运算符判断是否定义某个符号,例如:X已经定义,则结果为真,否则为假。汇编语言程序设计汇编语言的程序结构(Thumb )汇编语言程序中,以程序段为单位组织代码。段是相对独立的指令:DEF: X如果符号4.34.3.1在ARM或数据序列,具有特定的名称。段可以分为代码段和数据段,代码段的内容为执行代码,数据段存放代码运行时需要用到的数据。一个汇编程序至少应该有一个代码段,当程序较长时,可以分割为多个代码段和数据段,多个段在程序编译外链接时最终形成一个可执行的映象文 件。可执行映象文件通常由以下几部分构成:/

24、写。一个或多个代码段,代码段的属性为可读零个或我个包含初始化数据的数据段,数据段的属性为可读 零个或我个不包含初始化数据的数据段,数据段的属性为可读链接器系统默认或用户设定的规则,将各个段安排在存储器中的相应位置。中段之间的相对位置与可执行的映象文件中段的相对位置一般不会相同。AREAENTRYStartIn it ,CODE , READONLY/写。/写。因此源程序以下是一个汇编语言源程序的基本结构:LDRRO,=0x3FF5000LDRR1,0xFFSTRR1,R0LDRR0,=0x3FF5008LDRR1,0x01STRR1,R0END在汇编语言程序中,用 AREA伪指令定义一个段,并

25、说明所定义段的相关属性,本例 定义一个名为In it的代码段,属性为只读。ENTRY伪指令标识程序的入口点,接下来是指令序列,程序的末尾为 END伪指令,该伪指令告诉编译器源文件的结束,每一个汇编程序 段都必须有一条END伪指令,指示代码段的结束。432汇编语言的子程序调用在ARM汇编语言程序中,子程序的调用一般都是通过BL指令来实现的。在程序中,使用指令“ BL子程序名”即可完成子程序的调用。该指令在执行时完成如下操作:将子程序的返回地址存放在链接寄存器LR中,同时将程序计数器 PC指向子程序的入口点,当子程序执行完毕返回调用处时,只需要将存放在 LR中的返回地址重新复制给程序计数器PC即可

26、。在调用子的同时,也可以完成参数的传递和从子程序返回运算的结果,通常可以使用寄存器R0 R3完成。以下是使用 BL指令调用子程序的汇编语言程序的基本结构:In it ,CODE , READONL YAREAENTRYStartP RINTTEXTLDRR0,=0x3FF5000LDRR1,0xFFSTRR1,R0LDRR0,=0x3FF5008LDRR1,0x01STRR1,R0BLPRINT TEXTMOVPC, BLEND433宏定义及其作用使用宏定义可以提高程序的可读性,简化程序代码和同步修改。 语言的#define相似,只在源程序中进行字符的简单替代。宏定义从 到MEND结束,并可以

27、使用参数。宏首先要定义,然后才能使用。使用时直接书写宏名, 并根据对应的宏定义格式设置输 入参数或书写桔等。当源程序被汇编时, 汇编器将展开每一个宏调用, 用宏定义代替程序中 的宏调用,并使用实际的参数值取代宏定义时的形参。下面的例子是一个宏调用,程序中定义了一个宏 所需要调用的子程序名$ 是MOV指令,所以$ARM宏定义与标准CMACRO伪指令开始,CALL,用于调用子程序,调用时设置Function及两个入口参数$ dat1和$ dat2。由于宏定义体中使用的 dat1参数只能为8位的立即数或通用寄存器。MACROCALLSubfu nction数LMPORTMOV R0,MOV R1 ,

28、;宏定义$ Function , $ dat1, $ dat2 ;宏名为 CALLSubfunction,带 3 个参$ Function$ dat1$ dat2;声明外子程序名;设置子程序参数R0= $ dat1BL FunctionMEND;调用子程序CALL FADD1 , #3, #2;宏调用汇编处理后,宏调用将被展开,程序如下:IMP ORTMOVMOVBLFADD1RO, #3R1, #2FADD14.3.4数据比较跳转汇编程序可以使用 CMP指令进行两个数的比较,然后根据比较结果实现程序的跳转, 代码如下:CMP R5, #10BEQBRANCH1;如果R5为10,则跳转至U B

29、RANCH1CMPR1,R2ADDHIR1,R1,#1;如果R1R2,则 R1=R1+1ADDLSR1,R1,#2;如果R1=R2,则 R1=R1+2ANDSR1,R1,#0x80;R1=R1 &0x80,并设置相应的标志位BNEWAIT;如果R1的第7位0,则跳转到 WAIT4.3.5循环下面的程序代码为汇编循环程序的例子,指定了循环的次数,每循环一次进行减1操作,并判断结果是否为R0,0,如果为0则退出循环。#10MOVLOOPSUBSBENRO,LOOPRO, #1436数据块复制LDRR0, =DATA_DST;指向数据的目标地址LDRR1 , =DATA_SRC;指向数据源地址MOV

30、R1 , #10;复制数据块的大小为LOOPLDMIA R1 ! , R2-R9STMIAR0!, R2-R9SUBSR10 , R10, #1BNELOOP4.3. 7堆栈操作LDM/STM 进行读取和存储,进行数据块的复制,示例代码10*N个字节可以使用存储器访问指令 如下:可以使用存储器访问指令LDM/STM 实现堆栈操作,用于子程序的寄存器保护。在使用堆栈前,首先需要分配好堆栈空间,设置好寄存器R13(即堆栈指针SP),否则操作会失败。OUTDATSTMFDSP! R0-R7;寄存器入栈BL DELAYLDMFD SP! R0-R7,PC ;寄存器出栈438查表操作查表操作是汇编程序经常使用

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论