ARM汇编语言源程序格式来源:MCU嵌入式领域常用ARM源程序文件类型汇编语言程序的结构1汇编语言程序的结构2汇编语言程序的结构3汇编语言程序的结构4ARM的汇编语言程序一般由几个段组成,每个段均由AREA伪操作定义。段可以分为多种,如代码段、数据段、通用段,每个段又有不同的属性,如代码段的默认属性为READONLY,数据段的默认属性为READWRITE。本程序定义了两个段,第一个段为代码段codesec,它在存储器中存放用于程序执行的代码以及main函数的本地字符串;第二个段为数据段constdatasec,存放了全局的字符串,由于本程序没有对数据进行写操作,该数据段定义属性为READONLY。汇编语言的行构成1格式:[标签]指令/伪操作/伪指令操作数[;语句的注释]所有的标签必须在一行的开头顶格写,前面不能留空格,后面也不能跟C语言中的标签一样加上“:”;ARM汇编器对标识符的大小写敏感,书写标号及指令时字母的大小写要一致;注释使用“;”符号,注释的内容从“;”开始到该行的结尾结束汇编语言的行构成2标签标签是一个符号,可以代表指令的地址、变量、数据的地址和常量。一般以字母开头,由字母、数字、下划线组成。当符号代表地址时又称标号,可以以数字开头,其作用范围为当前段或者在下一个ROUT伪操作之前。指令/伪操作指令/伪操作是指令的助记符或者定义符,它告诉ARM的处理器应该执行什么样的操作或者告诉汇编程序伪指令语句的伪操作功能。汇编语言的标号1标号代表地址。标号分为段内标号和段外标号。段内标号的地址值在汇编时确定,段外编号的地址值在链接时确定。在程序段中,标号代表其所在位置与段首地址的偏移量。根据程序计数器(PC)和偏移量计算地址即程序相对寻址。在映像中定义的标号代表标号到映像首地址的偏移量。映像的首地址通常被赋予一个寄存器,根据该寄存器值与偏移量计算地址即寄存器相对寻址。例如:loopSUBSr0,r0,#1;每次循环使r0=r0-1BNEloop;跳转到loop标号去执行汇编语言的标号2在宏中也可以使用局部符号。局部标号是0~99的十进位数开始,可以重复定义。局部标号引用格式:%{F|B}{A|T}N{routname}%:局部标号引用操作。F:编译器只向前搜索。B:编译器只向后搜索。A:编译器搜索宏的所有嵌套层次。T:编译器搜索宏的当前层。例如:01SUBSr0,r0,#1;每次循环使r0=r0-1BNE%B01;跳转到01标号去执行汇编语言的常量常量:其值在程序运行过程中不能被改变的量。(1)数字常量:数字常量有3种表示方式:十进制数,如1、2、123十六进制数,如0x123,0xabcn进制数,形式为n_XXX,n的范围是2到9,XXX是具体数字(2)字符常量:由单引号及中间的字符组成,包括C语言中的转义字符,如’a’,’\n’(3)字符串常量:由一对双引号及中间的字符串表示,中间也可以使用C语言中的转义字符,比如:“abcdef\0xa\r\n”(4)逻辑常量:{TRUE},{FALSE},注意带大括号汇编程序的变量代换1这里所说的变量,是相对于汇编程序的“变量”,是用于汇编程序进行处理的,但一旦编译到程序中,则不会改变,成为常量。在字符串变量的前面有一个$字符,在汇编时编译器将用该字符串变量的内容代替该串变量。在数字变量前面有一个代换操作符“$”,编译器会将该数字变量的值转换为十六进制的字符串,并用该十六进制的字符串代换“$”后的数字变量。需要将“$”字符加入到字符串中,可以用“$$”代替,此时编译器将不再进行变量代换,而是把“$$”看作一个“$”。在两个“|”之间的“$”并不进行变量的代换,但如果“|”在双引号内,则将进行变量代换。使用“.”来表示字符串中变量名的结束。汇编程序的变量代换2字符串“aaastr1$str1.l1$l1,a1$num1.ccc”中的3个变量将在编译时被替换。程序运行后看到下面结果:aaastr1:bbbl1:T,a1:0000004Fccc伪指令在ARM汇编语言源程序中有些特殊助记符,它们没有相对应的操作码或者机器码,通常称为伪指令,它们所完成的操作称为伪操作。伪指令在源程序中的作用是为完成汇编程序作各种准备工作的,由汇编程序在源程序的汇编期间进行处理,仅在汇编过程中起作用。在ARM的汇编程序中,有如下几种伪指令:符号定义伪指令数据定义伪指令汇编控制伪指令信息报告伪指令宏指令以及其他伪指令符号定义伪指令作用:用于定义ARM汇编程序中的变量、对变量赋值以及定义寄存器的别名等。符号定义有如下几种伪指令:用于定义局部变量的LCLA、LCLL和LCLS。用于定义全局变量的GBLA、GBLL和GBLS。用于对变量赋值的SETA、SETL和SETS。为通用寄存器列表定义名称的RLIST。符号定义伪指令1-1(1)LCLA、LCLL和LCLS格式:LCLA/LCLL/LCLS局部变量名说明:LCLA、LCLL和LCLS伪指令用于定义一个汇编程序中的局部变量并初始化。其中:LCLA定义一个局部的数字变量,初始化为0。LCLL定义一个局部的逻辑变量,初始化为F。LCLS定义一个局部的字符串变量,初始化为空串。这3条伪指令用于声明局部变量,在其局部作用范围内变量名必须惟一,例如在宏内。符号定义伪指令1-2符号定义伪指令2-12)GBLA、GBLL和GBLS格式:GBLA/GBLL/GBLS变量名说明:GBLA、GBLL和GBLS伪操作定义一个汇编程序中的全局变量并初始化。其中:GBLA定义一个全局数字变量,并初始化为0。GBLL定义一个全局逻辑变量,并初始化为F。GBLS定义一个全局字符串变量,并初始化为空串。这3条伪指令用于定义全局变量,因此在整个程序范围内变量名必须惟一。符号定义伪指令2-2例如:GBLAnum1;定义一个全局的数字变;量,变量名为num1num1SETA0xabcd;将该变量赋值为0xabcdGBLLl2;定义一个全局的逻辑变;量,变量名为l2l2SETL{FALSE};将该变量赋值为假GBLSstr3;定义一个全局的字符串变;量,变量名为str3str3SETSHello!;将该变量赋值为“Hello!”符号定义伪指令3-1(3)SETA、SETL和SETS格式:变量名SETA/SETL/SETS表达式说明:SETA:给一个数字变量赋值。SETL:给一个逻辑变量赋值。SETS:给一个字符串变量赋值。格式中的变量名必须为已经定义过的全局或局部变量,表达式为将要赋给变量的值。符号定义伪指令3-2例如:LCLAnum1;定义一个局部的数字;变量,变量名为num1num1SETA0x1234;将该变量赋值;为0x1234LCLSstr3;定义一个局部的字符串变;量,变量名为str3str3SETS“Hello!”;将该变量赋值为;“Hello!”符号定义伪指令44)RLIST格式:名称RLIST{寄存器列表}说明:RLIST可用于对一个通用寄存器列表定义名称,该名称可在ARM指令LDM/STM中使用。在LDM/STM指令中,列表中的寄存器为根据寄存器的编号由低到高访问次序,与列表中的寄存器排列次序无关。例如:pblockRLIST{R0-R3,R7,R5,R9};将寄存器列表名称定义为pblock,可在ARM指令;LDM/STM中通过该名称访问寄存器列表数据定义伪指令作用:为数据分配存储单元,同时初始化。有如下几种:DCB字节分配DCW/DCWU半字(2字节)分配DCD/DCDU字(4字节)分配DCQ/DCQU8个字节分配DCFS/DCFSU单精度浮点数分配DCFD/DCFDU双精度浮点数分配SPACE分配一块连续的存储单元FIELD定义一个结构化的内存表的数据域MAP定义一个结构化的内存表首地址数据定义伪指令1(1)DCB格式:标号DCB表达式说明:分配一块字节单元并用伪指令中指定的表达式进行初始化。表达式可以为使用双引号的字符串或0~255的数字。DCB可用“=”代替。例如:Array1DCB1,2,3,4,5;数组str1DCBYourarewelcome!;构造字符串并分配空间数据定义伪指令2(2)DCW/DCWU格式:标号DCW/DCWU表达式说明:DCW分配一段半字存储单元并用表达式值初始化,它定义的存储空间是半字对齐的。DCWU功能与DCW类似,只是分配的字存储单元不严格半字对齐。例如:Arrayw1DCW0xa,-0xb,0xc,-0xd;构造固定数组并分配半字存储单元数据定义伪指令3(3)DCD/DCDU格式:标号DCD/DCDU表达式说明:DCD伪指令用于分配一块字存储单元并用伪指令中指定的表达式初始化,它定义的存储空间是字对齐的。DCD也可用“&”代替。DCDU功能与DCD类似,只是分配的存储单元不严格字对齐。例如:Arrayd1DCD1334,234,345435;构造固定数组并分配字为单元的存储单元LabelDCDstr1;该字单元存放str1的地址数据定义伪指令4(4)DCQ/DCQU格式:标号DCQ/DCQU表达式说明:DCQ用于分配一块以8个字节为单位的存储区域并用伪指令中指定的表达式初始化,它定义的存储空间是字对齐的。DCQU功能与DCQ类似,只是分配的存储单元不严格字对齐。例如:Arrayd1DCQ234234,98765541;构造固定数组并分配字为单元的存储空间。;注意:DCQ不能给字符串分配空间数据定义伪指令5(5)DCFD/DCFDU格式:标号DCFD/DCFDU表达式说明:DCFD用于为双精度的浮点数分配一片连续的字存储单元并用伪指令中指定的表达式初始化,它定义的存储空间是字对齐的。每个双精度的浮点数占据两个字单元。DCFDU功能与DCFD类似,只是分配的存储单元不严格字对齐。例如:Arrayf1DCFD6E2Arrayf2DCFD1.23,1.45数据定义伪指令6(6)DCFS/DCFSU格式:标号DCFS/DCFSU表达式说明:DCFS用于为单精度的浮点数分配一片连续的字存储单元并用表达式初始化,它定义的存储空间是字对齐的。每个单精度浮点数使用一个字单元。DCFSU功能与DCFS类似,只是分配的存储单元不严格字对齐。例如:Arrayf1DCFS6E2,-9E-2,-.3Arrayf2DCFSU1.23,6.8E9数据定义伪指令77)SPACE格式:标号SPACE表达式说明:SPACE用于分配一片连续的存储区域并初始化为0,表达式为要分配的字节数。SPACE也可用“%”代替。例如:freespaceSPACE1000;分配1000字节的存储空间数据定义伪指令8(8)MAP格式:MAP表达式[,基址寄存器]说明:MAP定义一个结构化的内存表的首地址。此时,内存表的位置计数器{VAR}(汇编器的内置变量)设置成该地址值。“^”可以用来代替MAP。表达式可以为程序中的标号或数学表达式,基址寄存器为可选项,当基址寄存器选项不存在时,表达式的值即为内存表的首地址,当该选项存在时,内存表的首地址为表达式的值与基址寄存器的和。MAP可以与FIELD伪操作配合使用来定义结构化的内存表。例如:MAP0x130,R2;内存表首地址为0x130+R2数据定义伪指令9(9)FIELD格式:标号FIELD字节数说明:FIELD用于定义一个结构化内存表中的数据域。“#”可用来代替FIELD。FIELD常与MAP配合使用来定义结构化的内存表:FIELD伪指令定义内存表中的各个数据域,MAP则定义内存表的首地址,并为每个数据域指定一个标号以供其他的指令引用。需要注意的是MAP和FIELD伪指令仅用于定义数据结构,并不分配存储单元。例如:MAP0xF10000;定义结构化内存表首地址为0xF10000countFIELD4;定义count的长度为4字节,位置为0xF1000+0xFIELD4;定义x的长度为4字节,位置为0xF1004yFIELD4;定义y的长度为4字节,位置为0xF1008汇编控制伪指令作用:指引汇编程序的执行流程。常用的伪操作包括:(1)