【大学】单片机课件 汇编语言程序设计PPT.ppt
第四章汇编语言程序设计,4.1 概述,4.2 顺序结构程序,4.3 分支结构程序,4.4 循环结构程序,4.5 子程序结构,4.6 综合程序举例,4.7 本章小节,4.8 思考与练习题,第四章汇编语言程序设计,主要内容:本章从程序结构和实用角度出发,通过典型的应用实例介绍汇编语言程序的基本结构及模块化程序设计,使学生进一步理解和掌握51系列单片机的指令系统,并掌握汇编语言程序设计的基本语言和技巧。要求:1、熟练运用指令系统,掌握循环程序、分支程序和搜索程序的设计方法;2、熟练运用指令系统,掌握基本的运算程序设计方法;,第四章汇编语言程序设计,3、熟练运用指令系统,掌握数制和码制转换程序的设计方法;4、熟练掌握子程序结构,实现模块化程序设计;5、深刻理解软件、硬件的相互作用,不断提高实际问题处理程序编写能力。,4.1 概述,4.1 概述 程序设计:为了解决某一个问题,将所设计应用系统(单片机类型)的指令按一定顺序组合在一起。即用计算机所能接受的语言把解决问题的步骤描述出来。单片机汇编源程序结构与通用微机汇编源程序结构略有不同,原因是:1、一般没有可以直接利用的监控程序,所有程序均要自己编写。,4.1 概述,2、没有像X86汇编语言程序那样,可直接调用系统提供的中断功能(如:BIOS中断、DOS中断)或Windows的API函数完成特定操作,即所有子程序(如键盘监控子程序、显示驱动程序、中断服务程序等)均需要自己编写。汇编语言语句三种基本类型:指令语句、伪指令语句、宏指令语句。,4.1 概述,一、汇编语言伪指令 伪指令 汇编程序某些指令在汇编时并不产生目标代码,不影响程序的执行,不是CPU能执行的指令,只提供一些汇编控制信息的指令。常用的伪指令:(1)设置起始地址ORG 格式:ORG nn 1、ORG:表明为后续源程序经汇编后的目标程序安排存放位置,nn则给出了存放的起始地址值;,4.1 概述,2、ORG总是出现在每段源程序或数据块的开始;3、在一个源程序中,可以多次使用ORG规定不同程序段的起始位置,但定义的地址顺序应从小到大,且不能重叠;4、若不用ORG,则汇编将从0000H单元开始存放目标程序;例4.1ORG 3000H;表示后续的目标程序代码从3000H单元开始存放。MOV A,30H,4.1 概述,(2)定义字节DB 格式:标号:DB字节数据项表 1、标号区段可有可无,项表指中间用逗号分开的字节、数、字符串或用引号括起来的ASC码字符串(一个字符用ASC码表示,就相当于一个字节)。2、功能:把项表的数据存入从标号开始的连续单元中。例4.2ORG 2000HSEG1:DB 35H,78H,4.1 概述,SEG2:DB DAY END则(2000H)=35H,(2001H)=78H,(2002H)=44H,(2003H)=41H,(2004H)=59H 注意:项表中若为数值,其取值范围应为00HFFH,若为字符串,其长度应限制在80个字符内。(3)定义字DW 格式:标号:DW字节数据项表 DW的基本含义与DB相同,不同的是DW定义16位数据,常用来建立地址表。存放时一个字需两个单元,高8位先存放,低8位后存放。,4.1 概述,例4.3 ORG 8000HHETAB:DW 7234H,8AH,10 汇编后:(8000H)=72H,(8001H)=34H,(8002H)=00H,(8003H)=8AH,(8004H)=00H,(8005H)=0AH(4)数据地址赋值DATA 格式为:字符名称 DATA 数据或表达式 把数据地址或代码地址赋予字符名称。常用于定义数据地址,它可以先使用后定义(因为DATA定义的字符名称作为标号登记在符号表中,而EQU没定义),这点与EQU不同。表达式应是可求值的。,4.1 概述,例4.4ORG8000H INDEXJDATA 8096H LJMP INDEXJ END 等价于ORG8000H LJMP 8096H END,4.1 概述,(5)赋值(等值)EQU 格式:标号 EQU 项或表达式 功能:将语句操作数的值赋于本语句的标号,用EQU赋过值的标号名可以用作数据地址、代码地址、位地址或是一个立即数,它可以是8位、也可以是16位。注意:1、在同一程序中,用EQU伪指令对标号赋值后,该标号的值在整个程序中不能再改变;2、用EQU定义的字符须先定义后使用。,4.1 概述,例4.5 ORG8000H AAEQUR6;AA与R6等值MOV A,AA;(R6)的值送入A中(6)位地址符号命令BIT 格式:字符名称 BIT 位地址 功能:给一个可位寻址的位单元起一个名字。用BIT定义过的位单元可用名字使用。注意:名字必须是以字母开头的字母数字串,它必须是事先未定义过的。,4.1 概述,例4.6 A1BITP1.0A2BIT02H(7)源程序结束END 格式:标号:END 表达式 1、标号和表达式是可有可无的。2、END是一个结束标志,在一个程序中只允许出现一个END语句,而且它必须放在整个程序的最后面。(8)定义存储空间DS 格式:标号:DS 表达式 1、由标号指定单元开始,定义一个存储区,以备源程序使用。,4.1 概述,2、存储区内预留的存储单元数由数据或字符表达式的值决定。例4.7 ORG 8000HTEMP:DS 08HDB 30H,8AH即8000H8007H单元保留备用,(8008H)=30H,(8009H)=8AH。二、汇编语言程序设计的基本步骤1、分析问题(调研),确定方案和计算方法 目的:对需要解决的问题进行分析,以求对问题有正确的理解。,4.1 概述,2、了解应用系统的硬件配置、性能指标。3、建立系统数学模型,确定控制算法和操作步骤。4、编制说明要解决问题的程序框图。画程序框图:用各种图形、符号、指向线等来说明程序设计的过程。框图步骤写得越细致,编程时也就越方便。目的:把具有一定功能的各个部分有机地联系起来,可以使人们抓住程序的基本线索,对全局有完整的了解。,4.1 概述,好处:(1)容易发现设计思想上的错误和矛盾,便于找出解决问题的途径。(2)便于把较大的程序分成若干个模块,从而分头进行设计,最后合在一起联调。5、按所使用计算机的指令系统,依据框图写出汇编语言程序。编程的三个原则:尽可能的节省数据存储单元;缩短程序长度;减少执行时间。,4.1 概述,.合理分配存储器单元和了解I/O接口地址。.按功能设计程序,明确各程序之间的相互关系。.用注释行说明程序,便于阅读、调试和修改。6、上机调试程序,直至完成预定功能。MCS-51 程序总体组成MCS-51汇编语言源程序一般由程序头、主程序、完成特定操作的子程序(可能不止一个)及相应功能的中断服务程序等部分组成。结构如下:,4.1 概述,-程序头(即定义变量和等值符号)-SCL BIT P1.2;定义SCL位变量SDA BIT P1.3;定义SDA位变量ByteCon DATA 30H;定义字节变量ByteCon ORG nnnn;CPU复位后,第一指令机器码存放单元地址,具体值由CPU类型决定。例4.8 在51系列中,复位后PC=0000,因此在51系列中,第一条指令存放在ROM的0000H单元中,即nnnn为“0000H”。,4.1 概述,LJMP Main;一般第一条指令是跳转指令,跳到主程序入口地址,其中“Main”是主程序入口地址标号。主程序不能直接存放在复位后PC指向的存储单元,原因是这一区域往往是中断服务程序的入口地址,不能覆盖,否则不能使用相应的中断功能。例4.9 在51系列中,外部中断0的入口地址为 0003H,显然只有0000H、0001H和0002H三个单元,刚好可以存放一条长跳转指令的机器码。,4.1 概述,-主程序-ORG yyyy;其中yyyy就是主程序代码存放区的首地址,如0100H Main:MOV SP,#5FH;初始化有关寄存器,如设置SP、选择工作寄存器组。;初始化中断控制寄存器等;主程序实体,具体指令由程序功能决定 LCALL SUB1;调用子程序1,其中SUB1为子程序名;END,4.1 概述,-子程序结构-ORG zzzz;其中zzzz就是子程序代码存放区的首地址,可以不用ORG指令,直接将子程序存放主程序后。SUB1:PUSH PSW PUSH Acc;通过PUSH指令保护子程序中用到的有关寄存器,如Acc、PSW 等,即保护现场;子程序实体,具体指令由程序功能决定 POP Acc POP PSW;恢复现场RET;子程序最后一条指令,使子程序指令运行结束后,返回主程序断点。,4.1 概述,-中断服务程序结构-ORG kkkk;其中kkkk就是中断程序代码存放区的首地址 PUSH PSW PUSH Acc;通过PUSH指令保护中断服务程序中用到的有关寄存器,如 Acc、PSW等,即保护现场;中断服务程序实体,具体指令由程序功能决定POP AccPOP PSW;恢复现场,4.1 概述,CLR TI;清除中断标志(在51系列中,对于电平触发的外中断INT0和 INT1、串行接收及发送中断 RI、TI等,不自动清除,需要在中断服务结束前,通过CLR指令清除。RETI;中断服务程序最后一条指令,返回主程序断点。为了确保子程序、中断服务程序运行结束后,能够正确返回,从断点处继续执行主程序,必须注意在子程序以及中断服务程序中堆栈操作指令的匹配问题,否则将无法返回。,4.1 概述,例4.10 在上述子程序结构中,假设SUB1子程序入口地址为2000H,即主程序内“LCALL SUB1”指令等效于“LCALL 2000”。假设该指令机器码首地址为1000H,且指令执行前,SP=5FH,则“LCALL 2000”指令执行过程中PC和SP内容如下:(1)PCPC+3,即PC=1003H(即断点地址);(2)SPSP+1,即SP=60H,并把PC低8位压入堆栈,于是(60H)=03;(3)SPSP+1,即SP=61H,并把PC高8位压入堆 栈,于是(61H)=10;,4.1 概述,(4)把 SUB1入口地址装入PC,即 PC=2000H。可见,“LCALL 2000”指令执行后,PC=2000H,已指向子程序SUB1第一条指令所在的存储单元地址;SP=61H。在子程序中 PUSH Acc;执行后,SP=62H,(62H)就是Acc的当前值,假设为XX PUSH PSW;执行后,SP=63H,(63H)就是PSW的当 前值,假设为YY返回前 POP PSW;执行后,PSW(SP),即将(63H)单元,4.1 概述,中原来的PSW返回给PSW;SPSP1,即SP=62HPOP Acc;执行后,ACC(SP),即将(62H)单元中原来的Acc返回给Acc;SPSP1,即SP=61HRET;执行后,PC高8位(SP),即将(61H)单元内容10H传给PC高8位,SPSP1,即SP=60H;PC低8位(SP),即将(60H)单元内容03H传给PC;低8位,SPSP1,即SP=5FH 结果PC=1003H(重新装入主程序断点地址),4.1 概述,汇编语言程序按其结构可分为以下四类:(1)顺序结构;(2)分支结构;(3)循环结构;(4)子程序结构。,4.2 顺序结构程序,4.2 顺序结构程序 最简单的一种结构,又称简单程序。特点:按照程序编写的顺序依次执行,不发生任何分支 或转移。(程序走向只有一条路径。)例4.11 将两个半字节数组合成一个字节数。设内部RAM中40H、41H单元分别存放着8位二进制数,要求将两个单元中的低半字节合并成一个字节后,存入42H单元。40H的低4位作为42H的高4位。,4.2 顺序结构程序,分析:首先要取数送A(传送指令),分离出低4位(逻辑与0FH),用A半字节交换送到高4位,地址加1,取另一个数低4位数(逻辑与0FH),用或合成一个字节。解:START:MOV R1,#40H MOV A,R1 ANL A,#0FH;取第一个半字节 SWAP A;移至高4位,4.2 顺序结构程序,INC R1XCH A,R1;取第二个字节ANL A,#0FH;取第二个半字节ORL A,R1;拼字INC R1MOV R1,A;存放结果RET例4.12 将20H单元的两个BCD码拆开并变成ASC码,存入21H、22H单元。注意:ASC码09为30H39H。分析:,4.2 顺序结构程序,把BCD数除以10,商A余B,刚好把两个BCD码分别移到A、B的低4位,然后再各自与30H相“或”,即变成ASC码。其程序框图如图4-1所示。采用先把20H中低4位BCD码交换出来加以转换、存放,然后再把高4位BCD码交换至低4位加以转换、存放。其程序框图如图4-2所示。,4.2 顺序结构程序,图4-1 BCD码转换为ASCII码方法一流程图解,4.2 顺序结构程序,编程:ORG 2000HMOV A,20HMOV B,#0AH;用0AH作除数DIV ABORL B,#30H;低4位BCD码变成ASC码MOV 22H,B ORL A,#30H;高4位BCD码变成ASC码 MOV 21H,AEND,4.2 顺序结构程序,图4-2 BCD码转换为ASCII码方法二流程图解,4.2 顺序结构程序,编程:ORG 2000HMOV R0,#22HMOV R0,#00H MOV A,20HXCHD A,R0 ORL 22H,#30H SWAP AORL A,#30HMOV 21H,AEND,4.3 分支结构程序,4.3 分支结构程序一、分支程序设计综述分支结构程序:根据程序要求无条件或有条件改变程序执行的顺序,选择程序的流向。特点:程序中含有转移类指令。关键:正确选用转移指令。单重分支程序:一个判断决策框,程序有两条出路。,4.3 分支结构程序,两种分支结构,4.3 分支结构程序,转移指令有3种:1、无条件转移 程序转移方向是设计者事先安排的,与已执行程序的结果无关,使用时只需给出正确的转移目标地址或偏移量即可。(LJMP、AJMP、SJMP)2、条件转移 根据已执行程序对标志位或A或对内部RAM某位的影响结果,决定程序的走向,形成各种分支。(JZ/JNZ、CJNE、DJNZ、位控制转移类指令)在编写有条件转移语句时要特别注意以下两点:(1)在使用条件转移指令形成分支前,一定要安排可供条件转移指令进行判别的条件。,4.3 分支结构程序,例如,若采用“JC rel”指令,在执行此指令前必须使用影响Cy标志的指令;若采用“CJNE A,#data,rel”指令,在执行此指令前必须使用改变A内容的指令,以便为测试做准备。(2)要正确选定所用的转移条件和转移目标地址。3、散转(JMPA+DPTR)它是根据某种已输入的“或”运算的结果,使程序转向各个处理程序中去。操作:把16位DPTR的内容与“或”运算的结果与在A中的8位无符号数相加,形成地址,装入PC,即散转的目的地址。其操作结果不影响A和DPTR。(JMP),4.3 分支结构程序,二、无条件/条件转移程序 分支程序中最常见的一类。其中,条件转移类程序编写较容易出错,编写时需要确定转移条件。例4.13 两个无符号数比较大小。同P59页例4-7 解 设外部RAM存储单元ST1和ST2中存放两个不带符号的二进制数,找出其中的大数存入ST3单元中。,4.3 分支结构程序,图4-3 两个无符号数比较大小程序框图,4.3 分支结构程序,解:ORG 8000H ST1 EQU 8040HSTART:CLR C;进位位清0 MOV DPTR,#ST1;读数据指针 MOVX A,DPTR;取第一个数 MOV R2,A;暂存R2 INC DPTR MOVX A,DPTR;取第二个数 SUBB A,R2;两数比较 JNC BIG1;若Cy=0,则转BIG1(第二个数大),4.3 分支结构程序,XCH A,R2;第一个数大 BIG0:INC DPTR MOVX DPTR,A;存大数 RET BIG1:MOVX A,DPTR;第二个数大 SJMP BIG0 END 上面程序中,应用带借位的减法指令SUBB比较两数的大小。在执行指令前,应先把进位位清“0”。执行JNC指令后形成分支,指令中BIG1为标号地址,表示相对偏移量rel。,4.3 分支结构程序,例4.14 设5AH单元中有一变量X,请编写计算下列函数式的程序,结果存入5BH单元。同P61页例4-8.,4.3 分支结构程序,图4-4 例4.6程序流程图,4.3 分支结构程序,解:根据题意首先计算X2(使用乘法)并暂存于R1中,因为X2最大值为225,可只用一个寄存器,然后根据X值的范围,决定Y的值。R0作中间寄存器。编程:ORG 2000H MOV A,5AH MOV B,A MUL AB;AX2 MOV R1,A MOV A,5AH;重新把X装入A CJNE A,#10,L1,4.3 分支结构程序,L1:JC L2;C=1,X10转L2MOV R0,#41;先假设X15 CJNE A,#10H,L3;与16比较 L3:JNC L4;C=0,X15转L4 MOV A,R1 ADD A,#8;10X15,Y=X2+8 MOV R0,A SJMP L4 L2:MOV A,R1CLR CSUBB A,#01;X10,Y=X2-1,4.3 分支结构程序,MOV R0,A L4:MOV 5BH,R0;存结果 SJMP$END 由于本题的具体情况,在判别(A)10和(A)15时采用的是“CJNE”和“JC”以及“CJNE”和“JNC”两条指令相结合的方法。条件分支程序与简单程序的区别在于:分支程序存在两个或两个以上的结果。要根据给定的条件进行判断,以得到某一个结果。这样,就要用到比较命令、测试指令以及无条件/条件转移指令。条件分支程序设计 的技巧,就在于正确而巧妙地使用这些命令。,4.3 分支结构程序,例题:求符号函数的值。已知片内RAM的40H单元内有一自变量X,编制程序按如下条件求函数Y的值,并将其存入片内RAM的41H单元中。1 X0Y=0 X=0-1X0,解:此题有三个条件,所以有三个分支程序。这是一个三分支归一的条件转移问题。X是有符号数,判断符号位是0还是1可利用JB或JNB指令。判断X是否等于0则直接可以使用A的判0指令。程序流程图如右图所示。,ORG 1000HSTART:MOV A,40H;将X送入A中JZ COMP;若A为0,转至COMP处JNB ACC.7,POST;若A第7位不为1(X为正数),则程序转到POST处,否则(X为负数)程序往下执行MOV A,#0FFH;将1(补码)送入A中SJMP COMP;程序转到COMP处POST:MOV A,#01H;将+1送入A中COMP:MOV 41H,A;结果存入YSJMP$;程序执行完,“原地踏步”END,4.3 分支结构程序,三、散转程序设计散转程序:一种并行分支程序(多分支程序),它是根据某种输入或运算结果,分别转向各个处理程序。转移的地址最多为256个。其结构如图下所示。,4.3 分支结构程序,散转程序设计采用下面两种方法:(JMP ADPTR)(1)DPTR固定,根据A的内容,程序转入相应的分支程序中去。(2)A清“0”,根据DPTR的值,决定程序转向目的地址。DPTR的值可用查表或其他方法获得。1、采用转移指令表在许多应用中,需要根据某标志单元的内容(输入或运算结果)0,1,2,n,分别转向操作程序0、操作程序1、操作程序2、操作程序n。,4.3 分支结构程序,解决步骤:(1)可先用“AJMP”或“LJMP”指令按序组成一个转移表;(2)将转移表首地址装入DPTR中;(3)将标志单元的内容装入A经运算后作为变址值;(4)执行“JMP ADPTR”指令实现散转。例4.15 128种分支转移程序。根据入口条件转移到128个目的地址。,4.3 分支结构程序,图4-5 分支转移程序框图,4.3 分支结构程序,解:入口:(R3)=转移目的地址的序号00H7FH。出口:转移到相对子程序入口。编程:JMP-128:MOV A,R3 CLR C RLC A;A(A)2 MOV DPTR,#JMPTAB JMP A+DPTR JMPTAB:AJMP ROUT00;128个子程序首址 AJMP ROUT7F,4.3 分支结构程序,此程序要求128个转移目的地址(ROUT00ROUT7F)必须驻留在与绝对转移指令AJMP同一个2KB存储区内。RL指令对变址部分乘以2,是由于每条AJMP指令占用2个字节。,4.3 分支结构程序,2、采用地址偏移量表 上面介绍的散转程序,首先必须建立转移指令表,程序根据散转点执行“JMP ADPTR”指令,进入转移表后,再由双字节“AJMP”指令转入2KB空间范围内的操作入口或由三字节“LJMP”指令转入64KB空间范围内的操作入口。如果散转点较少,所有操作程序处在同一页(256B)时,可使用地址偏移量转移表。例4.17 根据R7的内容转向5个操作程序。解:JUMP3:MOV A,R7 MOV DPTR,#TAB3 MOVC A,A+DPTR,4.3 分支结构程序,JMP A+DPTR TAB3:DB OPR0-TAB3 DB OPR1-TAB3 DB OPR2-TAB3 DB OPR3-TAB3 DB OPR4-TAB3 OPR0:操作程序0 OPR1:操作程序1 OPR2:操作程序2 OPR3:操作程序3 OPR4:操作程序4,4.3 分支结构程序,从本例可以看出,地址偏移量表每项对应一个操作程序的入口,占一个字节,分别表示对应入口地址与表首的偏移量。使用这种方法,地址偏移量表的长度加上各操作程序长度必须在同一页内。当然,最后一个操作程序的长度不受限制,只要其程序入口与地址偏移量表首的偏移量在一个字节内(小于256)就可以。,4.3 分支结构程序,3、采用转向地址表 采用地址偏移量表的方法,其转向范围局限于一页,使用受限制。若使用转向较大的范围,方法:(1)建立一个转向地址表,即将所要转向的双字节地址组成一个表;(2)在散转时,先用查表方法获得表中的转向地址;(3)将该地址装入DPTR中,再清A;(4)执行“JMP ADPTR”指令,程序转入所要到达的目的地址中去。例4.18 根据R7的内容转入各对应的操作程序中去。解 设转移入口地址为OPR0、OPR1、OPRn,散转程序及转移表如下:,4.3 分支结构程序,JMUP4:MOV DPTR,#TAB4 MOV A,R7 ADD A,R7;A(R7)2 JNC NADD INC DPH;(R7)2进位加至DPH NADD:MOV R3,A;暂存 MOVC A,ADPTR;取地址高8位 XCH A,R3;置转移地址高8位 INC A MOVC A,ADPTR;取地址低8位,4.3 分支结构程序,MOV DPL,A;置转移地址低8位 MOV DPH,R3 CLR A JMP ADPTR TAB4:DW OPR0 DW OPR1 DW OPRn 这种散转方法可以达到64KB地址范围内的转移,但也可看出,散转数n小于256。若要使n大于255,可用双字节加法运算的方法修改DPTR。,4.4 循环结构程序,4.4 循环结构程序 循环程序设计:能连续多次重复执行的某段程序。目的:缩短程序长度,节省存储单元,提高所编写程序的质量。一、循环结构程序组成(1)初始化部分 为循环程序作准备。如设置循环次数计数器初值,地址指针置初值,为其他变量赋初值等。一个重要部分,不注意容易出错。(2)处理部分 重复执行的程序段,循环程序的实体。,4.4 循环结构程序,(3)循环控制部分 每执行一次循环体后,都要为下一次循环作必要的准备。如修改计数器值;检查循环条件是否符合,以决定继续循环或退出循环。(4)结束部分 分析或存放执行结果。二、循环结构程序两种基本结构(1)计数循环结构(先处理后控制):先进入处理部分再控制循环。此结构至少执行一次循环体;,4.4 循环结构程序,(2)条件循环结构(先控制后处理):先控制循环,后进入处理部分。此结构有时不进入循环体就退出循环,故称之“允许0次循环的循环程序”。注:循环结构的程序,其关键是控制循环次数。对循环次数的控制方法有:循环次数已知,用计数器控制循环;次数未知,按条件控制循环;按逻辑尺控制循环。有些情况下,循环体中的处理部分为分支程序,这就构成分支循环结构。实际中常用逻辑尺来控制分支和循环。所谓逻辑尺就是一个存储单元(字节或字单元),在这存储单元中的每一位便是一个标志,它有两个状态0或1。根据标志位为0或为1就可以实现两路分支,多个标志就可重复地实现分支。可见,重复的次数就是逻辑尺中设定的位数。,4.4 循环结构程序,4.4 循环结构程序,三、循环程序分类单循环程序:结构特点:循环体为顺序结构或分支结构,每循环一次,执行一次循环体程序。循环体中不包含循环程序。51所用指令:DJNZ Rn,rel;以Rn作控制计数器 DJNZ direct,rel;以direct作控制计数器多重循环程序(循环嵌套)结构特点:在循环体中还包含有循环的程序。若把每重循环的内部看作一个整体,则多重循环结构与单循环结构是一样的。,4.4 循环结构程序,四、使用多重循环程序必须注意的问题 循环嵌套必须层次分明,不允许产生内外层交叉;外循环可以一层层向内循环进入,结束时由里向外一层层退出;内循环体可以直接转入外循环体,实现一个循环由多个条件控制的循环结构方式。,4.4 循环结构程序,五、举例 例4.11 多个单字节数据求和。解设Xi为单字节数(i=1n),依次存放在内部RAM中50H单元开始的连续单元中。要求n放入R2中,把计算结果存入R3R4中(高位存入R3,低位存入R4)。,4.4 循环结构程序,图4-6 多个单字节数据求和程序框图,4.4 循环结构程序,参考程序 ADD1:MOV R3,#00H MOV R4,#00H MOV R2,#n;R2为循环次数计数器 MOV R0,#50H;R0作间址寄存器用它来寻址Xi LOOP:MOV A,R4;取部分和低位 ADD A,R0;与Xi相加 MOV R4,A INC R0;地址加1 CLR A ADDC A,R3;低位字节向高位进位 MOV R3,A DJNZ R2,LOOP;未加完继续重复,练习题,例题 已知片内RAM 30H3FH单元中存放了16个二进制无符号数,编制程序求它们的累加和,并将其和数存放在R4,R5中。,解:每次求和的过程相同,可以用循环程序实现。16个二进制无符号数求和,循环程序的循环次数应为16次(存放在R2中),它们的和放在R4,R5中(R4存高8位,R5存低8位)。程序流程图如右图所示。,程序如下:ORG 1000HSTART:MOV R0,#30H MOV R2,#10H;设置循环次数(16)MOV R4,#00H;和高位单元R4清0 MOV R5,#00H;和低位单元R5清0LOOP:MOV A,R5;和低8位的内容送A ADD A,R0;将R0与R5的内容相加并产生进位Cy MOV R5,A;低8位的结果送R5 CLR A;A清0 ADDC A,R4;将R4的内容和Cy相加 MOV R4,A;高8位的结果送R4 INC R0;地址递增(加1)DJNZ R2,LOOP;若循环次数减1不为0,则转到LOOP处循环;否则,循环结束 SJMP$END,例题 编制程序将片内RAM的30H4FH单元中的内容传送至片外RAM的2000H开始的单元中。同书上P48,P49 例3-32,3-34,解:每次传送数据的的过程相同,可用循环程序实现。30H4FH共32个单元,循环次数应为32次(保存在R2中),为了方便每次传送数据时地址的修改,送片内RAM数据区首地址送R0,片外RAM数据区首地址送DPTR。程序流程图如右图所示。,程序如下:ORG 1000H START:MOV R0,#30H MOV DPTR,#2000H MOV R2,#20H;设置循环次数 LOOP:MOV A,R0;将片内RAM数据区内容送A MOVX DPTR,A;将A的内容送片外RAM数据区 INC R0;源地址递增 INC DPTR;目的地址递增 DJNZ R2,LOOP;若R2的不为0,则转到LOOP处继续循环;否则循环结束 SJMP$END,4.4 循环结构程序,例4.12 已知80C51单片机作用的晶振为6MHz,要设计 一个软件延时程序,延时时间为10ms。同书P63例4-11分析:延时时间主要与两个因素有关:(1)所用晶振;(2)延时程序中的循环次数。现已知晶振为6MHz,则可知一个机器周期为2s,那么DJNZ指令为2个机器周期,共4s,采用单重循环要循环250次,可实现1ms的延时,1ms则再用一循环,循环10次,可得10ms延时。,4.4 循环结构程序,图4-7 延时程序框图,4.4 循环结构程序,解 本例采用循环体为两NOP指令,则(1+1+2)2sMT=1ms,MT=125=7DH ORG 2000H MOV R0,#0AH;毫秒数R0 DL2:MOV R1,#MT;1ms延时的预定值MTR1 DL1:NOP NOP DJNZ R1,DL1;1ms延时循环 DJNZ R0,DL2;毫秒数减1,不等于0则继续循环,等于0结束 END,4.4 循环结构程序,若考虑其他指令的执行时间,则该段延时程序的精确延时时间计算如下:2s1(12)2s(112)2s125 10=10062s若需要延时更长时间,可采用更多重循环,如1s延时可用3重循环,而7重循环可延时1年。注意:在采用软件实现延时功能时,不允许使用中断,否则将影响定时精度。,例题 编制程序设计50ms延时程序。,解:延时程序与51系列指令执行时间(机器周期数)和晶振频率fOSC有直接的关系。当fOSC=12MHz时,机器周期为1s,执行一条DJNZ指令需要2个机器周期,时间为2s。50ms2s255,因此单重循环程序无法实现,可采用双重循环的方法编写50ms延时程序。,程序如下:ORG 1000H DELAY:MOV R7,#200;设置外循环次数(此条指令需要1个机器周期)DLY1:MOV R6,#123;设置内循环次数 DLY2:DJNZ R6,DLY2;(R6)1=0,则顺序执行,否则转回DLY2继续循环,延时时间为2s123=246s NOP;延时时间为1s DJNZ R7,DLY1;(R7)1=0,则顺序执行,否则转回DLY1继续循环,延时时间为(246211)20021=50.003ms RET;子程序结束 END,4.4 循环结构程序,例4.13 将20H单元内的两个BCD数相乘,相乘的结果要求仍为BCD数,乘积存入21H单元。分析:两个BCD数最大的是99,99=81。若采用“MUL”指令,则结果为51H,而对乘法没有十进制调整指令。所以,在此必须采用加法与十进制调整指令重复执行的方法。,4.4 循环结构程序,图4-8 BCD数乘法流程图,4.4 循环结构程序,解 ORG 2000H MOV A,20H ANL A,#0FH;把BCD数的低位分离出来 MOV R0,A MOV A,20H SWAP A;变换BCD数的高低位 ANL A,#0FH;把BCD数的高位分离出来 MOV R1,A CLR A;清A,4.4 循环结构程序,LP:ADD A,R1 DA A DJNZ R0,LP;R0个R1相加 MOV 21H,A LP1:SJMP LP1 END本程序中,循环体只有ADD、DA、DJNZ 3条指令,这3条指令的作用是把乘法变为累加。,4.4 循环结构程序,例4.14 冒泡程序。设有n个数,分别存放在RAM中LIST地址开始的连续存储单元中,要求将n个数比较大小之后,按由小到大的次序排列,再存入原存储区。设n=7,参与比较的数为0,13,3,90,27,32,11。分析:依次将相邻两个单元的内容进行比较。即第一个数与第二个数进行比较,第二个数与第三个数进行比较,依此进行,如符合由小到大的顺序,则不改变它们在内存中的位置,否则交换它们之间的位置。如此反复比较,直到数列排完为止。,4.4 循环结构程序,由于在比较过程中,小数向上冒,因此这种排序程序称为“冒泡程序”,比较过程如下:,4.4 循环结构程序,第一轮经过6次两两比较,得到一个最大数;第二轮经过5次两两比较,得到一个次大数;依此类推。每轮比较后得到本轮最大数,该数就不再参与下一轮的比较,故每轮比较次数减1。为加快排序速度,程序中设置一个标志位,只要在比较过程中两数之间没有发生过交换,就表示数列已按由小到大的顺序排列好了,就可以结束比较。,4.4 循环结构程序,图4-9 冒泡程序流程图,4.4 循环结构程序,设数列首地址存于R0中,R2为外循环次数计数器,R3为内循环次数计数器,R1为交换标志。解 ORG 0050H LIST DB 0,13,3,90,27,32,11 CNT EQU 07H ORG 8000H MOV R2,#CNT-1;数列个数减1,这里(R2)=7-1,4.4 循环结构程序,LOOP1:MOV A,R2;外循环计数值 MOV R3,A;内循环计数 MOV R1,#01H;交换标志位 LOOP2:MOV A,R0;取数据 MOV B,A;暂存B INC R0 CLR C SUBB A,R0;两数比较 JC LESS;XiXi+1转LESS,4.4 循环结构程序,MOV A,B;取大数 XCH A,R0;两数交换位置 DEC R0 MOV R0,A INC R0;恢复数据指针 MOV R1,#02H;置交换标志位为2 LESS:DJNZ R3,LOOP2;内循环计数减1,判一遍查完?DJNZ R2,LOOP3;外循环计数减1,判排序结束?STOP:RET,4.4 循环结构程序,LOOP3:DJNZ R1,LOOP1;发生交换转移 SJMP STOP END 练习题:200名学生参加考试,成绩放在80C51的外部RAM的一个连续存储单元,95100分颁发A级证书,9094分颁发B级证书,低于90分不计。编写程序,统计获A、B级证书的人数。将结果存入内部RAM的两个单元。注意:地址指针的分配 参考程序:,4.4 循环结构程序,ORG 0030H EGX DATA 1000H;存放成绩的外部连续存储单元起始地址 GA DATA 20H;设置存放获取A级证书人数的单元 GB DATA 21H;设置存放获取B级证书人数的单元 MOV GA,#00 MOV GB,#00 MOV DPTR,#EGX;初始化,数据块首地址 MOV R2,#200;定义计数器,200名学生数LOOP:MOVX A,DPTR CJNE A,#95,LOOP1,4.4 循环结构程序,LOOP1:JNC NEXT1;C=0,A=95转至NEXT1 CJNE A,#90,LOOP2 LOOP2:JC NEXT INC GB SJMP NEXT NEXT1:INC GA NEXT:INC DPTR DJNZ R2,LOOP SJMP$END,4.5 子程序结构,4.5 子程序结构一、概念子程序:完成确定任务,并能为其他程序反复调用的程序段。要求子程序在结构上具有通用性和独立性。例如:代码转换,运算程序,任意数的平方等。子程序的调用与返回:主程序调用子程序的过程:在主程序中需要执行这种操作的地方执行一条调用指令(LCALL或ACALL),转到子程序,而完成规定的操作后,再在子程序最后应用RET返回指令返回到主程序断点处,继续执行下去。,4.5 子程序结构,子程序的调用子程序的入口地址:子程序的第一条指令地址,常用标号表示。程序的调用过程:单片机收到ACALL或LCALL指令后,首先将当前的PC值(调用指令的下一条指令的首地址)压入堆栈保存(低8位先进栈,高8位后进栈),然后将子程序的入口地址送入PC,转去执行子程序。子程序的返回主程序的断点地址:子程序执行完毕后,返回主程序的地址,它在堆栈中保存。子程序的返回过程:子程序执行到RET指令后,将压入堆栈的断点地址弹回给PC(先弹回PC的高8位,后弹回PC的低8位),使程