资源描述
单击此处编辑母版标题样式,*,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,第7章 汇编语言程序设计,教学目的:,熟悉80C51系列单片机的汇编语言,能够熟练编写汇编语言源程序。,教学重点:,常用汇编语言程序设计方法。,教学难点:,分支程序、散转程序与子程序的设计,7.1 概述,7.1.1 汇编语言源程序的格式,1.汇编语句格式,标号:操作码 操作数 ;注释,这4部份只有操作码段是必须具有的,其余部分为可选项,但对于包含操作数的指令,则操作数段也是必须具有的。,例如:,SU:MOV A,0CDH ;CDH,A,7.1.2 汇编语言伪指令,(1)ORG 汇编起始指令,规定目标程序的起始地址,格式如下:标号 操作码 操作数,ORG 表达式(exp),(2)EQU 赋值指令,把操作数段中的地址或数据赋值给标号,格式如下:,标号 操作码 操作数,字符名称 EQU 数或汇编符号,例1 AA EQU R1 ;R1与AA等值,则 MOV A,AA 指令与 MOV A,R1指令结果相同。,(3)DB定义字节指令,定义程序存储器中存放的8位常数表,,格式如下:,(标号)操作码 操作数,DB 字节常数或ASCII字符,例2 ORG 1000H,DB 76H,73,C,B;在表示ASCII字 符时要用 括号,DB OACH,则 (1000H)76H (1001H)49H (1002H)43H (1003H)42H (1004H)0ACH,(4)DW 定义字指令,定义程序存储器中存放的16位常数表,格式 DW。,例3 ORG 2200H,DW 1246H,7BH,10,则 (2200H)12H (2201H)46H,(2202H)00 (2203H)7BH,(2204H)00 (2205H)0AH,(5)BIT 定义位地址指令,格式 BIT,例4 ABC BIT P1.0,Q4 BIT P2.2,则汇编后,位地址P1.0,P1.2分别赋给变量ABC和Q4。,(6),END 汇编结束指令,7DATA定义标号数值伪指令,它的功能是给标号段中的数据地址标号赋以数值,也称为数据地址赋值指令。它的格式如下:,字符名称 DATA 表达式,例6 M5 DATA 1A00H,汇编后M5的值为1A00H。,8DS 定义存储空间指令,它的功能是从指定地址开始,定义一个存储区,保留由表达式指定的若干字节空间作为备用空间,这个存储区预留的存储单元数由DS表达式的值决定。,它的格式如下:DS 表达式,表达式通常是一个常数。,例7 ORG 500H,DS 10H,DB 4BH,5AH,72 顺序与循环程序设计,7.2.1 顺序程序设计,例1,将R5中的两个BCD码拆开并变成ASCII码,存入61H、62H单元。,解:在此采用把BCD数除以10H的方法,除后相当于把此数右移了4位,刚好把两个BCD码分别移到A、B的低4位。由于ASCII码的09为30H39H。然后再各自与30H相或即变为ASCII码。,源程序如下:,ORG 0000H,LJMP MAIN,ORG 30H ;主程序起始地址,MAIN:MOV A,R5,MOV B,10H;用10H作除数,DIV AB,ORL B,30H ;低4位BCD码变为ASCII码,MOV 62H,B,ORL A,30H;高4位BCD码变为ASCII码,MOV 61H,A,SJMP$;循环等待,END,7.2.2 循环程序设计,1.循环初态(或称初始条件),循环初态是设置循环过程中工作单元的初始值。,2.循环体,重复执行的程序段部分。,3.循环控制部分。,用于控制循环的执行和结束。,例2 已知:80C51单片机使用的晶振为12MHz,要求设计一个软件延时程序,延时时间为20ms。,解:延时程序的延时时间主要与两个因素有关,一个是所用晶振,一个是延时程序中的循环次数。一旦晶振确定之后,则主要是如何设计与计算需给定的延时循环次数。在本题中已知晶振为12MHz,则可知一个机器周期为1,s,可预计采用单重循环是有可能实现1ms的延时的。现根据题意编写源程序如下:,周期数,1 MOV R0,14H ;毫秒数,R0,1 DL2:MOV R1,MT;1ms延时的预定值MT,R1,1 DL1:NOP,1 NOP,2 DJNZ R1,DL1;lms延时循环,2 DJNZ R0,DL2;毫秒数减1,不等于0,继续循环,等于0结束,例3 从22H单元开始有一个无符号数据块,其长度在20H单元。求出数据块中最大值,并存入21H单元,ORG 200H,CLR A ;清A作为初始最大值,MOV R2,20H ;数据个数初值,MOV R1,22H ;数据块首地址初值,LP:CLR C ;清进位,SUBB A,R1 ;最大值减队列中数,JNC NEXT ;小于最大值继续,SJMP NEXT1,SUBB A,R1 ;最大值减队列中数,JNC NEXT ;小于最大值继续,SJMP NEXT1,MOV A,R1 ;大于最大值,则用此值代换,NEXT:ADD A,R1;小于最大值,则恢复,NEXT1:INC R1 ;修改地址指针,DJNZ R2,LP ;依次重复比较,直至R20,MOV 21H,A ;最大值存入21H单元,73 分支程序设计,7.3.1 分支程序设计综述,分支程序应用要点是正确使用转移指令,通常有如下3种指令。,1.无条件转移,2.条件转移,3.散转,例1 设5AH单元中有一变量X,请编写计算下述函数式的程序,结果存入5BH单元,7.3.2 无条件/条件转移程序,MOVA,5AH,MOVB,A,MULAB ;,X,2,BA,MOVR1,,,A,MOVA,,,5AH ;,重新把,X,装入,A,CJNEA,,,#5,,,L1,Ll,:,JCL2 ;,X,10,CJNEA,,,#11,,,L3 ;,与,11,比,L3,:,JNCL4 ;,X,10,转,L4,MOVA,R1,ADDA,#08 ;10,X,5,Y,=,X,2+8,MOVR0,A,SJMPL4,L2,:,MOVA,R1,CLRC,SUBBA,,,#01 ;,X,10,,,Y,=,X,21,MOVR0,,,A,L4,:,MOV5BH,,,R0,SJMP,7.3.3 散转程序设计,散转程序的设计可采用下面两种方法:,(1)数据指针DPTR固定,根据累加器A的内容,程序转入相应的分支程序中去。,(2)累加器A清零,根据数据指针DPTR的值,决定程序转向的目的地址,DPTR的值可用查表或其他方法获得。,下面介绍两种不同方法的散转程序。,1采用转移指令表,例1 设有n个分支程序,n小于256,将n存放在R4中,设计散转程序。,解:程序清单如下。,MOV DPTR,TAB1 ;跳转表首地址送数据指针,MOV A,R4,ADD A,R4;R42,A(修正变址值),JNC NOAD ;判有否进位,INC DPH ;有进位则加到高字节地址,NOAD:JMP ADPTR ;转向形成的散转地址入口,TAB1:AJMP OPR0 ;转移到分支程序OPR0,AJMP OPR1,.,AJMP OPRn,2采用转向地址表,例,7.13,根据R2的内容转入各对应的分支程序中去。,解 设转移入口地址为OPR0、OPR1、OPRn,散转程序及转移表如下:,MOVDPTR,#TAB1,MOVA,R2,ADDA,R2 ;(R2)2,A,JNCNADD,INCDPH ;(R2)2的进位加至DPH,NADD:MOVR3,A ;暂存,MOVCA,A+DPTR ;取地址高8位,XCHA,R3 ;转移地址高8位暂存到R3,INCA,MOVCA,A+DPTR ;取地址低8位,MOVDPL,A ;置转移地址低8位,MOVDPH,R3;置转移地址高8位,CLRA,JMPA+DPTR ;转向分支程序,TAB1:DWOPR0 ;16位转移地址表的首地址,DWOPR1,DWOPRn,74 子程序设计,7.4.1 子程序结构与设计注意事项,子程序结构,编写子程序时的注意事项,在编写子程序时要注意以下几点:,(1)要给每个子程序赋一个名字,实际上是一个入口地址的代号。,(2)要能正确地传递参数。即首先要有入口条件,说明进入子程序时,它所要处理的数据如何得到。另外,要有出口条件,即处理的结果是如何存放的。,(3)注意保护现场和恢复现场。,7.4.2 子程序的调用与返回,主程序调用子程序是通过子程序调用指令LCALL addl6和ACALL add11实现的。子程序的返回是通过返回指令RET实现的。,主程序在调用子程序时要注意以下问题:,(l)在需要保护现场的程序中,在主程序初始化时要正确地设置堆栈指针。,(2)在主程序中,要安排相应指令,满足子程序的入口条件。,(3)在主程序中,安排相应的指令,在子程序返回后,处理子程序提供的出口参数。,7.4.3 子程序设计举例,例1,有两个ASCII码值表示的字符串,2个字符串的首地址分别为50H和70H,每个字符串的第一个字节都存放字符串长度。求出这2个字符串中字符A的个数,并将其和存入4FH单元。,解:本例采用分别求出两个字符串字符A的个数,然后求和的方法,求字符A个数的过程可采用子程序。子程序的入口条件是字符串首地址,返回参数即为个数值,放在A中。,下面分别列出主程序和子程序:,主程序,MOV R1,50H ;置入口条件参数 ACALL ZF ;调求字符A个数子程序 MOV 40H,R0 ;第一个数据块的A个数暂存40H,MOV R1,70H ;置入口条件参数,ACALL ZF ;调求字符A个数子程序,MOV A,,R0,ADD A,40H ;两个字符A个数相加,MOV 4FH,A ;把和送入4FH,SJMP ,子程序 ;子程序入口参数:R1为字符串首地址,;子程序出口参数:R0为字符串中A的个数,ZF :MOV R0,#0;清R0作为初始值,MOV A,R1 ;取字符个数初值,MOV R2,A;字符个数初值送R2,LP:MOV A,R1;取字符,CJNE A,#41H,LP1;与字符A比较,INC R0 ;等于加1后继续,LP1:INC R1;修改地址指针,DJNZ R2,LP;依次重复比较,直至R20,RET ;返回,例2,编制一个循环闪烁灯的程序。有8个发光二极管,每次其中一个灯闪烁点亮10次后,转移到下一个灯闪烁点亮10次,循环不止。,MOVSP,#3FH ;设堆栈指针,MOV A,#01 ;初值,SHIFT:LCALLFLASH ;调闪亮10次子程序,RRA ;右移,SJMPSHIFT ;循环,FLASH:MOV R2,#0AH ;闪烁次数送R2(第0组),FLASH1:MOV Pl,A ;点亮,LCALLDELAY ;延时,MOV P1,#00H ;熄灭,LCALL DELAY ;延时,DJNZ R2,FLASH1;循环,RET,DELAY:PUSH02H ;保存R2(第0组R2地址为2),MOVR2,#0F0H ;赋延时初值,可以按延时要求选择,LP,:,DJNZR2,,,LP,POP 02H ;恢复第0组R2,RET,75 查表程序设计,7.5.1 查表程序综述,为了实现查表功能,在80C51汇编语言中专门设置了两条查表指令:,MOVC A,A+DPTR,MOVC A,A+PC,这2条指令特点不同,在应用时要注意区别。,为了便于查表,要求表中的数或符号按照便于查找的次序排列,并将它存放在从指定的首地址(或称基地址)开始的存储单元。,7.5.2 查表程序设计举例,例1 设计一个将16进制数转换成ASCII码的子程序,设16进制数存放在R0的低4位,要求将转换后的ASCII码送回R0。,ORG 60H,MOV A,R0,ANL A,0FH;保留低4位,ADD A,2 ;变址调整,MOVC A,APC;查表获取ASCII码值,MOV R0,A,RET,TAB:DB 30H,31H,32H,33H,34H,35H,DB 36H,37H,38H,39H,41H,42H,43H,44H,45H,46H,
展开阅读全文