您好,欢迎访问三七文档
当前位置:首页 > 行业资料 > 其它行业文档 > 第4章 ARM汇编语言程序设计
第四章ARM汇编语言程序设计廖京盛茂名学院计算机与电子信息学院自动化系电气教研室ARM程序设计基础4.1.伪操作和伪指令4.2.ARM汇编语言语句格式4.3.ARM汇编语言的程序格式4.4.相关的程序示例主要内容4.1.1概念4.1.2ARM汇编伪指令4.1.3ARM汇编伪操作一、符号定义伪操作二、数据定义伪操作三、汇编控制伪操作四、其它伪操作4.1.4ARM汇编宏指令4.1ARM汇编伪指令和伪操作4.1.1伪指令、伪操作和宏指令概念伪指令——是汇编语言程序里的特殊指令助记符,在汇编时被合适的机器指令替代。伪操作——为汇编程序所用,在源程序进行汇编时由汇编程序处理,只在汇编过程起作用,不参与程序运行。宏指令——通过伪操作定义的一段独立的代码。在调用它时将宏体插入到源程序中。也就是常说的宏。说明:所有的伪指令、伪操作和宏指令,均与具体的开发工具中的编译器有关,当前主要采用ARM公司的“ADS/SDTIDE”开发工具,所以后面的讨论,均是基于ARM公司的开发工具。4.1.2ARM汇编伪指令ARM伪指令不属于ARM指令集中的指令,是为了编程方便而定义的。伪指令可以像其它ARM指令一样使用,但在编译时这些指令将被等效的ARM指令代替。ARM伪指令有四条,分别是:ADR:小范围的地址读取伪指令。ADRL:中等范围的地址读取伪指令。LDR:大范围的地址读取伪指令。NOP:空操作伪指令。一、ADR——小范围的地址读取ADR伪指令功能:将基于PC相对偏移的地址值或基于寄存器相对偏移的地址值读取到寄存器中。ADR伪指令功能的实现方法:在汇编编译器编译源程序时,ADR伪指令被编译器替换成一条合适的指令。通常,编译器用一条ADD指令或SUB指令来实现此ADR伪指令的功能,若不能用一条指令实现,则产生错误,编译失败。语法格式:ADR{cond}register,expr其中:register:加载的目标寄存器。expr:地址表达式。地址非字对齐,-255~255地址字对齐,-1020~1020例1:……(0x20)ADRR1,Delay……Delay(0x64)MOVR0,R14……使用ADR将程序标号Delay所表示的地址存入R1。编译后的反汇编代码:……ADDR1,PC,#0x3C……MOVR0,R14PC+0x3C=0x20+0x08+0x3C=0x64例2:查表ADRR0,D_TAB;加载转换表地址LDRBR1,[R0,R2];使用R2作为参数,进行查表……D_TABDCB0xC0,0xF9,0xA4,0xB0,0x99,0x92二、ADRL——中等范围的地址读取ADRL伪指令功能:将基于PC相对偏移的地址值或基于寄存器相对偏移的地址值读取到寄存器中,比ADR伪指令可以读取更大范围的地址。ADRL伪指令功能实现方法:在汇编编译器编译源程序时,ADRL被编译器替换成两条合适的指令。若不能用两条指令实现,则产生错误,编译失败。语法格式:ADRL{cond}register,expr其中:register:加载的目标寄存器。expr:地址表达式。地址非字对齐,-64KB~64KB地址字对齐,-256KB~256KB例3:……(0x20)ADRLR1,Delay……Delay(0x64)MOVR0,R14……使用ADRL将程序标号Delay所表示的地址存入R1。编译后的反汇编代码:……ADDR1,PC,#0x3CADDR1,R1,#0……MOVR0,R14ADRL伪指令被汇编成两条指令,尽管第2条指令并没有意义。ADRL-中等范围的地址读取伪指令示例:startMOVr0,#10;PC值为当前指令地址值加8字节ADRLr4,start+60000;本ADRL伪指令将被编译器替换成下面两条指令;ADDr4,pc,#0xe800;ADDr4,r4,#0x254;60000=0xEA60三、LDR——大范围的地址读取LDR伪指令功能:用于加载32位立即数或一个地址值到指定的寄存器。LDR伪指令功能实现方法:在汇编编译源程序时,LDR伪指令被编译器替换成一条合适的指令。若加载的常数未超过MOV或MVN的范围,则使用MOV或MVN指令代替该LDR伪指令;否则汇编器将常量放入文字池,并使用一条程序相对偏移的LDR指令从文字池读出常量。语法格式:LDR{cond}register,=expr其中:Register:加载的目标寄存器。expr:32位常量或地址表达式。例4:……(0x060)LDRR1,=Delay……Delay(0x102)MOVR0,R14……使用LDR将程序标号Delay所表示的地址存入R1。编译后的反汇编代码:……LDRR1,stack……DelayMOVR0,R14……LTORGstackDCD0x102LDR伪指令被汇编成一条LDR指令,并在文字池中定义一个常量,该常量为标号Delay的地址。注意:从指令位置到文字池的偏移量必须小于4KB。与ARM指令的LDR的区别:伪指令LDR的参数有“=”号。四、NOP——空操作伪指令NOP伪指令功能实现方法:在汇编时将被替代成ARM中的空操作,比如可能是“MOVR0,R0”指令等。用途:NOP可用于延时操作。语法格式:NOP例:延时子程序DelayNOP;空操作NOPNOPSUBSR1,R1,#1;循环次数减1BNEDelayMOVPC,LR4.1.3ARM汇编伪操作ADS编译环境下的伪操作可分为以下几类:1.符号定义(SymbolDefinition)伪操作2.数据定义(DataDefinition)伪操作3.汇编控制(AssemblyControl)伪操作4.其它(Miscellaneous)伪操作符号定义伪指令符号定义(SymbolDefinition)伪指令用于定义ARM汇编程序中的变量、对变量赋值以及定义寄存器的别名等操作。常见的符号定义伪指令有如下几种:-用于定义全局变量的GBLA、GBLL和GBLS。-用于定义局部变量的LCLA、LCLL和LCLS。-用于对变量赋值的SETA、SETL、SETS。-为通用寄存器列表定义名称的RLIST。符号定义伪指令1、GBLA、GBLL和GBLS语法格式:GBLA(GBLL或GBLS)全局变量名GBLA、GBLL和GBLS伪指令用于定义一个ARM程序中的全局变量,并将其初始化。GBLA伪指令用于定义一个全局的数字变量,并初始化为0;GBLL伪指令用于定义一个全局的逻辑变量,并初始化为F(假);GBLS伪指令用于定义一个全局的字符串变量,并初始化为空;由于是定义全局变量,因此在整个程序范围内变量名必须唯一。GBLATest1;定义一个全局的数字变量,变量名为Test1Test1SETA0xaa;将该变量赋值为0xaa,’a’;GBLLTest2;定义一个全局的逻辑变量,变量名为Test2Test2SETL{TRUE};将该变量赋值为真GBLSTest3;定义一个全局的字符串变量,变量名为Test3Test3SETS“Testing”;将该变量赋值为“Testing”符号定义伪指令2、LCLA、LCLL和LCLS语法格式:LCLA(LCLL或LCLS)局部变量名LCLA、LCLL和LCLS伪指令用于定义一个ARM程序中的局部变量,并将其初始化。LCLA伪指令用于定义一个局部的数字变量,并初始化为0;LCLL伪指令用于定义一个局部的逻辑变量,并初始化为F(假);LCLS伪指令用于定义一个局部的字符串变量,并初始化为空;由于是用于声明局部变量,在其作用范围内变量名必须唯一。LCLATest4;声明一个局部的数字变量,变量名为Test4Test4SETA0xaa;将该变量赋值为0xaaLCLLTest5;声明一个局部的逻辑变量,变量名为Test5Test4SETL{TRUE};将该变量赋值为真LCLSTest6;定义一个局部的字符串变量,变量名为Test6Test6SETS“Testing”;将该变量赋值为“Testing”符号定义伪指令3、SETA、SETL和SETS语法格式:变量名SETA(SETL或SETS)表达式伪指令SETA、SETL、SETS用于给一个已经定义的全局变量或局部变量赋值。其中,变量名为已经定义过的全局变量或局部变量,表达式为将要赋给变量的值。SETA伪指令用于给一个数学变量赋值;SETL伪指令用于给一个逻辑变量赋值;SETS伪指令用于给一个字符串变量赋值;LCLATest3;声明一个局部的数字变量,变量名为Test3Test3SETA0xaa;将该变量赋值为0xaaLCLLTest4;声明一个局部的逻辑变量,变量名为Test4Test4SETL{TRUE};将该变量赋值为真符号定义伪指令4、RLIST语法格式:名称RLIST{寄存器列表}RLIST伪指令可用于对一个通用寄存器列表定义名称,使用该伪指令定义的名称可在ARM指令LDM/STM中使用。在LDM/STM指令中,列表中的寄存器访问次序为根据寄存器的编号由低到高,而与列表中的寄存器排列次序无关。RegListRLIST{R0-R5,R8,R10};将寄存器列表名称定义为RegList,可在ARM指令LDM/STM中通过该名称访问寄存器列表。4.1.3ARM汇编伪操作ADS编译环境下的伪操作可分为以下几类:1.符号定义(SymbolDefinition)伪操作2.数据定义(DataDefinition)伪操作3.汇编控制(AssemblyControl)伪操作4.其它(Miscellaneous)伪操作数据定义伪操作LTORG:声明一个数据缓冲池的开始。SPACE:分配一块内存单元,并用0初始化。MAP:定义一个结构化的内存表的首地址。FIELD:定义结构化内存表中的一个数据域。DCB:分配一段字节内存单元,并初始化。DCD、DCDU:分配一段字内存单元,并初始化。1、LTORG用于声明一个数据缓冲池(文字池)的开始。语法格式:LTORG例:startBLfunc……funcLDRR1,=0x8000;子程序……MOVPC,LR;子程序返回LTORG;定义数据缓冲池&0x8000DataSPACE4200;从当前位置开始分配4200字节的内存单元,并初始化为0。END默认数据缓冲池为空注意:LTORG伪操作通常放在无条件跳转指令之后,或者子程序返回指令之后,这样处理器不会错误地将数据缓冲池中的数据当作指令来执行。通常ARM汇编编译器把数据缓冲池放在代码段的最后面,即下一个代码段开始之前,或者END伪操作之前。2、SPACE——也可以用符号“%”表示用于分配一块连续的内存单元供程序使用,并且将这个内存单元的内容初始化为0。语法格式:{label}SPACEexpr或{label}%expr其中:{label}:是一个标号,可选项。expr:数值表达式,用来规定内存单元的字节数。例:AREADataSpace,Data,READWRITEdata1SPACE256;定义大小为256字节的数据区3、MAP、FIELD使用MAP和FIELD伪操作描述数据结构。MAP用于定义数据结构的起始地址;FIELD用于定义结构中的字段(各数据域的字节长度),并可为每一个数据域指定一个标号,其它指令可引用此标号。注:MAP和FIELD伪操作只是定义数据结构并不实际分配内存单元。(1)MAP——也可以用符号”^”表示语法格式:MAPexpr{,base-register}或^expr{,base-register}其中:expr:数据表达式或程序中的标号(使用MAP之前已定义)。base-register:基址寄存器若指令中没有此项时,expr为结构的首地址。(基于绝对地址的数据结构)若指令中包含此项时,expr+base-register的和为结构首地址。(基于相对地址的数
本文标题:第4章 ARM汇编语言程序设计
链接地址:https://www.777doc.com/doc-4822594 .html