1TM第6章ARM汇编伪指令与伪操作汇编语言程序设计时所用的ARM/Thumb汇编语言伪指令;由ARM公司推出的开发工具所支持的伪操作。本章主要内容2TM2内容提要6.1汇编语言伪指令6.2ARM汇编语言伪操作6.3ARM汇编伪操作6.4GNUARM汇编伪操作3TM36.1汇编语言伪指令伪指令:汇编语言源程序里的特殊助记符,它不在处理器运行期间执行,而是在汇编时将被合适ARM或Thumb指令代替,从而实现真正的指令操作。4TM43.ADRADR{cond}register,expression功能:小范围地址读取伪指令将基于PC相对偏移的地址值或基于寄存器相对偏移的地址值读取到寄存器中。5TM5下列指令存放在0x8000起始的地址单元,分析汇编后的结果。.global_start.text_start:MOVR0,#0x0FADRR0,_start.end解:汇编后的结果为:0x00008000MOVR0,#0x0F0x00008004SUBR0,PC,#126TM62.ADRLADRL{cond}register,expression功能:中等范围地址读取伪指令它将基于PC相对偏移的地址值或基于寄存器相对偏移的地址值读取到寄存器中。7TM7汇编器在处理源程序时,ADRL伪指令被两条具有ADRL等同功能的ARM指令(通常用ADD或SUB指令)替代。如果不能用两条指令实现ADRL伪指令的功能,则编译器报告错误,编译失败。8TM8以下指令存放在0x8000起始的地址单元,分析汇编后的结果。.global_start.text_start:MOVR0,#0x0FADRLR0,_start.end解:汇编后的结果为:0x00008000MOVR0,#0x0F0x00008004SUBR0,PC,#120x00008008NOP(MOVR0,R0)9TM9ARM汇编语言伪指令1.LDRLDR{cond}register,=expression功能:大范围地址读取伪指令将一个32位的常数或者一个地址值读取到寄存器中,可以看作是加载寄存器的内容。10TM10如果加载的常数符合MOV或MVN指令立即数的要求,则用MOV或MVN指令替代LDR伪指令。如果加载的常数不符合MOV或MVN指令立即数的要求,汇编器将常量放入内存文字池,并使用一条程序相对偏移的LDR指令从内存文字池读出常量。11TM11伪指令语句:LDRR0,=0x0AA00;R0—0x0AA00汇编后:MOVR0,#4352012TM12伪指令语句:LDRR0,=0x0AA00;R0—0x0AA00汇编后:MOVR0,#4352013TM134.空操作伪指令NOPNOP功能:空操作,在汇编时将会被替代成ARM中的空操作。作用:用于编写延时程序。14TM146.2ARM汇编语言伪操作伪操作(Directive)是ARM汇编语言源程序里的指令助记符,其作用是指导汇编程序对汇编语言源程序的编译操作。是编译器执行的指令,而不是ARM处理器执行的指令。伪操作只是汇编过程中起作用,一旦汇编结束,伪操作也就随之消失。与伪指令的区别15TM15目前常用的编译环境有2种:ARM公司推出的开发工具:ADS/SDT、RealViewMDK等GNUARM开发工具16TM161、ADS推出的开发工具ADS/SDT开发工具ADS由ARM公司推出,使用了CodeWarrior公司的编译器。针对ARM资源配置为用户提供了在CodeWarriorIDE集成环境下配置各种ARM开发工具的能力。17TM17RealViewMDK开发工具ARM将Keil公司收购之后,正式推出了针对ARM微控制器的开发工具RealViewMicrocontrollerDevelopmentKit(简称RealViewMDK或者MDK),它将ARM开发工具RealViewDevelopmentSuite(简称RVDS)的编译器RVCT与Keil的工程管理、调试仿真工具集成在一起,是一款非常强大的ARM微控制器开发工具。18TM182、GNUARM开发工具2.GNUARM开发工具GNU格式ARM汇编语言程序主要是面对在ARM平台上移植嵌入式Linux操作系统,GNU组织开发的基于ARM平台的编译工具有主要由GNU的汇编器as,交叉汇编器gcc和连接器ld组成。19TM196.3ARM汇编伪操作ARM公司推出的开发工具所支持的汇编伪操作包括符号定义伪操作、数据定义伪操作、汇编信息报告控制伪操作、汇编代码控制伪操作、文件包含伪操作、指令集类型标识伪操作以及其他功能伪操作。20TM20符号定义伪操作符号定义伪指令用于定义ARM汇编程序的变量,对变量进行赋值以及定义寄存器名称,该类伪指令包括:全局变量声明:GBLA,GBLL和GBLS局部变量声明:LCLA,LCLL和LCLS变量赋值:SETA,SETL和SETS为一个通用寄存器列表定义名称:RLIST为一个协处理器的寄存器定义名称:CN为一个协处理定义名称:CP为一个VFP寄存器定义名称:DN和SN为一个FPA浮点寄存器定义名称:FN21TM21局部变量定义LCLA、LCLL及LCLS语法格式LCLAvariableLCLLvariableLCLSvariable其中:variable所说明的局部变量名称。功能:LCLA伪指令用于声明一个局部的算术变量,并将其初始化为0LCLL伪指令用于声明一个局部的逻辑变量,并将其初始化为{FALSE}LCLS伪指令用于声明一个局部的字符串变量,并将其初始化为空字符串“”注意:在其作用范围内必须惟一,用于宏定义的体中.22TM22伪指令应用举例如下;MACRO;声明一个宏SENDDAT$dat;宏的原型LCLAbitno;声明一个局部算术变量…bitnoSETA8;设置变量值为8…MEND23TM23全局变量定义GCLA、GCLL及GCLS语法格式GCLAvariableGCLLvariableGCLSvariable其中:variable所说明的全局变量名称。24TM24全局变量定义GCLA、GCLL及GCLS语法格式GBLAvariableGBLLvariableGBLSvariable其中:variable定义的全局变量名称。功能:GBLA伪指令用于声明一个全局的算术变量,并将其初始化为0;GBLL伪指令用于声明一个全局的逻辑变量,并将其初始化为{FALSE};GBLS伪指令用于声明一个全局的字符串变量,并将其初始化为空字符串“”。注意:在其作用范围内必须惟一25TM25GBLLcodedbg;声明一个全局逻辑变量codebgSETL{TRUE};设置变量为{TRUE}26TM26变量赋值伪操作SETA、SETL及SETS语法格式variable_aSETAexpr_avariable_lSETLexpr_lvariable_sSETSexpr_s功能:SETA伪指令用于给一个全局/局部的算术变量赋值.SETL伪指令用于给一个全局/局部的逻辑变量赋值.SETS伪指令用于给一个全局/局部的字符串变量赋值27TM27其中variable_a算术变量.用GBLA,LCLA伪指令定义的变量.expr_a赋值的常数.variable_l逻辑变量.用GBLL,LCLL伪指令定义的变量.expr_l逻辑值,即{TRUE}或{FALSE}.variable_s字符串变量.用GBLS,LCLS伪指令定义的变量.expr_s赋值的字符串.28TM28GBLSErrStr…ErrStrSETS“No,semaphone”29TM29给通用寄存器列表定义名称RLIST语法格式nameRLIST{registers_list}其中:name寄存器列表的名称;registers_list通用寄存器列表。30TM30LoRegRLIST{R0-R7};定义寄存器列表LoRegSTMFDSP!,LoReg;保存寄存器列表LoReg31TM31数据定义伪操作数据定义伪操作一般用于为特定的数据分配存储单元,也可以完成已分配存储单元的初始化。32TM32数据定义伪操作该类伪指令如下;声明一个文字池:LTORG;定义一个结构化的内存表的首地址:MAP定义结构化内存表中的一个数据域:FIELD分配一块内存空间,并用0初始化:SPACE分配一段字节的内存单元,并用指定的数据初始化:DCB;分配一段字的内存单元,并用指定的数据初始化:DCD和DCDU;分配一段双字的内存单元,并用双精度的浮点数据初始化:DCFD和DCFDU;分配一段字的内存单元,并用单精度的浮点数据初始化:DCFS和DCFSU;分配一段双字的内存单元,并用64位整数数据初始化:DCQ和DCQU分配一段半字的内存单元,并用指定的数据初始化:DCW和DCWU;33TM33分配字节存储单元DCB语法格式{label}DCBexpr{,expr}…其中:label内存块起始地址标号;expr是-128~255之间的数字或字符串。功能:用于分配一段字节内存单元,并用伪指令中的expr初始化.=与DCB同义.34TM34DISPTABDCB0x33,0x43,0x76,0x12DCB-120,20,36,55ERRSTRDCB“Send,dataiserror!”,035TM35分配半字存储单元DCW及DCWU语法格式{label}DCWexpr{,expr}…{label}DCWUexpr{,expr}…其中:label内存块起始地址标号;expr是-32768~65535之间的数字表达式。功能DCW、DCWU用于分配一段字的内存单元,并用指定的数据expr初始化.DCW伪指令分配的内存需要字对齐.DCW分配的内存不需要字对齐.36TM36分配字存储单元DCD及DCDU语法格式:{label}DCDexpr{,expr}…{label}DCDUexpr{,expr}…其中:label内存块起始地址标号;expr表达式。功能:DCD、DCDU用于分配一段字内存单元,并用伪指令中的expr初始化。DCD伪指令分配的内存需要字对齐,DCDU伪指令分配的内存不需要字对齐。一般可用来定义数据表格或其它常数&与DCD同义.37TM37VectorsLDRPC,ReserAddrLDRPC,UndefinedAddr…ResetAddrDCDResetUndefinedAddrDCDUndefined…Reset38TM38分配双字存储单元DCQ及DCQU语法格式{label}DCQ{-}expr{,{-}expr}…{label}DCQU{-}expr{,{-}expr}…其中:label内存块起始地址标号;expr用于初始化内存的数字或表达式,其数值必须是整数。功能DCQ、DCQU用于分配一段双字的内存单元,并用64位的整数数据初始化.DCQ伪指令分配的内存需要字对齐.DCQU分配的内存不需要字对齐.39TM39DCQU1234,-7656879877640TM40声明数据缓冲池LTORG在使用LDR伪指令时,要在适当的位置加入LTROG声明数据缓冲池,这样就会把要加载的数据保存到缓存池中,再使用ARM加载指令读出,如果没有使用LTROG声明数据缓冲池,则汇编器会在程序末尾自动声明。41TM41声明数据缓冲池LTORG语法格式LTROG注意:LTORG伪指令常放在无条件跳转指令之后,或者子程序返回指令之后,这样处理器就不会错误地将文字池中的数据当作指令来执行.42TM42LDRR0,=0x12345678ADDR1,R1,R0MOVPC,LRLTORG;声明文字池,此地址存储0x12345678…;其它代码43TM43分配存储空间SPACE语法格式{label}SPA