单片机原理与应用Principle&ApplicationofMCU第4章80C51单片机汇编语言程序设计1教学内容及要求教学内容汇编语言程序的基本结构形式、子程序结构形式80C51单片机汇编语言伪指令80C51单片机汇编语言程序设计举例教学要求掌握顺序结构程序、分支程序、循环程序和子程序等结构程序的设计等熟悉单片机汇编程序常用的伪指令了解汇编语言程序的格式2汇编语言源程序的编辑和汇编3机器编辑→交叉汇编→串行传送4地址机器码标号助记符指令80007820SORT:MOVR0,#20H80027F07MOVR7,#07H*.ASM编辑、汇编编辑:编写程序的过程称为编辑。机器编辑指借助于微型机进行单片机的程序设计,通常都是使用编辑软件进行源程序的编辑。编辑完成后,生成一个由汇编指令和伪指令构成的扩展名为”.ASM”的ASCII码文件。汇编:汇编语言源程序不能在单片机中直接执行,必须将其“翻译”为用二进制代码(机器语言)表示的目标程序才能执行。这个“翻译”过程称为汇编。机器汇编指由计算机通过汇编程序完成从汇编语言源程序到机器语言目标程序的“翻译”工作。交叉汇编指使用一种计算机(PC)的汇编程序为另一种计算机(单片机)的源程序进行汇编即运行汇编程序进行汇编的是一种计算机,而汇编得到的目标程序是另一种计算机用的。580C51单片机汇编语言伪指令汇编时,源程序须向汇编程序发出一些指示信息,协助完成汇编工作,这一工作是由伪指令来完成的。汇编起始地址命令ORG(Origin)定义字节命令DB(DefineByte)定义数据字命令DW(DefineWord)预留存储区命令DS(DefineStorage)位定义命令BIT赋值命令EQU(Equate)数据地址赋值伪指令DATA汇编终止命令END(Endofassembly)注意!伪指令仅供汇编程序将源程序翻译成目标程序,本身并不形成机器码。6汇编起始地址命令ORG(Origin)规定程序或数据的起始存放地址。出现在每段源程序或数据块的开始地址项是16位绝对地址,或者标号,或者表达式。在一个汇编语言源程序中允许使用多条定位伪指令,但其值应从小到大,并与前面的存放地址不重叠。如果程序的开始不放ORG,则汇编程序将从0000H单元开始放目标程序代码。ORG地址7ORG0000H;从0000H单元开始存放下面的指令LJMP0030HORG0030H;从0030H单元开始存放下面的指令MAIN:MOVSP,#50HORG0040H;从0040H单元开始存放下面的数据TAB:DB23,89定义字节命令DB(DefineByte)在程序存储器中定义字节数据。Xn可以是一字节常数;用双引号或者单引号括起来的字符或字符串;各个数之间用逗号隔开。DBX1,X2,…,Xn8ORG1000HA1:DB01001010B,23o,23,78H,A2:DB‘5’,”12AB”,12D,-2(1000H)=01001010B=4AH,(1001H)=23o=13H,(1002H)=23=17H,(1003H)=78H,(1004H)=35H(5的ASCII码),(1005H)=31H(1的ASCII码),(1006H)=32H(2的ASCII码),(1007H)=41H(A的ASCII码),(1008H)=42H(B的ASCII码),(1009H)=12D=0CH(100AH)=-2=0FEH【例】定义数据字命令DW(DefineWord)在程序存储器中定义16位的数据字。存放时,数据字的高8位在低地址,低8位在后高地址。通常,DB用来定义数据,DW用来定义地址。DWY1,Y2,…,YnDW“AA”;存入41H,41HDW“A”;存入00H,41HDW“ABC”;不合法,因为超过了两个字节DW100H,1ACH,-804;按顺序存入01H、00H、01H、0ACH、0FCH、0DCH9【例】预留存储区命令DS(DefineStorage)在程序存储器中保留指定数目的单元作为预留存储区,供程序运行使用。【例】ADDRTAB:DS20;从标号ADDRTAB代表的地址开始,预留20个;连续的地址单元。[标号:]DS16位数表DB、DW、DS只能对于程序存储器使用10位定义命令BIT把位地址赋给字符名称。【例】:AQBITP1.0;把P1.0的位地址赋给字符名AQ,在其后;的编程中AQ可以作为位地址使用。字符名称BIT位地址11赋值命令EQU(Equate)给数或符号赋给字符赋值项可以是常数、地址、标号或表达式。赋值以后的字符既可以作地址使用,也可以作立即数使用。【例】CSEQU0FFFFHA1EQUR1A2EQU10HDELAYEQU0708HA1可作为寄存器R1来使用,A2可作为8位直接地址或立即数使用,DELAY可作为16位地址或者立即数使用。字符名EQU数或汇编符号12数据地址赋值伪指令DATA将表达式的值赋给字符。表达式可以是一个数据或地址,也可以是一个包含所定义字符名在内的表达式,但不能是一个汇编符号(如R0~R7)。与EQU的区别:EQU必须先定义后使用。DATA无此限制,所以DATA伪指令可以放在源程序的开头或末尾MOVR0,ADDRESSMOVR1,#ADDRESSADDRESSDATA31H将31H单元内容送R0,(R1)=31H。字符名DATA表达式13汇编终止命令END(Endofassembly)用于终止源程序的汇编工作,在一个源程序中只能有一条END命令,并且位于程序的最后。如果END命令出现在程序中间,则其后面的源程序将不予处理。14一般汇编调试工具要求的汇编格式一般用汇编语言编写的程序,要求指出该程序存放于内存地址的位置,并且将用到的数据和需要预留存放数据的空间用伪指令定义好然后编写程序代码最后用原地踏步或返回起始位置循环作为结束。ORG……SJMP$END【例】程序格式如下:15汇编语言程序的基本结构形式16分支结构使用条件转移指令对程序的执行结果进行判断JZ、JNZ、CJNE、DJNZJC、JNC、JB、JNB、JBC17【例】二分支。在外部RAM中有ST1、ST2和ST3共3个连续单元,其中ST1和ST2单元中存放着两个无符号二进制数,要求找出其中的大数并存入ST3单元中。18【例】三分支-多次二选一。设变量x存入30H单元,求得函数y存入31H单元。按下式要求给y赋值:x-1(x<5)0(5≤x≤10)x+1(x10)Y=要根据x的大小来决定y值,在判断x<5和y>10时,采用CJNE和JC以及CJNE和JNC指令进行判断。19ORG1000HMOVA,30H;取xCJNEA,#5,NEXT1;与5比较NEXT1:JCNEXT3;x<5,则转NEXT3CJNEA,#10,NEXT2;与10比较NEXT2:JNCNEXT4;x>10,则转NEXT4MOVR0,#0;5≤x≤10,y=0SJMPNEXT5NEXT3:MOVR0,ADECR0;x<5,y=x-1SJMPNEXT5NEXT4:MOVR0,AINCR0;x10,y=x+1NEXT5:MOV31H,R0;存结果SJMP$END20多分支转移使用变址寻址转移指令(散转指令)JMP@A+DPTR;PC←(A)+(DPTR)数据表、转移指令表、堆栈操作21通过数据表实现程序多分支22MOVA,#k;分支序号k送AMOVDPTR,#BRTAB;表首址MOVCA,@A+DPTR;查表后,(A)=BRk-BRTABJMP@A+DPTR;散转指令,(PC)=BRkBRTAB:DBBR0-BRTAB;数据表,BRTAB+0DBBR1-BRTAB;分支入口地址与表首址之差,BRTAB+1…DBBRn-BRTAB;BRTAB+nBR0:…;各个分支程序BR1:……BRn:…通过转移指令表实现程序多分支23MOVA,#k;分支序号k送ARLA;分支序号乘以2MOVDPTR,#BRTAB;表首址JMP@A+DPTR;(PC)=BATAB+2kBRTAB:AJMPBR0;转分支程序0,BRTABAJMPBR1;转分支程序1,BRTAB+2…AJMPBRn;转分支程序n,BRTAB+2nBR0:…;各个分支程序BR1:……BRn:…使用长转移指令LJMP时,MOVA,#kRLAADDA,R3MOVDPTR,#BRTABJMP@A+DPTRBRTAB:LJMPBR0;BRTABLJMPBR1;BRTA+3…LJMPBRn;BRTAB+3n24通过堆栈操作实现程序多分支25MOVDPTR,#BRTAB;分支程序入口地址表首址MOVA,#k;分支序号放入A中RLA;分支序号值乘以2MOVR1,A;暂存A值入R1INCA;A指向低位地址MOVCA,@A+DPTR;取低位地址BRn7-0PUSHACC;低位地址入栈MOVA,R1;恢复A值MOVCA,@A+DPTR;取高位地址BRn15-8PUSHACC;高位地址入栈RET;分支入口地址装入PCBRTAB:DWBR0;分支程序入口地址表,BRTAB、BRTAB+1DWBR1;BRTAB+2、BRTA+3…DWBRn;BRTAB+2n、BRTAB+2n+1RETPC15~8←((SP)),SP←(SP)-1PC7~0←((SP)),SP←(SP)-1循环结构初始化部分对于循环次数计数器、地址指针赋初值,对于使用到的寄存器或者存储单元赋初值,为循环作准备。循环体部分为下一次循环创造条件:修改循环次数计数器、地址指针,避免死循环。循环的判断与控制:判断循环次数计数器,或者检查判断循环条件。可以直接由循环体内转到循环体外或外层循环;不能从循环体外直接跳转到循环体内,只能从外层向内层一层层进入。循环结束处理:结果保存等。26【例】单循环。编程实现把外部RAM中从8000H开始的100个字节数据传送到8100H开始的单元中。MOVR7,#100MOVDPL,#00HLOOP:MOVDPH,#80HMOVXA,@DPTRMOVDPH,#81HMOVX@DPTR,AINCDPLDJNZR7,LOOPMOVR0,#00LOOP:MOVP2,#80HMOVXA,@R0MOVP2,#81HMOVX@R0,AINCR0CJNER0,#100,LOOP或27【例】由循环内部跳出循环。把长度为10H的字符串从内部RAM缓冲区inbuf向位于外部RAM的输出缓冲区outbuf传送,一直进行遇到回车符CR或整个字符串传送完毕。START:MOVR7,#10HMOVR0,#inbufMOVDPTR,#outbufLOOP:MOVA,@R0CJNEA,#0D0H,CONTINUESJMPFINISHCONTINUE:MOVX@DPTR,AINCR0INCDPTRDJNZR7,LOOPFINISH:SJMP$END28子程序在主程序中调用子程序LCALL/ACALL标号;调用子程序时,断点入栈保存由子程序返回主程序RET;子程序返回时,断点出栈从而回到主程序。子程序中,视情况进行现场保护和现场恢复1、使用堆栈:PUSH/POP2、暂存到其它存储单元中,最终恢复即可29调用延时子程序DELAY。主程序:子程序:该子程序根本不需要主程序提供入口参数,从进入子程序开始,到子程序返回,这个过程花费CPU一定的时长。循环体只能执行有限次,避免“死循环”。DELAY:PUSH06HPUSH07HMOVR7,#100DLY0:MOVR6,#98NOPDLY1:DJNZR6,DLY1DJNZR7,DLY0POP07HPOP06HRETLCALLDELAY3080C51单片机汇编语言程序设计举例定时程序查表程序求平方极值查找程序查找关键字扩展阶乘计算压缩和解压程序算术运算:加、减、乘、除数据排序数制与编码转换程序LED的简单控制KEY+LED的