您好,欢迎访问三七文档
ARM嵌入式系统第5章ARM汇编程序设计5.1汇编语言源程序助记符伪指令宏指令汇编指令和机器指令是“一一对应”的汇编语言程序需由汇编程序将其汇编为机器语言程序,才能被计算机执行。汇编语言大体上包括了汇编指令、系统调用和中断、伪指令和宏指令,汇编语言是强烈依赖硬件和汇编环境的。学习和使用汇编语言程序设计的原因指令语句(instructions)完成一定操作功能,能够翻译成机器代码的语句。伪指令语句(directives,指示性语句)为汇编程序在翻译汇编语言源程序时提供有关信息,并不翻译成机器代码。宏指令语句(marcos)可看成是由若干条指令语句形成的语句,一条宏指令语句的功能相当于若干条指令语句的功能。ARM程序设计基础伪指令宏与宏指令ARM汇编语言规范(语句、表达式和运算符)ARM汇编语言的程序格式5.2伪指令段定义标号符号定义伪指令数据定义伪指令汇编控制伪指令其他伪操作汇编语言程序示例AREABlock,CODE,READONLYnumEQU10ENTRYstartLDRR0,=srcLDRR1,=dstMOVR2,#numblockcopyLDRR3,[R0],#4STRR3,[R1],#4SUBSR2,R2,#1BNEblockcopyB.AREABlockData,DATA,READWRITEsrcDCD0,1,2,3,4,5,6,7,8,9dstSPACE10*4END符号定义伪指令定义全局变量:GBLA、GBLL和GBLS定义局部变量:LCLA、LCLL和LCLS变量赋值:SETA、SETL、SETS通用寄存器列表定义名称:RLISTGBLA、GBLL和GBLSGBLA、GBLL和GBLS语法格式:GBLA(GBLL或GBLS)全局变量名GBLAobjectsize;全局的数字变量objectsize,为0ObjectsizeSETA0xff;将该变量赋值为0xffSPACEobjectsize;引用该变量GBLLstatusB;全局的逻辑变量statusB,为{False}statusBSETL{TRUE};将该变量赋值为真全局:作用范围为包含该变量的源程序LCLA、LCLL和LCLSLCLA、LCLL和LCLS语法格式:LCLA(LCLL或LCLS)局部变量名MACRO;声明一个宏$labelmessage$a;宏的原型LCLSerr;声明一个局部变量err,为空串errSETS“errorno:”;向该变量赋值$label;代码INFO0,err:CC::STR:$a;使用该串变量MEND;宏定义结束局部:作用范围为包含该局部变量的宏代码的一个实例SETA、SETL、SETSSETA、SETL和SETS语法格式:变量名SETA(SETL或SETS)表达式在向变量赋值前,必须先声明该变量RLISTRLIST语法格式:名称RLIST{寄存器列表}ContextRLIST{r0-r6,r8,r10-r12,r15};将寄存器列表名称定义为Context,可在ARM指令LDM/STM中通过该名称访问寄存器列表。排列顺序无关数据定义伪指令DCBDCW(DCWU)DCD(DCDU)DCFD(DCFDU)DCFS(DCFSU)SPACEMAPFIELDDCB语法格式:{标号}DCB表达式表达式取值范围:-128~127;0~255的数字或字符串。DCB:“=”NullstringDCB“Nullstring”,0;构造一个以0结尾的字符串DCW(或DCWU)语法格式:{标号}DCW(或DCWU)表达式DCW:半字对齐DCWU:不严格半字对齐。表达式取值范围:-32768~32767;0~65535data1DCW-128,num1+8;num1必须是已经定义过的DCD(或DCDU)语法格式:{标号}DCD(或DCDU)表达式DCD:“&”DCD:字对齐DCDU:不严格字对齐。data1DCD1,5,20;其值为1,5,20data2DCDmemaddr+4;分配一个字单元,其值为程序中标号memaddr加4个字节DCFD(或DCFDU)语法格式:{标号}DCFD(或DCFDU)表达式每个双精度的浮点数占据两个字单元。DCFD:字对齐DCFDU:不严格字对齐DCFD1E308,-4E-100DCFDU100000,-.1,3.1E26DCFS(或DCFSU)语法格式:{标号}DCFS(或DCFSU)表达式每个单精度的浮点数占据一个字单元。DCFS:字对齐DCFSU:不严格字对齐DCFS1E3,-4E-9DCFSU1.0,-.1,3.1E6SPACE语法格式:{标号}SPACE表达式分配一片连续的存储区域并初始化为0。其中,表达式为要分配的字节数。SPACE:“%”DatastrucSPACE280;分配连续280字节的存储单元并初始化为0LTORG语法格式:{标号}LTORG说明某个存储区域是用来暂存数据的数据缓冲区——文字池或数据缓冲池。大的代码段也可以使用多个数据缓冲池。当程序中使用LDR之类的指令访问数据缓冲池时,为防止越界产生,通常把数据缓冲池放在代码段的后面,或者放在无条件跳转指令或子程序返回指令之后,使得处理器不会错误的将数据缓冲池中的数据当做指令来执行。AREAExample,CODE,READONLYStartBLFunc1…Func1LDRR1,=0x800MOVPC,LRLRORGDataSPACE40ENDMAP语法格式:MAP表达式{,基址寄存器}用于定义一个结构化的内存表的首地址。MAP:“^”通常与FIELD伪指令配合使用来定义结构化的内存表。MAPfun;定义结构化内存表,fun就是内存表的首地址MAP0x80,R9;定义结构化内存表首地址的值为0x80+R9FILED语法格式:{标号}FIELD表达式定义一个结构化内存表中的数据域。FILED也可用“#”代替。MAP0;定义结构化内存表首地址为0constaFIELD4;consta的长度为4字节,相对位置为0x0constbFIELD4;constb的长度为4字节,相对位置为0x4xFIELD8;x的长度为8字节,相对位置为0x8yFIELD8;y的长度为8字节,相对位置为0x10stringFIELD256;y的长度为256字节,相对位置为0x18MOVR9,#4096LDRR5,[R9,constb];将内存表中数据域constb读取到R5中汇编控制伪指令汇编控制(AssemblyControl)伪指令用于控制汇编程序的执行流程,常用的汇编控制伪操作包括以下几条:IF、ELSE、ENDIFWHILE、WENDIF、ELSE、ENDIF语法格式:IF逻辑表达式指令序列1ELSE指令序列2ENDIF示例:IFVersion=“1.0”;指令;伪指令ELSE;指令;伪指令ENDIFWHILE、WEND语法格式:WHILE逻辑表达式指令序列WEND示例:countSETA1WHILEcount=4countSETAcount+1;codeWEND其他常用的伪操作AREACODE16、CODE32ENTRYENDEQUIMPORTGET(或INCLUDE)AREA语法格式:AREA段名属性1,属性2,……定义一个代码段或数据段。常用的属性如下:CODE:用于定义代码段,默认为READONLY。DATA:用于定义数据段,默认为READWRITE。READONLY:指定本段为只读,代码段默认为READONLY。READWRITE:指定本段为可读可写,数据段的默认属性为READWRITE。示例:AREAExample,CODE,READONLY;codeCODE16、CODE32语法格式:CODE16(或CODE32)CODE16:其后的指令序列为16位的Thumb指令。CODE32:其后的指令序列为32位的ARM指令。示例:AREAChangeState,CODE,READONLYCODE32;指示下面的指令为ARM指令LDRr0,=start+1BXr0;切换到Thumb状态,并跳转到start处执行CODE16;指示下面的指令为Thumb指令startMOVr1,#10ENTRY语法格式:ENTRYENTRY伪操作用于指定汇编程序的入口点。在一个源文件里最多只能有一个ENTRY(可以没有)。在一个完整的汇编程序中至少要有一个ENTRY(当有多个ENTRY时,程序的真正入口点由链接器指定)。示例:AREAexample,CODE,READONLYENTRY;应用程序的入口点END语法格式:ENDEND伪指令用于通知编译器已经到了源程序的结尾。示例:AREAexample,CODE,READONLY……ENDEQU语法格式:名称EQU表达式{,类型}EQU:“*”示例:abcdEQU2;定义abcd符号的值为2abcdEQUlabel1+16;定义abcd符号的值(label1+16)IMPORT语法格式:IMPORT标号{[WEAK]}用于通知编译器要使用的标号在其他的源文件中定义,但要在当前源文件中引用。示例:AREAInit,CODE,READONLYIMPORTMain;通知编译器当前文件要引用标号Main,但Main在其他源文件中定义……ENDGET(或INCLUDE)语法格式:GET文件名用于将一个源文件包含到当前的源文件中,并将被包含的源文件在当前位置进行汇编处理。可以使用INCLUDE代替GET。使用方法与C语言中的“include”相似。示例:AREAexample,CODE,READONLYGETfile1.s;包含源文件file1.sGETC:\project\file2.s;包含源文件file2.sGETC:\Programfiles\file3.s;包含源文件file3.s5.3宏和宏指令宏:在汇编程序中可以用伪指令MACRO、MEND为一个程序段定义一个名称,在往后的程序中就可以通过这个名称来使用它所代表的程序段。在源程序被汇编时,该名称将被替换为它所代表的程序段。宏指令:在ARM中,还有一种汇编器内置的无参数和标号宏,我们把其称为宏指令。在汇编的时候,这些宏指令也是被替换成一条或两条真正的ARM或Thumb指令。ADR、ADRL、LDRMACRO、MEND语法格式:MACRO$标号宏名$参数1,$参数2,……;宏名为宏的名称,为宏在程序中引用名。;$参数1,$参数2,……为宏中可以使用的参数。指令序列;宏定义体MEND规定:$标号为主标号,宏内的所有其他的标号必须由主标号组成。宏中的所有标号必须在前面冠以符号$。宏中的参数在汇编时被相应的值替换。示例:在ARM中完成测试-跳转操作需要两条指令,定义一条宏指令完成测试-跳转操作MACRO$labelTestAndBranch$dest,$reg,$cc$label.A1CMP$reg,#0B$cc$destMENDMACRO、MEND;在程序中调用该宏testTestAndBranchNonZero,r0,NE……NonZero;程序被汇编后,宏展开的结果testCMPr0,#0BNENonZero……NonZeroMEXIT语法格式:MEXITMEXIT用于从宏定义中跳转出去。宏指令ADRADRLLDRNOPADR-小范围的地址读取伪指令语法格式ADR{cond}register,exprcond:可选的指令执行条件register:目标寄存器expr:基于PC或寄存器的地址表达式,取值范围:地址非字对齐,-255~255地址字对齐,-1020~1020将基于PC或寄存器的地址值读取到寄存器中。ADR伪指令被替换成一条合适的指令(ADD指令或SUB指令)。如果不能用一条来实现ADR伪指令的功能,编译器将报告错误。ADR-小范围的地址读取伪指令示例:startMOVr0,#10;PC值为当前指令地址值加8字节ADRr4
本文标题:ARM汇编程序设计
链接地址:https://www.777doc.com/doc-23696 .html