【大学】单片机课件-汇编语言程序设计PPT_第1页
【大学】单片机课件-汇编语言程序设计PPT_第2页
【大学】单片机课件-汇编语言程序设计PPT_第3页
【大学】单片机课件-汇编语言程序设计PPT_第4页
【大学】单片机课件-汇编语言程序设计PPT_第5页
已阅读5页,还剩223页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、第四章汇编语言程序设计4.1 概述 4.2 顺序结构程序4.3 分支结构程序4.4 循环结构程序4.5 子程序结构4.6 综合程序举例4.7 本章小节4.8 思考与练习题第四章汇编语言程序设计 主要内容:本章从程序结构和实用角度出发,通过典型的应用实例介绍汇编语言程序的基本结构及模块化程序设计,使学生进一步理解和掌握51系列单片机的指令系统,并掌握汇编语言程序设计的基本语言和技巧。 要求: 1、熟练运用指令系统,掌握循环程序、分支程序和搜索程序的设计方法; 2、熟练运用指令系统,掌握基本的运算程序设计方法; 第四章汇编语言程序设计 3、熟练运用指令系统,掌握数制和码制转换程序的设计方法; 4、

2、熟练掌握子程序结构,实现模块化程序设计; 5、深刻理解软件、硬件的相互作用,不断提高实际问题处理程序编写能力。 4.1 概述 4.1 概述 程序设计:为了解决某一个问题,将所设计应用系统(单片机类型)的指令按一定顺序组合在一起。即用计算机所能接受的语言把解决问题的步骤描述出来。 单片机汇编源程序结构与通用微机汇编源程序结构略有不同,原因是: 1、一般没有可以直接利用的监控程序,所有程序均要自己编写。4.1 概述 2、没有像X86汇编语言程序那样,可直接调用系统提供的中断功能(如:BIOS中断、DOS中断)或Windows的API函数完成特定操作,即所有子程序(如键盘监控子程序、显示驱动程序、中

3、断服务程序等)均需要自己编写。 汇编语言语句三种基本类型:指令语句、伪指令语句、宏指令语句。4.1 概述 一、汇编语言伪指令 伪指令 汇编程序某些指令在汇编时并不产生目标代码,不影响程序的执行,不是CPU能执行的指令,只提供一些汇编控制信息的指令。常用的伪指令: (1)设置起始地址ORG 格式:ORG nn 1、ORG:表明为后续源程序经汇编后的目标程序安排存放位置,nn则给出了存放的起始地址值; 4.1 概述 2、ORG总是出现在每段源程序或数据块的开始; 3、在一个源程序中,可以多次使用ORG规定不同程序段的起始位置,但定义的地址顺序应从小到大,且不能重叠; 4、若不用ORG,则汇编将从0

4、000H单元开始存放目标程序; 例4.1ORG 3000H;表示后续的目标程序代码从3000H单元开始存放。MOV A,30H 4.1 概述 (2)定义字节DB 格式:标号:DB字节数据项表 1、标号区段可有可无,项表指中间用逗号分开的字节、数、字符串或用引号括起来的ASC码字符串(一个字符用ASC码表示,就相当于一个字节)。 2、功能:把项表的数据存入从标号开始的连续单元中。 例4.2ORG 2000HSEG1:DB 35H,78H4.1 概述 SEG2:DB DAY END则 (2000H)=35H,(2001H)=78H,(2002H)=44H,(2003H)=41H,(2004H)=5

5、9H 注意:项表中若为数值,其取值范围应为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 数据或表达式 把数据地址或代码地址赋

