资源描述
单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,第,4,章,ARM,处理器指令概述,本章重点,常用,ARM,指令,ARM,汇编程序编程实例,汇编与,C,语言混合编程,ADS,集成开发环境,本章内容,4.1 ARM,微处理器的指令的分类与格式,4.2 ARM,指令的寻址方式,4.3,常用,ARM,指令,4.4,汇编语言的程序结构及在,ADS,环境下调试,4.5,汇编语言与,C/C+,的混合编程,4.1 ARM,微处理器的指令的分类与格式,ARM,微处理器的指令集是加载,/,存储型的,也即指令集仅能处理寄存器中的数据,而且处理结果都要放回寄存器中,而对系统存储器的访问则需要通过专门的加载,/,存储指令来完成。,ARM,微处理器的指令集可以分为跳转指令、数据处理指令、程序状态寄存器(,PSR,)处理指令、加载,/,存储指令、协处理器指令和异常产生指令六大类。,4.2 ARM,指令的寻址方式,所谓寻址方式就是处理器根据指令中给出的地址信息来寻找物理地址的方式。目前,ARM,指令系统支持如下几种常见的寻址方式。,4.2.1,立即寻址,立即寻址也叫立即数寻址,这是一种特殊的寻址方式,操作数本身就在指令中给出,只要取出指令也就取到了操作数。这个操作数被称为立即数,对应的寻址方式也就叫做立即寻址。例如以下,指令:,ADD R0,,,R0,,,1 ;R0R0,1,ADD R0,,,R0,,,0x3f ;R0R0,0x3f,在以上两条指令中,第二个源操作数即为立即数,要求以“”为前缀,对于以十六进制表示的立即数,还要求在“”后加上“,0x”,或“,&”,。,4.2 ARM,指令的寻址方式,4.2.2,寄存器寻址,寄存器寻址就是利用寄存器中的数值作为操作数,这种寻址方式是各类微处理器经常采用的一种方式,也是一种执行效率较高的寻址方式。以下指令:,ADD R0,,,R1,,,R2 ;R0R1,R2,该指令的执行效果是将寄存器,R1,和,R2,的内容相加,其结果存放在寄存器,R0,中。,4.2.3,寄存器间接寻址,寄存器间接寻址就是以寄存器中的值作为操作数的地址,而操作数本身存放在存储器中。例如以下指令:,ADD R0,,,R1,,,R2 ;R0R1,R2,LDR R0,,,R1 ;R0R1,STR R0,,,R1 ;R1R0,在第一条指令中,以寄存器,R2,的值作为操作数的地址,在存储器中取得一个操作数后与,R1,相加,结果存入寄存器,R0,中。,第二条指令将以,R1,的值为地址的存储器中的数据传送到,R0,中。,第三条指令将,R0,的值传送到以,R1,的值为地址的存储器中。,4.2 ARM,指令的寻址方式,4.2.4,基址变址寻址,基址变址寻址就是将寄存器(该寄存器一般称作基址寄存器)的内容与指令中给出的地址偏移量相加,从而得到一个操作数的有效地址。变址寻址方式常用于访问某基地址附近的地址单元。采用变址寻址方式的指令常见有以下几种形式,如下所示:,LDR R0,,,R1,,,#4 ;R0R1,4,LDR R0,,,R1,,,#4,!,;R0R1,4,、,R1R1,4,LDR R0,,,R1,,,#4 ;R0R1,、,R1R1,4,LDR R0,,,R1,,,R2 ;R0R1,R2,在第一条指令中,将寄存器,R1,的内容加上,4,形成操作数的有效地址,从而取得操作数存入寄存器,R0,中。,在第二条指令中,将寄存器,R1,的内容加上,4,形成操作数的有效地址,从而取得操作数存入寄存器,R0,中,然后,,R1,的内容自增,4,个字节。,在第三条指令中,以寄存器,R1,的内容作为操作数的有效地址,从而取得操作数存入寄存器,R0,中,然后,,R1,的内容自增,4,个字节。,在第四条指令中,将寄存器,R1,的内容加上寄存器,R2,的内容形成操作数的有效地址,从而取得操作数存入寄存器,R0,中。,4.2 ARM,指令的寻址方式,4.2.5,多寄存器寻址,采用多寄存器寻址方式,一条指令可以完成多个寄存器值的传送。这种寻址方式可以用一条指令完成传送最多,16,个通用寄存器的值。以下指令:,LDMIA R0,,,R1,,,R2,,,R3,,,R4 ;R1R0,;R2R0,4,;R3R0,8,;R4R0,12,该指令的后缀,IA,表示在每次执行完加载,/,存储操作后,,R0,按字长度增加,因此,指令可将连续存储单元的值传送到,R1,R4,。,4.2.6,相对寻址,与基址变址寻址方式相类似,相对寻址以程序计数器,PC,的当前值为基地址,指令中的地址标号作为偏移量,将两者相加之后得到操作数的有效地址。以下程序段完成子程序的调用和返回,跳转指令,BL,采用了相对寻址方式:,BL NEXT ;,跳转到子程序,NEXT,处执行,NEXT,MOV PC,,,LR ;,从子程序返回,4.2 ARM,指令的寻址方式,4.2.7,堆栈寻址,堆栈是一种数据结构,按先进后出(,First In Last Out,,,FILO,)的方式工作,使用一个称作堆栈指针的专用寄存器指示当前的操作位置,堆栈指针总是指向栈顶。,当堆栈指针指向最后压入堆栈的数据时,称为满堆栈(,Full Stack,),而当堆栈指针指向下一个将要放入数据的空位置时,称为空堆栈(,Empty Stack,)。,同时,根据堆栈的生成方式,又可以分为递增堆栈(,Ascending Stack,)和递减堆栈(,Decending Stack,),当堆栈由低地址向高地址生成时,称为递增堆栈,当堆栈由高地址向低地址生成时,称为递减堆栈。这样就有四种类型的堆栈工作方式,,ARM,微处理器支持这四种类型的堆栈工作方式,,即:,满递增堆栈:堆栈指针指向最后压入的数据,且由低地址向高地址生成。,满递减堆栈:堆栈指针指向最后压入的数据,且由高地址向低地址生成。,空递增堆栈:堆栈指针指向下一个将要放入数据的空位置,且由低地址向高地址生成。,空递减堆栈:堆栈指针指向下一个将要放入数据的空位置,且由高地址向低地址生成。,4.3,常用,ARM,指令,4.3.1,内存访问指令,1.,基本指令,LDR,:存储器,memory,中数据传送到寄存器,register,STR,:寄存器,register,中数据传送到存储器,memory,例如:,ldrr0,r1 ; r1,作为指针,该指针指向的数存入,r0,strr0,r1,#4 ; r1+4,作为指针,,r0,的值存入该地址,strr0,r1,#4! ;,同上,并且,r1 = r1 + 4,ldrr1,=0x08100000 ;,立即数,0x08100000,存到,r1,ldrr1,r2, #4 ; r2+4,作为指针,指向的值存入,r1,,并且,r2=r2+4,4.3,常用,ARM,指令,4.3.1,内存访问指令,2.,多字节存取指令,多字节存取指令常应用于堆栈操作。,LDM,:存储器,memory,中数据传送到多个寄存器,STM,:多个寄存器中的数据传送到存储器,memory,例如:,sub lr,lr, #4 ;lr4,是异常处理完后应该返回的地方,stmfdsp!,r0-r12, lr ;,保存,r0r12,和,lr,寄存器的值到堆栈并更新堆栈指针。,ldmfdsp!,r0-r12, pc ;,从堆栈中恢复,r0r12,,返回地址赋给,pc,指针,使程序返回到异常发生前所执行的地方,,标记用来使,CPU,退出异常模式,进入普通状态。,4.3,常用,ARM,指令,4.3.2,算术运算指令,基本指令:,ADD,:加,SUB,:减,例如:,add r0,r1,r2; r0 = r1 + r2,adds r0,r1, #0x80; r0 = r1 + 0x80,,并设置状态寄存器,subs r0,r1,#2000; r0 = r1 2000,,并设置状态寄存器,4.3,常用,ARM,指令,4.3.3,逻辑运算指令,基本指令:,AND,:与,ORR,:或,EOR,:异或,BIC,:位清,0,例如:,ands r0,,,r1,,,#0xff00; r0 = r1 and 0xff00,,并设置状态寄存器,orr r0,r1,r2; r0 = r1 and r2,bics r0,r1,#0xff00; r0 = r1 and ! (0xff00),ands r0,r1,#0xffff00ff;,错误,4.3,常用,ARM,指令,4.3.4 MOV,指令,mov,指令:,例如:,mov r0, #8; r0 = 8,mov r0,r1; r0 = r1,mov,不同于,LDR,、,STR,指令,该指令可以在寄存器间赋值。,4.3.5,比较指令,基本指令:,CMP,:比较两个操作数,并设置状态寄存器,例如:,cmp r0,r1 ;,计算,r0- r1,,并设置状态寄存器,判断,r0,是否大于、小于或等于,r1,cmp r0,#0;,4.3,常用,ARM,指令,4.3.6,跳转指令,基本指令:,B,:跳转,BL,:跳转并将下一指令的地址存入,lr,寄存器,例如:,loop1,bloop1;,跳到地址,loop1,处,blsub1;,将下一指令地址写入,lr,,并跳至,sub1,sub1,mov pc,lr;,从,sub1,中返回,4.3,常用,ARM,指令,4.3.7,条件执行指令,条件:状态寄存器中某一或某几个比特的值代表条件,对应不同的条件后缀,cond,。,例如:,cmp r0, r1;,比较,r0,和,r1,blgt sub1;,如果,r0r1,,跳转到,sub1,,否则不操作,;,;,一段循环代码,ldr r2,=8;r2 = 8,loop,;,这里可以进行一些循环内的操作,subsr2,r2,#1;r2 = r2 1,,并设置状态位,bneloop ;,如果,r2,不等于,0,,则继续循环,;,movr0,#1; r0 = 1,cmpr2,#8;,比较,r2,和,8,movltr0,#2;,如果,r2,下可以输入命令进行调试。,(,3,)监视变量变化,在,AXD,窗口中,点击,Processor Views|Watch,用鼠标选中某变量,单击鼠标右键,在弹出的菜单中选中,Add to watch,,此变量显示在,watch,窗口中。,4.4 汇编语言的程序结构及在ADS环境下调试,(,4,)设置断点,将光标定位在要设置断点的某语句处,按,F9,键。调试的结果如图,4-12,所示,图中显示了断点、,Watch,中寄存器的值、存储器从起始地址,0x1000,开始的存储内容。,4.5,汇编语言与,C/C+,的混合编程,在应用系统的程序设计中,若所有的编程任务均用汇编语言来完成,其工作量是可想而知的,同时,不利于系统升级或应用软件移植,事实上,,ARM,体系结构支持,C/C+,以及与汇编语言的混合编程,在一个完整的程序设计的中,除了初始化部分用汇编语言完成以外,其主要的编程任务一般都用,C/C+,完成。,汇编语言与,C/C+,的混合编程通常有以下几种方式:,1,在,C/C+,代码中嵌入汇编指令。,2,在汇编程序和,C/C+,的程序之间进行变量的互访。,3,汇编程序、,C/C+,程序间的相互调用。,4.5,汇编语言与,C/C+,的混合编程,在以上的几种混合编程技术中,必须遵守一定的调用规则,如物理寄存器的使用、参数的传递等,这对于初学者来说,无疑显得过于烦琐。在实际的编程应用中,使用较多的方式是:程序的初始化部分用汇编语言完成,然后用,C/C+,完成主要的编程任务,程序在执行时首先完成初始化过程,然后跳转到,C/C+,程序代码中,汇编程序和,C/C+,程序之间一般没有参数的传递,也没有频繁的相互调用,因此,整个程序的结构显得相对简单,容易理解。,.,.,C,程序调用汇编程序,1,C,程序嵌入汇编指令,汇编指令以语句块形式嵌入在,C,程序的函数中,其使用格式为:,_asm,汇编语句,汇编指令以函数形式嵌入在,C,程序的函数中,其使用格式为:,_asm int,函数名,(,形式参数表,),汇编代码,4.5,汇编语言与,C/C+,的混合编程,(,1,)汇编指令以语句块形式嵌入在,C,程序中,例如:在,C,程序中嵌入汇编语句的例子。,#include,int add(int i,int j),int sum;,_asm,ADD sum,i,j,return sum;,int main(),int x,y;,scanf(%d %d,printf(%d+%d=%dn,x,y,add(x,y);,return 0;,请建立一个工程,调试上述程序。,4.5,汇编语言与,C/C+,的混合编程,(,2,)在,C,程序中调用以函数形式构成的汇编指令,C,程序调用汇编程序时,汇编程序的书写也要遵循,ATPCS,规则,以保证程序调用时参数正确传递。在,C,程序中调用汇编子程序的方法为:首先在汇编程序中使用,EXPORT,伪指令声明被调用的子程序,表示该子程序将在其他文件中被调用;然后在,C,程序中使用,extern,关键字声明要调用的汇编子程序为外部函数。,例如:在一个汇编源文件中定义了如下求和函数。,EXPORT add ;,声明,add,子程序将被外部函数调用,add ;,求和子程序,add,ADD r0,r0,r1,MOV pc,lr,在一个,C,程序的,main(),函数中对,add,汇编子程序进行了调用:,extern int add (int x,int y); /,声明,add,为外部函数,void main( ),int a=1,b=2,c;,c=add(a,b); /,调用,add,子程序,当,main(),函数调用,add,汇编子程序时,变量,a,、,b,的值会给了,r0,和,r1,,返回结果由,r0,带回,并赋值给变量,c,。函数调用结束后,变量,c,的值变成,3,。,4.5,汇编语言与,C/C+,的混合编程,例如:,1,、建立文件,add.s,,代码如下:,EXPORT add,AREA add,CODE,READONLY,ENTRY,ADD r0,r0,r1,MOV pc,lr,END,2,、,C,程序代码为:,#include,extern int add(int x,int y);,int main(),int x,y;,scanf(%d %d,printf(%d+%d=%dn,x,y,add(x,y);,return 0;,4.5,汇编语言与,C/C+,的混合编程,3,、程序调试方法,(,1,)首先建立一个工程,test,(,2,)按照图,-,所示建立源程序,main.c,与,add.s,,请注意选中”,Add to Project”,,并分别输入源程序与汇编源程序。,。,4.5,汇编语言与,C/C+,的混合编程,(,3,)在图,-,中设置,inker,中,utput,的,ase,地址设为,x400000,,,。,4.5,汇编语言与,C/C+,的混合编程,(,4,)设置程序开始执行的地址,如图,-,所示。,。,4.5,汇编语言与,C/C+,的混合编程,(,5,)如图,-,所示,设置程序从,main.o,开始执行。,。,4.5,汇编语言与,C/C+,的混合编程,(,6,)执行菜单,rocject,下的,make,命令,编译程序。,(,7,)执行程序,run,,如图,-,所示。,。,4.5,汇编语言与,C/C+,的混合编程,4.5.2,汇编程序调用,C,程序,从汇编程序调用程序,格式较为简单。其格式为:,BL C,函数名,例题,1,、新建一个工程项目,test3.mcp,2,、新建一个,init.s,文件,这个程序是该项目文件的入口程序,程序代码为:,AREA asm,CODE,READONLY,IMPORT add,ENTRY,LDR r0,=0x1,LDRr1,=0x20,LDR r2,=0x2,BLadd;result saved in r0,B .,END,4.5,汇编语言与,C/C+,的混合编程,3,、新建一个,main.c,程序,程序代码为:,int add(int a, int b, int c),int sum=0,i;,for(i=a;i=b;i=i+c),sum=sum+i;,return sum;,4,、在,ADS1.2,集成开发环境(,CodeWarrior for ARM Developer Suite,)选择微处理器、,ase,地址、程序执行的首地址、程序开始执行的函数,Init.o,等环境参数。,5,、选择菜单,Project|Make,后,点击,Project|Debug,,转入,AXD,环境。,6,、在,AXD,环境中,点击,Ecxute|Go,,然后进行单步调试。,7,、调试过程中把变量,r0,、,r1,、,r2,、,i,、,sum,添加到,Watch,窗口,观察这些变量的变化情况。,
展开阅读全文