您好,欢迎访问三七文档
当前位置:首页 > 行业资料 > 其它行业文档 > ARM汇编语言程序设计基础.ppt
XUPT嵌入式系统原理与应用第四章ARM汇编语言程序设计基础目录4.1ARM汇编语言的程序结构4.2ARM汇编语言程序设计4.3C与汇编混合编程本章小结24.1ARM汇编语言的程序结构本章通过一个完整的ARM汇编例子入手,给出了ARM汇编程序的基本框架,并详细介绍了编写汇编程序常用的汇编器伪指令,具备了这些基础知识,学生就能自己动手编写汇编程序。4.1.1一个简单的ARM汇编程序例子4.1.2汇编器伪指令4.1.3汇编语言的规范4.1.1一个简单的ARM汇编程序例子4一段完整的ARM汇编语言程序,由若干个段组成,段可以分为代码段和数据段,代码段的内容为执行代码,数据段存放代码运行时需要用到的变量。程序框架可抽象如下:AREA代码段名字,CODE,READONLYENTRYCODE32;添加用户代码AREA数据段名字,DATA,READWRITE;添加用户数据END指令和汇编器伪指令的比较①指令语句:在汇编后能产生目标代码的语句,CPU可以执行并能完成一定的功能,例如MOV,ADD等;②汇编器伪指令:在汇编后不产生目标代码的语句,仅在汇编过程中告诉汇编器如何汇编。汇编器伪指令的作用包括:定义数据、分配存储区、定义段、定义宏、定义子程序等。一旦汇编结束,它们的使命就完成了。4.1.2汇编器伪指令在ARM的汇编程序中,有如下几种汇编器伪指令:符号定义伪指令,数据定义伪指令,段定义伪指令,模块控制伪指令,汇编控制伪指令,宏处理伪指令等。1.段定义相关伪指令AREA语法格式:AREA段名属性1,属性2,……程序4-1中使用如下语句定义段:AREAMAIN,CODE,READONLY;定义代码段,名字为MAINAREANUM,DATA,READWRITE;定义数据段,名字为NUMAREA伪指令用于定义一个代码段或数据段。其中,段名若以数字开头,则该段名需用“|”括起来,如|1_data|。属性字段表示该代码段(或数据段)的相关属性,例如:CODE(定义代码段),DATA(定义数据段),READONLY(只读),READWRITE(读写)。多个属性用逗号分隔。一个汇编程序至少应该有一个代码段,由具体的设计需求,也可由多个代码段和数据段组成,多个段在程序汇编链接时最终形成一个可执行的映象文件。可执行映象文件通常由以下几部分构成:①一个或多个代码段,代码段的属性为只读。②零个或多个包含初始化数据的数据段,数据段的属性为可读写。③零个或多个不包含初始化数据的数据段,数据段的属性为可读写。ENTRYENTRY用于指示程序的入口,其后紧跟着第一条可执行语句。CODE16/CODE32CODE16用于通知汇编器,本语句后面的指令序列为16位的Thumb指令。CODE32用于通知汇编器,本语句后面的指令序列为32位的ARM指令。ENDEND用于指示程序的结束,每一个汇编源程序都必须以END语句结束,以通知汇编器结束汇编。2.数据定义伪指令DCB(Define?Byte)语法格式(方括号内的内容为可选项):标号DCB表达式[,表达式]……DCB用于在内存中分配一片连续的字节单元,并用表达式进行初始化。每个表达式可以是数字或字符串,数字的范围在0~255内,也可以为算术表达式,例如:StrDCB“HelloWorld!”num_bDCB2+3,3*5字符串只能用DCB定义。0x48(‘H’)0x65(‘e’)0x6C(‘l’)0x6C(‘l’)0x6F(‘o’)0x20(‘’)0x57(‘W’)0x6F(‘o’)0x72(‘r’)str0x6C(‘l’)0x64(‘d’)0x21(‘!’)0x050x0Fnum_bDCW(Define?Word)语法格式:标号DCW表达式[,表达式]……DCW用于在内存中分配一片连续的半字单元,并用指定的表达式进行初始化。这些分配的内容是半字对齐的。其中表达式可以为程序标号或者数字表达式。例如:num_wDCW0x1234,0x56780x340x120x780x56num_wDCD(Define?Doubleword)语法格式:标号DCD表达式[,表达式]……DCD用于在内存中分配一片连续的字单元,并用指定的表达式进行初始化。这些分配的内容是字对齐的。其中表达式可以为程序标号或者数字表达式。例如:num_dDCD-5,0x90abcdef0xFB0xFF0xFF0xFF0xEF0xCD0xABnum_d0x90SPACE语法格式:标号SPACE表达式SPACE用于分配一片连续的存储区域并初始化为0。其中,表达式为要分配的字节数。例如:dataSPACE1024;分配1024个字节空间并初始化为0LTORGLTORG用于声明一个文字池,用来存放常量,特别是不符合8位位图数据标准的常数。其使用情景及实例见本章的4.2.1节。3.宏处理伪指令MACRO和ENDM语法格式:宏名MACRO[参数1][,参数2]……宏体ENDMMACRO用于定义一个宏,引用宏时需使用宏名,并传递实参。ENDM用于结束宏定义。例如:以下定义一个宏,实现参数x与参数y相加再减去参数z,结果放在参数x中,三个参数均为存储器操作数。addmMACROx,y,zLDRR2,=xLDRR1,[R2]LDRR3,=yLDRR4,=zADDR1,R1,[R3]SUBR1,R1,[R4]STRR1,[R2]ENDM4.1.3汇编语言的规范1.语句的格式ARM(Thumb)汇编语言的语句格式为:[标号][指令或伪指令][;注释]语句书写时需遵循以下规则:①所有标号必须在一行的顶格书写,其后不要添加“:”号;②所有的指令均不能顶格写;③如果同一行有两条汇编语句,需要在它们之间以“;”隔开;如果一条语句要分多行显示,需要使用“\”放在分隔处;④每一条指令的助记符可以全部用大写、或全部用小写,但不能在一条指令中大、小写混用。⑤注释使用分号“;”,不要在语句中间添加注释。2.标号在汇编语言程序设计中,可以使用各种标号表示指令或数据的地址,以增加程序的可读性。例如程序4-1中的:loop1LDRR3,[R0],#4……BNEloop1;如果R1不为零,则转向loop1处以下为标号命名规则:①标号不应与指令或伪指令同名②标号在其作用范围内必须唯一。③标号区分大小写,同名的大、小写标号被视为两个不同的标号。④自定义的不能与系统保留字相同。3.常量和变量程序中的常量是指其值在程序的运行过程中不能被改变的量,变量是指其值在程序的运行过程中可以改变的量。ARM汇编程序支持逻辑量、数字和字符串。①数字一般为32位的整数,无符号数取值范围为0~232-1,带符号数取值范围为-231~231-1。②逻辑量只有两种取值:真或假。③字符串用于在程序的运行中保存一个字符串,其长度不应超出字符串变量所能表示的范围。4.2ARM汇编语言程序设计程序设计的三种基本结构是顺序结构、分支结构和循环结构,以解决不同的问题。在ARM汇编语言中采用跳转语句来实现分支与循环结构。在进行程序设计时,首先分析该程序的流程,绘制流程图,再根据流程图编写代码。4.2.1顺序程序4.2.2分支程序4.2.3循环程序4.2.4子程序4.2.5基于查表法的程序设计4.2.1顺序程序顺序程序是一种最简单的程序结构,它按照语句编写的顺序从上往下执行,直到最后退出程序。例4-2:计算100-50,结果存放到R1寄存器中。开始初始化以下内容R1=100R2=50R1=R1+R2结束在ADS中建立工程,编写以上程序,并进行汇编链接,使用AXD进行调试。程序调试结果:寄存器R1的内容为0x32,即为十进制的50,程序运行结果正确。缺省文字池ARM规定:可由一个8位的常数经过循环右移偶数位(0,2,4,……,30)得到的数据,称为8位位图数据。只有8位位图数据可以直接采用立即数寻址方式来获取,其余的数据只能使用文字池的方式,通过存储器访问指令来加载,下面我们改变数据的大小,使得所访问立即数数不再是8位位图数据。例4-3:计算0x123456-0x123,结果存放到R0寄存器中。程序如下:汇编提示错误信息为:文字池是一片用于存放常量的地方,LDR指令寻址文字池,可以访问任意的32位数据。在汇编过程中,汇编器会默认的在每个段的末尾开辟一个文字池,下面我们采用缺省文字池的方式来重写例4-3:例4-3-1:采用缺省文字池的方式实现例4-3。调试信息:地址0x8000存放代码段中的第一条可执行语句LDRR1,=0x123456,地址0x8018存放代码段在的最后一条可执行语句SWI0X123456,代码段的地址范围在0x8000~0x801b之间。实线框住的部分表示汇编器自动生成的文字池。该文字池就在紧跟着代码段的位置,存放着三个LDR访问的数据:0x123456,0x123,0x20026。自定义文字池文字池的使用限制是:LDR指令的寻址范围是前后4KB,不能使文字池与访问它的LDR指令之间的距离超过这个范围。如果用户程序比较大,则可能使整个程序段超过4KB的范围,这样汇编器在程序段的末尾开辟的缺省文字池与访问它的LDR指令之间的距离就有可能超出范围,LDR指令就不能正确加载数据了。在缺省文字池的例子程序中添加伪代码SPACE4096,开辟4096个字节的空间(4096B=4KB),则代码段大小超过4KB。以上代码汇编提示错误信息如图4-7所示,汇编器提示:缺省文字池距离访问它的LDR太远,建议使用LTORG伪指令来创建自定义文字池。在例4-3-2中,使用LTORG伪指令在程序中创建自定义文字池。例4-3-2:采用自定义文字池的方式实现例4-3。采用LTORG伪指令自定义文字池,该程序汇编链接成功。一般LTORG伪指令放在跳转指令B之后,使得在数据段中开辟的文字池中存放的数据不被当做指令执行。虚线框住的部分为自定义文字池,实线框住的部分为缺省文字池。4.2.2分支程序ARM汇编分支程序采用转移指令B或条件转移指令BX来实现。例4-4:给定符号函数:,假定x是-5。开始初始化以下内容R0变量xR1变量yR2=[R0]R2=R2*R2结束R2=0R2=R2+5R20R2=0R20R2与0比较minuszeroplus将R2存入变量y[R1]=R24.2.3循环程序1.计数控制循环已知循环次数,可以用计数器控制循环的次数来进行程序的设计。例4-5:计算1+2+3+……+100的结果,并存放到sum单元。开始初始化以下内容R0=0,存放和R1=100,存放加数及计数值结束R1=R1-1NR1是否等于0R2指向变量sum[R2]=R0每次将R1加到R0上R0=R0+R1Y2.条件控制循环有些情况无法确定循环的次数,这时只能通过循环结束的条件来判断是否结束循环。例4-6:计算1+2+3+……+n,当计算结果大于10000时停止循环,在数据段中定义sum和n两个变量,并将加法和存放到sum单元,将最后一个加数存放到n单元。开始初始化以下内容R0=0,存放和R1=0,存放加数结束每次将R1加到R0上R0=R0+R1NR0是否大于10000R2指向变量sum,[R2]=R0R2指向变量n,[R2]=R1R1=R1+1Y4.2.4子程序在ARM汇编中,通过BL指令可以实现子程序的调用,在跳转时LR寄存器自动保存紧跟着BL指令的下一条指令的地址。在子程序的结束处,可以通过MOVPC,LR返回主程序中。子程序的定义一般放在程序结束返回编译器调试环境的语句之后,END之前,这样使得子程序的定义代码参与编译,但不会在定义的位置执行。只有调用该子程序才会执行。BLfunc指令func:指令指令……MOVPC,LR……主程序在调用子程序时,往往需要向子程序传递一些参数,同样,子程序在运行完毕后也可能要把结果传回给调用程序。1.寄存器传递参数2.存储区域传递参数3.堆栈传递参数例4-7:用子程序实现内存块拷贝,将字符串从源位置拷到目的位置
本文标题:ARM汇编语言程序设计基础.ppt
链接地址:https://www.777doc.com/doc-7878454 .html