6、予字符名称。常用于定义数据地址,它可以先使用后定义(因为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伪指令对标号赋值后,该标号的值在整

7、个程序中不能再改变; 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、在整个程序的最后面。 (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、编制说明要解决问题

9、的程序框图。画程序框图:用各种图形、符号、指向线等来说明程序设计的过程。框图步骤写得越细致,编程时也就越方便。目的:把具有一定功能的各个部分有机地联系起来,可以使人们抓住程序的基本线索,对全局有完整的了解。4.1 概述好处:(1)容易发现设计思想上的错误和矛盾,便于找出解决问题的途径。(2)便于把较大的程序分成若干个模块,从而分头进行设计,最后合在一起联调。5、按所使用计算机的指令系统,依据框图写出汇编语言程序。编程的三个原则:尽可能的节省数据存储单元;缩短程序长度;减少执行时间。4.1 概述.合理分配存储器单元和了解I/O接口地址。.按功能设计程序,明确各程序之间的相互关系。.用注释行说明程

10、序,便于阅读、调试和修改。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

11、的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 ;初始化有

12、关寄存器,如设置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 ;子程序最后一条指令,使子程序指令运行结束后,返回主程序断点

13、。 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 ;中断服务程序最后一条指令,返回主程序断点。为了确保子程序、中断服务程序运行结束后,能够正

14、确返回,从断点处继续执行主程序,必须注意在子程序以及中断服务程序中堆栈操作指令的匹配问题,否则将无法返回。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位压入堆 栈

15、,于是(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)单元

16、中原来的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.1

17、1 将两个半字节数组合成一个字节数。 设内部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

18、 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 2000H

19、MOV 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 分支结构程序一、分支程序设计综述分支结构程序:根据程序要求无条件或有

20、条件改变程序执行的顺序,选择程序的流向。 特点:程序中含有转移类指令。 关键:正确选用转移指令。 单重分支程序:一个判断决策框,程序有两条出路。4.3 分支结构程序两种分支结构 4.3 分支结构程序转移指令有3种: 1、无条件转移 程序转移方向是设计者事先安排的,与已执行程序的结果无关,使用时只需给出正确的转移目标地址或偏移量即可。(LJMP、AJMP 、SJMP) 2、条件转移 根据已执行程序对标志位或A或对内部RAM某位的影响结果,决定程序的走向,形成各种分支。(JZ/JNZ、CJNE、DJNZ、位控制转移类指令) 在编写有条件转移语句时要特别注意以下两点: (1)在使用条件转移指令形成分

21、支前,一定要安排可供条件转移指令进行判别的条件。4.3 分支结构程序例如,若采用“JC rel”指令,在执行此指令前必须使用影响Cy标志的指令;若采用“CJNE A,#data,rel”指令,在执行此指令前必须使用改变A内容的指令,以便为测试做准备。 (2)要正确选定所用的转移条件和转移目标地址。3、散转(JMPA+DPTR ) 它是根据某种已输入的“或”运算的结果,使程序转向各个处理程序中去。 操作:把16位DPTR的内容与“或”运算的结果与在A中的8位无符号数相加,形成地址,装入PC,即散转的目的地址。其操作结果不影响A和DPTR。(JMP)4.3 分支结构程序二、无条件/条件转移程序 分

22、支程序中最常见的一类。其中,条件转移类程序编写较容易出错,编写时需要确定转移条件。 例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 ;两数

23、比较 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

24、程序流程图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,L14.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 M

25、OV R0,A SJMP L4 L2:MOV A,R1CLR CSUBB A,#01 ;X10,Y=X2-14.3 分支结构程序 MOV R0,A L4:MOV 5BH,R0 ;存结果 SJMP $ END 由于本题的具体情况,在判别(A)10和(A)15时采用的是“CJNE”和“JC”以及“CJNE”和“JNC”两条指令相结合的方法。 条件分支程序与简单程序的区别在于:分支程序存在两个或两个以上的结果。要根据给定的条件进行判断,以得到某一个结果。这样,就要用到比较命令、测试指令以及无条件/条件转移指令。条件分支程序设计 的技巧,就在于正确而巧妙地使用这些命令。 4.3 分支结构程序例题:求符

26、号函数的值。已知片内RAM的40H单元内有一自变量X,编制程序按如下条件求函数Y的值,并将其存入片内RAM的41H单元中。 1 X0Y= 0 X=0 -1X255,因此单重循环程序无法实现,可采用双重循环的方法编写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 ;(R

27、7)1=0,则顺序执行,否则转回DLY1继续循环,延时时间为(246211)20021=50.003ms RET ; 子程序结束 END4.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

28、MOV A,20H SWAP A;变换BCD数的高低位 ANL A,#0FH;把BCD数的高位分离出来 MOV R1,A CLR A;清A4.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

29、,11。 分析: 依次将相邻两个单元的内容进行比较。即第一个数与第二个数进行比较,第二个数与第三个数进行比较,依此进行,如符合由小到大的顺序,则不改变它们在内存中的位置,否则交换它们之间的位置。如此反复比较,直到数列排完为止。 4.4 循环结构程序 由于在比较过程中,小数向上冒,因此这种排序程序称为“冒泡程序”,比较过程如下: 4.4 循环结构程序 第一轮经过6次两两比较,得到一个最大数;第二轮经过5次两两比较,得到一个次大数; 依此类推。每轮比较后得到本轮最大数,该数就不再参与下一轮的比较,故每轮比较次数减1。为加快排序速度,程序中设置一个标志位,只要在比较过程中两数之间没有发生过交换,就表

30、示数列已按由小到大的顺序排列好了,就可以结束比较。 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

31、 INC R0 CLR C SUBB A,R0 ;两数比较 JC LESS ;XiXi+1转LESS4.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:RET4.4 循环结构程序 LOOP3:DJNZ R1,LOOP1 ;发生交换转移 SJMP STOP END 练习题:200名学生参加考试,成绩放在80C51的外部RAM的一

32、个连续存储单元,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

33、,#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 $ END4.5 子程序结构4.5 子程序结构一、概念子程序:完成确定任务,并能为其他程序反复调用的程序段。 要求子程序在结构上具有通用性和独立性。例如:代码转换,运算程序,任意数的平方等。 子程序的调用与返回: 主程序调用子程序的过程:在主程序中需要执行这种操作的地方执行一条调用指令(LCALL或A

34、CALL),转到子程序,而完成规定的操作后,再在子程序最后应用RET返回指令返回到主程序断点处,继续执行下去。4.5 子程序结构子程序的调用子程序的入口地址:子程序的第一条指令地址,常用标号表示。程序的调用过程:单片机收到ACALL或LCALL指令后,首先将当前的PC值(调用指令的下一条指令的首地址)压入堆栈保存(低8位先进栈,高8位后进栈),然后将子程序的入口地址送入PC,转去执行子程序。子程序的返回主程序的断点地址:子程序执行完毕后,返回主程序的地址,它在堆栈中保存。子程序的返回过程:子程序执行到RET指令后,将压入堆栈的断点地址弹回给PC(先弹回PC的高8位,后弹回PC的低8位),使程序

35、回到原先被中断的主程序地址(断点地址)去继续执行。4.5 子程序结构注意:中断服务程序是一种特殊的子程序,它是在计算机响应中断时,由硬件完成调用而进入相应的中断服务程序。RETI指令与RET指令相似,区别在于RET是从子程序返回,RETI是从中断服务程序返回。 子程序优点: 简化了程序的逻辑结构;提高编程效率,便于调试;节省存储器的空间。4.5 子程序结构与子程序调用有关的指令: 两条调用子程序指令:ACALL addr11;LCALL addr16一条返回主程序指令:RET二、子程序设计要点 1、第一条语句前必须有标号。 2、子程序最后应以返回指令(RET)结尾。 3、在主程序中设置堆栈。凡

36、有子程序的程序,主程序初始化一定要设置栈底和栈区,以免造成混乱和错误。因调用子程序时,主程序的断点将自动入栈,转入子程序后,现场的保护都要占用堆栈工作单元。4.5 子程序结构 4、保护和恢复现场 在转入子程序时,特别是进入中断服务子程序时,要特别注意保护现场的问题。主程序使用的A、DPTR、PWS、R0R7等,不应因转入子程序而改变。若两者使用的寄存器有冲突,则必须在转入子程序后首先保护现场,即把要保护的单元压堆栈;返回主程序前恢复现场,即出栈。4.5 子程序结构 5、参数传递 指调用子程序时,主程序应把有关的参数(入口参数)存放在约定的位置,子程序在执行时,可以从约定的位置取得参数,当子程序

37、执行完,将得到的结果(出口参数)存入约定的位置,返回主程序后,主程序可以从这些约定的位置上取得需要的结果。4.5 子程序结构几种参数传递方法: 用A或寄存器传递;(如:例4.15) 用地址指针寄存器(R0、R1、DPTR)传递;(如:例4.16) 用堆栈传递参数。(如:例4.17)三、子程序的嵌套 在实际应用中,子程序中调用子程序的情况。4.5 子程序结构四、举例例4.15 设a、b、c分别存放在内部RAM的40H、41H、42H单元中,a、b均小于10。试编程计算: 分析:用子程序来实现某数的平方,即通过调用子程序查平方表,结果在主程序中得到。4.5 子程序结构 图4-10 程序框图 4.5

38、 子程序结构 主程序: MAIN: MOV A,40H ACALL SQR ;调查表子程序MOV R1,A ;a2暂存R1中MOV A,41H ACALL SQR ;调查表子程序ADD A,R1MOV 42H,ASJMP $ ;等待4.5 子程序结构 子程序: SQR: INC A MOVC A,A+PC ;查平方表 RET ;单字节 TAB: DB 0,1,4,9,16 DB 25,36,49,64,81 该程序中子程序的入口条件(A)=待查表的数,出口条件(A)=待查表数的平方。4.5 子程序结构例4.16 求两个无符号数据块中的最大值。数据块的首地址分别为60H和70H,每个数据块的第一

39、个字节都存放数据块长度。结果存入5FH单元。 分析:可采用分别求出两个数据块的最大值,然后比较其大小的方法。求最大值的过程可采用子程序。子程序的入口条件是数据块首地址,返回参数即为最大值,放在A中。4.5 子程序结构 解:主程序:ORG 2000HMOV R1,#60H ;置入口条件参数ACALL QMAX ;调用求最大值子程序MOV 40H,A ;第一个数据块的最大值暂存40H MOV R1,#70H ;置入口条件参数ACALL QMAX ;调求最大值子程序CJNE A,40H,NEXT ;两个最大值进行比较NEXT:JNC LP ;A大则转LP MOV A,40H ;A小则把40H单元中的

40、内容送入A LP: MOV 5FH,A;把两个数据块的最大值送入5FH SJMP $4.5 子程序结构子程序: ORG 2200HQMAX:MOV A,R1 ;取数据块长度MOV R2,A ;设置计数值CLR A ;设0为最大值,最大值放入A中 LP1:INC R1 ;修改地址指针 CLR C SUBB A,R1 ;两数相减 JNC LP3 ;原数仍为最大值,转LP3 MOV A,R1 ;否,用此数代替最大值 SJMP LP4 ;无条件转LP4 LP3: ADD A,R1 ;恢复原最大值 LP4: DJNZ R2,LP1 ;若没比较完,继续比较 RET ;比较完,返回 4.5 子程序结构例4.

41、17 在50H单元中存放着两个十六进制数字,编程使它们分别转换成ASC码,并存入51H和52H单元。 解:十六进制数转换成ASC码的过程可采用子程序。这里采用堆栈来传递参数。 主程序:ORG 2000HMOV SP,#3FH;设堆栈指针PUSH 50H ;把50H单元内的数压入堆栈ACALL HASC ;调子程序,并把主程序的断点地址高、低位(PCH、PCL)分别压入41H、42H单元 POP 51H ;把已转换的低半字节的ASC码弹入51H单元接下页4.5 子程序结构MOV A,50H SWAP A ;准备处理高半字节的十六进制数 PUSH A ACALL HASC POP 52H ;把已转

42、换的高半字节的ASC码弹入52H单元 SJMP $接下页4.5 子程序结构子程序: ORG 3000H HASC:DEC SP DEC SP ;两次执行“DEC SP”,把堆栈指针修正到40H POP A ;把40H中的原50H单元内的数据弹入到A中 ANL A,#0FH ;屏蔽高4位 ADD A,#07 ;修正查表位置 MOVC A,APC ;取表中数至A PUSH A ;将已转换的ASC码值压入堆栈的40H单元,2字节指令 INC SP ;修改SP指针到断点位置, 2字节指令 INC SP ;两次执行“INC SP”,SP变为42H, 2字节指令 RET ;把原断点内容又送回PC,SP又指

43、向40H 1字节指令 TAB:DB 0,1,2,3,4,5,6,7 DB 8,9,A,B,C,D,E,F 4.5 子程序结构 图4-11 堆栈操作示意图 4.5 子程序结构说明:本题也可以不采用堆栈传递参数的办法,此时可以用ACC既作为入口条件,也作为出口条件来传递参数。在主程序中把“PUSH 50H”改为“MOV A,50H”;把“POP 51H”改为“MOV 51H,A”;依次类推。在子程序中把6条有关堆栈的操作指令都去掉;再把“ADD A,#07”改为“ADD A,#01”即可。4.5 子程序结构练习题1: M1和M1+1单元存有16位二进制数,试编程将其扩大二倍。 参考答案: CLR

44、C MOV R1,#M1 MOV A,R1 RLC A MOV R1,A INC R1 MOV A,R1 RLC A MOV R1,ASJMP $4.5 子程序结构 练习题2:将内部ROM的60H、61H单元中的连续存放着4位BCD码。试编写一段程序将这4位BCD码倒序排列。 参考答案: MOV R0,#60H MOV R1,#61H MOV A,R0 SWAP A XCH A,R1 SWAP A MOV R0,A4.5 子程序结构 练习题3:已知外部RAM的3000H开始放一数据区,缓冲区中以回车符0DH结束。 编程:将正数送入片内RAM以30H开始的正数区,将负数放入以40H开始的负数区。

45、 参考答案: 4.5 子程序结构 解法一: MOV R0,#30HMOV R1,#40HMOV DPTR,#3000HNEXT: MOVX A, DPTRMOV 10H,ACJNE A,#0DH,END1;#0DH与A中内容不相等转至END1处,(A)0DH,C=0;(A)0DH,C=1SJMP OVER ;相对转移到OVER处4.5 子程序结构 END1: ANL A,#10000000B;判断正负数JZ ZH;(A)=0,转移到ZH处SJMP NEG ZH: MOV R0,10H;存放正数程序段INC R0INC DPTRSJMP NEXT NEG: MOV R1,10H;存放负数程序段

46、INC R1 INC DPTR SJMP NEXTOVER: RET 4.5 子程序结构解法二: MOV R0,#30HMOV R1,#40HMOV DPTR,#3000H NEXT: MOVX A, DPTRCJNE A,#0DH,COMPSJMP OVER COMP: JB ACC.7,LOOP;ACC.7=1程序转移到LOOPMOV R0,A;存放正数程序段INC R0INC DPTR4.5 子程序结构 SJMP NEXTLOOP: MOV R1,A;存放负数程序段INC R1INC DPTRSJMP NEXTOVER: RET 4.6 综合程序举例4.6 综合程序举例一、查表程序 1、

47、查表程序 查表:根据变量x在表格中查找y,使y=f(x)。函数值y事先根据变量x的取值范围计算出,并按一定规律编成表格存放在计算机的ROM中。当用户程序中需要用这些数据时,直接按编排的索引值(或程序号)寻找答案。 主要用于: LED显示器控制、智能化仪表控制、打印机的打印以及数据计算、复杂函数计算:Y=SIN(X); 数据补偿:传感器补偿、复杂代码转换显示等功能程序中。4.6 综合程序举例 在51中有两条查表指令: MOVC A,A+DPTR;MOVC A,A+PC1.采用MOVC A, A+DPTR指令查表程序的设计方法在ROM中建立相应的函数表(设自变量为X)。计算出这个表中所有的函数值Y

48、。将这群函数值按顺序存放在起始(基)地址为TABLE的ROM中。将表格首地址TABLE送入DPTR,X送入A,采用查表指令MOVC A, A+DPTR完成查表,就可以得到与X相对应的Y值于A中。4.6 综合程序举例2.采用MOVC A, A+PC指令查表程序的设计方法 当使用PC作为基址寄存器时,由于PC本身是一个程序计数器,与指令的存放地址有关,查表时其操作有所不同。在ROM中建立相应的函数表(设自变量为X)。计算出这个表中所有的函数值Y。将这群函数值按顺序存放在起始(基)地址为TABLE的ROM中。X送入A,使用ADD A, #data指令对A的内容进行修正,偏移量data由公式data=

49、函数数据表首地址PC1确定,即data值等于查表指令和函数表之间的字节数。采用查表指令MOVC A, A+PC完成查表。 4.6 综合程序举例例题利用查表的方法编写Y=X2(X=0, 1, 2, 9)的程序解:设变量X的值存放在内存30H单元中,求得的Y的值存放在内存31H单元中。平方表存放在首地址为TABLE的ROM中。方法一:采用MOVC A, A+DPTR指令实现,查表过程如下图所示。程序如下: ORG 1000H START: MOV A, 30H ; 将查表的变量X送入A MOV DPTR, #TABLE ; 将查表的16位基地址TABLE送DPTR MOVC A, A+DPTR ;

50、 将查表结果Y送A MOV 31H, A ; Y值最后放入31H中 TABLE: DB 0, 1, 4, 9, 16 DB 25, 36, 49, 64, 81 END方法二:采用MOVC A, A+PC指令实现,查表过程如下页图所示。程序如下: ORG 1000H START: MOV A, 30H ; 将查表的变量X送入A ADD A, #02H ; 定位修正 MOVC A, A+PC ; 将查表结果Y送A MOV 31H, A ; Y值最后放入31H中 TABLE: DB 0, 1, 4, 9, 16 DB 25, 36, 49, 64, 81 END 4.6 综合程序举例2、查表程序优

51、点 程序简单、执行速度快。3、查表程序有多种结构形式,下面介绍两种常用查表程序。 例4.18 设计一个将16进制数转换成ASC码的子程序。设16进制数存放在R0中的低4位,要求将转换后的ASC码送回R0中。 解:已知09的ASC码为30H39H,AF的ASC码为41H46H。按题意程序的入口和出口都在R0中,表中所有的值都是单字节,表格长度为16个字节(0F)。4.6 综合程序举例参考程序: ORG 2160H MOV A,R0 ANL A,#0FH ;保留低4位 ADD A,#02H ;变址调整,因为“MOVC A,A+PC”指令与表格首址相隔两个字节,故变址调整值为2 MOVC A,A+P

52、C ;查表得ASC值 MOV R0,A RET4.6 综合程序举例 TAB:DB 30H,31H,32H DB 33H,34H,35H DB 36H,37H,38H DB 39H,41H,42H DB 43H,44H,45H,46H 4.6 综合程序举例 例4.19 某智能化仪器的键盘程序中,根据命令的键值(0,1,2,9),转换成相应的双字节16位命令操作地址,其键入值与对应入口关系如下: 设键值存放在20H单元中,出口地址值存放在22H,23H单元中。参考程序: ORG 2200H MOV DPTR,#TAB ;指向表首高8位 MOV A,20H ;取键值 键值 0 12 3 456789

53、入口地址01230186023403160415052006260710081809294.6 综合程序举例 RL A ;因函数值y为双字节,所以把键值乘2作查表偏移量 MOV 20H,A ;暂存偏移量 MOVC A,A+DPTR ;取高8位地址 MOV 22H,A ;暂存高8位地址 INC DPTR ;指向表首低8位 MOV A,20H ;取偏移量 MOVC A,A+DPTR ;取低8位地址 MOV 23H,A ;暂存低8位地址 RET TAB: DB 01,23H ;“0”键入口地址 DB 01,86H ;“1”键入口地址 4.6 综合程序举例 DB 02,34H ;“2”键入口地址 DB

54、 03,16H ;“3”键入口地址 DB 04,15H ;“4”键入口地址 DB 05,20H ;“5”键入口地址 DB 06,26H ;“6”键入口地址 DB 07,10H ;“7”键入口地址 DB 08,18H ;“8”键入口地址 DB 09,29H ;“9”键入口地址 4.6 综合程序举例二、代码转换程序 例4.20 将A中00FF范围内二进制数转换为BCD码(0255)。分析:BCD码是四位二进制数表示的十进制数。它在单片机中有两种存放形式: 一种是一个字节放一位BCD码,高半字节取0,适用于显示和输出; 另一种是一个字节存放两位BCD码,即压缩BCD码,有利于节省存储空间。本题所转换

55、的最大BCD数是255,超过了一个字节,因而把十位、个位以压缩BCD码的形式存放,把百位单独存放。 .4.6 综合程序举例 编程思路:将A中十进制数除以100、10,所得商即为百、十位数,余数为个位数。结果存放在R0内容为初始地址的单元中。参考程序: MOV B,#100 DIV AB ;A中为百位数,B内为余数 MOV R0,A ;存入RAM单元 INC R0 ;修改地址指针 MOV A,#10 XCH A,B DIV AB ;A中为十位数,B中为个位数 SWAP A ;十位数移到高半字节 ADD A,B ;形成十位和个位数的压缩BCD码 MOV R0,A ;存入RAM单元 RET4.6 综

56、合程序举例*例4.21 编写多字节二进制数转换为BCD码的程序。分析:若本例采用上例算法,需进行多字节除法运算,运算速度慢,且程序通用性差。本程序采用图4-12所示流程图的算法编制。(a15a14a1a0)=( (02+a15)2+a14)2+a0,所以将二进制数从最高位逐次向左移入BCD码的最低位,并且每次都实现()*2+ai的运算。 编程时应注意两点: (1)BCD码数乘2不能用左移指令,只能用ADDC指令对BCD数自身相加一次且要用十进制调整指令;4.6 综合程序举例 (2)二进制数转换后的压缩BCD码可能要比原来二进制数多占一个字节单元。 入口:(BIND)= 二进制数低位字节地址指针

57、; (BCDD)= BCD数个位数地址指针; (BYTES)= 二进制数字节数。 出口:(BCDD)= BCD数个位数地址指针。4.6 综合程序举例 图4-12 二进制数转换为BCD码程序流程图 4.6 综合程序举例 参考程序: ORG 2000H MOV R1,BCDD ;取BCD码数个位地址 MOV R2,BYTES ;取二进制数字节数 INC R2 CLR A BB0:MOV R1,A ;清BCD单元 INC R1 DJNZ R2,BB0 4.6 综合程序举例 MOV A,BYTES MOV B,#08H MUL AB MOV R3,A ;存放二进制数位数 BB3: MOV R0,BIN

58、D ;取二进制数位数低位地址 MOV R2,BYTES ;取二进制数字节数 CLR C BB1: MOV A,R0 4.6 综合程序举例 RLC A MOV R0,A INC R0 DJNZ R2,BB1 ;二进制数左移 MOV R2,BYTES INC R2 MOV R1,BCDD BB2: MOV A,R1 4.6 综合程序举例 ADDC A,R1 ;BCD码乘2 DA A ;十进制调整 MOV R1,A INC R1 DJNZ R2,BB2 DJNZ R3,BB3 ;反复循环 RET 4.6 综合程序举例例4.22 把A中的压缩BCD码转换成二进制数。 解: MOV R2,A ;暂存 A

59、NL A,#0F0H ;屏蔽低4位 SWAP A ;高、低4位交换 MOV B,#10 MUL AB ;乘法运算,A中高半字节乘10 MOV R3,A ;暂存 MOV A,R2 ;取原数 ANL A,#0FH ;取BCD个位 ADD A,R3 ;个位与十位数相加 RET4.6 综合程序举例 例4.23 将R0所指出单元中的ASC码转换成十六进制数,并把结果存放于原单元。 分析: 对于不大于9的数,ASC代码减去30H; 对于大于9的数,ASC代码减去37H,即得转换后的十六进制数。4.6 综合程序举例参考程序: MOV A,R0 ;取操作数 CLR C SUBB A,#30H ;09的转换 M

60、OV R0,A ;暂存结果 SUBB A,#0AH ;结果是否大于9 JC SB2 ;不大于9则返回 XCH A,R0 SUBB A,#07H ;大于9,则减37H MOV R0,A ;存结果 SB2: RET4.6 综合程序举例*例4.24 将R2中两位16进制数转换成七段代码,并存入R2R3中。 解:七段代码是用七段发光二极管显示一个数,该数对应的代码为七段代码。 图4-13在七段代码显示器共阳极接法中,相应段加上“0”电平时,该段亮。 由七段代码表4-1可以看出,七段代码和数字之间没有什么规律,所以适合用查表的方法进行转换。先把七段代码按0F的顺序存入存储器,表首地址TABS。利用代码首

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论