您好,欢迎访问三七文档
汇编语言设计顺序结构分支结构循环结构3.1汇编语言程序设计方法汇编语言程序设计同高级语言程序设计一样,是有章可循的,只要按照一定的方法步骤去做,程序设计就会变成一件轻松愉快的事情,设计的程序也会规范、清晰、易读、易懂。使用汇编语言设计程序大致上可分为以下几个步骤。1.分析题意,明确要求。2.确定算法。3.画程序流程图。4.分配内存工作单元。5.编写源程序。6.程序优化。7.上机调试。3.2顺序程序设计【例】程序初始化。初始化就是为变量、寄存器、存储单元赋一初值,是最简单、最常用的操作。如将R0-R3,P1,30H,40H单元初始化为00H,把R4,R5初始化为0FFH。参考程序如下:ORG0000H;PC起始地址LJMPSTART;转主程序ORG0100H;主程序起始地址START:MOVR0,#00H;初始化MOVR1,#00HMOVR2,#00HMOVR3,#00HMOVP1,#00HMOVR4,#0FFHMOVR5,#0FFHMOV30H,#00HMOV40H,#00HHERE:SJMPHERE;反复执行该指令,相当于等待END用立即数比较直观,但用MOVA,#00H,MOVR0,A指令赋值,效果更好。【例】逻辑运算。逻辑操作是控制过程中经常使用的,掌握逻辑运算的特点是提高程序效率的重要途径。在逻辑运算中,进位标标志CY的地位很特殊,它是逻辑累加器,大多数逻辑操作要通过CY来完成。用程序实现图4-2所示的逻辑电路功能。图3-2逻辑电路参考程序如下:ORG0000HLJMPSTARTORG0100HMOVP1,#0FFH;P1口初始化LOOP:MOVC,P1.1ORLC,P1.2;P1.1与P1.2逻辑或运算CPLC;取反ANLC,P1.0;C与P1.0逻辑与运算CPLCMOV07H,C;暂存于07H单元中MOVC,P1.3ANLC,/P1.4;P1.3与P1.4的反逻辑与运算CPLCORLC,07HMOVP1.5,C;把结果在P1.5口输出SJMP$END3.3分支程序设计分支程序的主要特点是程序包含有判断环节,不同的条件对应不同的执行路径。编程的关键任务是合理选用具有逻辑判断功能的指令。由于选择结构程序的走向不再是单一的,因此,在程序设计时,应该借助程序框图(判断框)来明确程序的走向,避免犯逻辑错误。一般情况下,每个选择分支均需单独一段程序,并有特定的名字,以便当条件满足时实现转移。1.单分支选择结构当程序的判断是二选一时,称为单分支选择结构。通常用条件转移指令实现判断及转移。单分支选择结构有三种典型表现形式。图3-3单分支选择结构(a)当条件满足时执行分支程序1,否则执行分支程序2。(b)当条件满足时跳过程序段1,从程序段2顺序执行;否则,顺序执行程序段1和程序段2。(c)当条件满足时程序顺序执行程序段2;否则,重复执行程序段1,直到条件满足为止。由于条件转移指令均属相对寻址方式,其相对偏移量rel是个带符号的8位二进制数,可正可负。因此,它可向高地址方向转移,也可向低地址方向转移。对于第三种形式,可用程序段1重复执行的次数作为判断条件,当重复次数达到某一数值时,停止重复,程序顺序往下执行。这是分支结构的一种特殊情况,这实际是循环结构程序。用这种方式可方便实现状态检测。【例】:LOOP:JBP1.1,LOOP单分支程序一般要使用状态标志,应注意标志位的建立。【例】设a存放在累加器A中,b存放在寄存器B中,若a≥0,Y=a-b;若a0,则Y=a+b。这里的关键是判a是正数,还是负数;可通过判断ACC.7确定。ORG0000HLJMPBRORG0100HBR:JBACC.7,MINUS;负数,转到MINUSCLRC;清进位位SUBBA,B;A-BSJMPDONEMINUS:ADDA,B;A+BDONE:SJMP$;等待END2.双向分支程序设计举例【例4.3】设X存在30H单元中,根据下式X+2X0Y=100X=0∣X∣X0求出Y值,将Y值存入31H单元。解:根据数据的符号位判别该数的正负,若最高位为0,再判别该数是否为0。程序流程如图4-4所示。A为负数?取数,A←(30H)开始结束A=0?YNNA←|X|A←64HA←X+2存数,(31H)←A(30H)参考程序如下:ORG1000HMOVA,30H;取数JBACC.7,NEG;负数,转NEGJZZER0;为零,转ZER0ADDA,#02H;为正数,求X+2AJMPSAVE;转到SAVE,保存数据ZER0:MOVA,#64H;数据为零,Y=100AJMPSAVE;转到SAVE,保存数据NEG:DECACPLA;求∣X∣SAVE:MOV31H,A;保存数据SJMP$;暂停2.多分支选择结构当程序的判别输出有两个以上的出口流向时,称为多分支选择结构。8051的多分支结构程序还允许嵌套,即分支程序中又有另一个分支程序。汇编语言本身并不限制这种嵌套的层次数,但过多的嵌套层次将使程序的结构变得十分复杂和臃肿,以致造成逻辑上的混乱。多分支选择结构通常有两种形式,如图4-4所示。图4-4多分支选择结构8051的散转指令和比较指令均可以实现多分支转移。散转指令JMP@A+DPTR比较指令CJNEA,direct,rel(共有4条)使用散转指令前,先将各分支程序编写好,存放在程序存储器中,并将各分支程序的入口地址组成一个表格放在一起,把表首地址送入DPTR,把子程序的序号放入A中。在8051指令中,还有4条功能极强的比较转移指令:CJNEA,direct,relCJNEA,#data,relCJNERn,#data,relCJNE@Ri,#data,rel这4条指令对指定单元内容进行比较,当不相等时程序作相对转移,并指出其大小,以备作第二次判断;若两者相等,则程序顺序执行。【例】散转程序。编写程序,根据20H单元中的内容转入相应的分支,执行指定的操作,将结果存入指定存储器单元。程序流程框图如图4-5所示图3-5散转程序流程参考程序ORG0000HLJMPMEMSRESULTEQU0050HORG0100HMEMS:MOVA,20HMOVDPTR,#KKKK;散转程序入口地址表首址RLA;分支号乘2,每个入口地址均为2字节JMP@A+DPTR;转移END1:SJMP$KKKK:AJMPMEMSP0;A=0加法AJMPMEMSP1;A=1减法AJMPMEMSP2;A=2乘法SJMPMEMSP3;A=3除法SJMPMEMSP4;A=4逻辑与SJMPMEMSP5;A=5逻辑或MEMSP0:MOVA,R0;相加分支CLRCADDA,R1MOVRESULT,ALJMPEND1MEMSP1:MOVA,R0;相减分支CLRCSUBBA,R1MOVRESULT,ALJMPEND1MEMSP2:MOVA,R0;乘法分支MOVB,R1CLRCMULABMOVRESULT,AMOVRESULT+1,BLJMPEND1MEMSP3:MOVA,R0;除法分支MOVB,R1CLRCDIVABMOVRESULT,AMOVRESULT+1,BLJMPEND1MEMSP4:MOVA,R0;逻辑与分支ANLA,R1MOVRESULT,ALJMPEND1MEMSP5:MOVA,R0;逻辑或分支ORLA,R1MOVRESULT,ALJMPEND1END【例】两个无符号数比较大小。设外部RAM单元ST1和ST2中存放两个无符号二进制数,要找出其中的大数存入ST3单元中。程序流程框图如图3-6所示。图3-6求大数程序流程参考程序如下:ORG0000HLJMPSTARTORG0100HSTART:MOVA,addr1;将addr1中内容送ACJNEA,addr2,LOOP1;两数比较,不相等则转LOOP1LOOP3:AJMP$;结束LOOP1:JCLOOP2;当CY=1,转LOOP2MOVaddr3,A;CY=0,(A)>(addr2)SJMPLOOP3;转结束LOOP2:MOVaddr3,addr2;CY=1,(addr2)>(A)SJMPLOOP3END3.4循环程序设计在实际应用中经常会遇到功能相同,需要多次重复执行某段程序的情况,这时可把这段程序设计成循环结构,这有助于节省程序的存储空间,提高程序的质量。循环程序一般由4部分组成。1.初始化。即设置循环过程中有关工作单元的初始值,如置循环次数、地址指针及工作单元清零等。2.循环体。即循环处理部分,完成主要的计算或操作任务,是重复执行的程序段。3.循环控制。每循环一次,就要修改循环次数、数据及地址指针等循环变量。并根据循环结束条件,判断是否结束循环。4.循环结束处理。对结果进行分析、处理、保存。循环程序结构有两种,如图3-7所示。图3-7循环程序结构图(a)是“先执行后判断”结构,适用于循环次数已知的情况。其特点是进入循环后,先执行循环处理部分,然后根据循环次数判断是否结束循环。图(b)是“先判断后执行”结构,适用于循环次数未知的情况。其特点是将循环控制部分放在循环的入口处,先根据循环控制条件判断是否结束循环,若不结束,则执行循环操作;若结束,则退出循环。【例】50ms软件延时程序。软件延时程序一般都是由DJNZRn,rel指令构成。执行一条DJNZ指令需要两个机器周期。软件延时程序的延时时间主要与机器周期和延时程序中的循环次数有关,在使用12MHz晶振时,一个机器周期为1μs,执行一条DJNZ指令需要两个机器周期,即2μs。适当设置循环次数,即可实现延时功能。参考程序如下:ORG0000HLJMPMEMSORG0100HMEMS:DEL:MOVR7,#125;外循环次数,该指令为一个机器周期DEL1:MOVR6,#200;内循环次数DEL2:DJNZR6,DEL2;200×2=400μs(内循环时间)DJNZR7,DEL1;0.4ms×125=50ms(外循环时间)SJMP$END例2.循环程序设计举例【例】有一数据块从片内RAM的30H单元开始存入,设数据块长度为10个单元。根据下式:X+2X0Y=100X=0求出Y值,并将Y值放回原处。∣X∣X0解:设置一个计数器控制循环次数,每处理完一个数据,计数器减1。程序流程如图4-8所示。A=0?YYNNYNA为负数?取数,A←((R1))开始结束A←∣X∣A←64HA←X+2存数,((R1))←A(30H)设置地址指针R1、计数器R0初值R1←R1+1;R0←R0-1R0=0?图4-8例4.5的程序流程图返回本节参考源程序如下:ORG2000HMOVR0,#10MOVR1,#30HSTART:MOVA,@R1;取数JBACC.7,NEG;若为负数,转NEGJZZER0;若为零,转ZER0ADDA,#02H;若为正数,求X+2AJMPSAVE;转到SAVE,保存数据ZER0:MOVA,#64H;数据为零,Y=100AJMPSAVE;转到SAVE,保存数据NEG:DECACPLA;求∣X∣SAVE:MOV@R1,A;保存数据INCR1;地址指针指向下一个地址DJNZR0,START;数据未处理完,继续处理SJMP$;暂停【例】排序程序。设在内部RAM中存一无符号数的数组,其长度为n,起始地址是30H,要求将它们按从大到小排序,排序后仍存放在原区域中。按“冒泡法”对n个数排序时,可能用不到n-1次循环,排序就结束了。为了提高排序速度,程序中可设一交换标志位,如10H位,每次循环中,若有交换则执行SETB10H,表明排序未完成;若无交换,则执行CLR10H,表明排序已经完成。每次循环结束时,测10H位,判断排序是否结束。参考程序如下:ORG0000HLJMPBUBBLEORG0100HBUBBLE:MOVR0,#30HMOVB,#64HCLR10HDECB;长度计数LOOP:MOVA,@R0;内循环的入口MOV20H,A;暂存,为交换作准备INCR0MOV21H,@R0CJNEA,21H,BUEU;若(20H)≠(21
本文标题:单片机程序设计
链接地址:https://www.777doc.com/doc-7025611 .html