收藏 分销(赏)

汇编语言及C语言程序设计.pptx

上传人:精*** 文档编号:4224507 上传时间:2024-08-26 格式:PPTX 页数:88 大小:695.49KB
下载 相关 举报
汇编语言及C语言程序设计.pptx_第1页
第1页 / 共88页
汇编语言及C语言程序设计.pptx_第2页
第2页 / 共88页
汇编语言及C语言程序设计.pptx_第3页
第3页 / 共88页
汇编语言及C语言程序设计.pptx_第4页
第4页 / 共88页
汇编语言及C语言程序设计.pptx_第5页
第5页 / 共88页
点击查看更多>>
资源描述

1、单片机技术第第4章章 汇编语言及汇编语言及C语言程序设计语言程序设计4.1 4.1 程序设计概述程序设计概述4.2 4.2 汇编语言源程序的编辑和汇编汇编语言源程序的编辑和汇编4.3 4.3 汇编语言程序设计汇编语言程序设计4.4 C514.4 C51基本语法基本语法4.5 C514.5 C51与汇编的结合与汇编的结合单片机技术411 程序设计语言简介程序设计语言简介1 机器语言机器语言 v机器语言机器语言就是用二进制(可缩写为十六进制)代码来表示指令和数据。也称为机器代码、指令代码。机器语言是计算机唯一能识别和执行的语言,用其编写的程序执行效率最高,速度最快,但由于指令的二进制代码很难记忆和

2、辨认,给程序的编写、阅读和修改带来很多困难。所以,没有人使用机器语言来编写程序。v2 汇编语言汇编语言 v用助记符表示的指令就是计算机的汇编语言汇编语言,汇编语言与机器语言一一对应。用汇编语言编写程序,每条指令的意义一目了然,给程序的编写、阅读和修改带来很大方便。而且用汇编语言编写的程序占用内存少,执行速度快,尤其适用于实时应用场合的程序设计。因此,在单片机应用系统中主要是用汇编语言来编写程序。41 程序设计概述程序设计概述单片机技术v汇编语言也有它的缺点:缺乏通用性,程序不易移植,是一种面向机器的低级语言。即使用汇编语言编写程序时,仍必须熟悉机器的指令系统、寻址方式、寄存器的设置和使用方法。

3、每个计算机系统都有它自己的汇编语言。不同计算机的汇编语言之间不能通用。v3 3 高级语言高级语言 v高级语言高级语言是一种面向算法、过程和对象的程序设计语言,它采用接近人们自然语言和习惯的数学表达式及直接命令的方法来描述算法、过程和对象,如BASIC、C语言等。高级语言的语句直观,易学,通用性强,便于推广、交流,但高级语言编写的程序经编译后所产生的目标程序大,占用内存多,运行速度较慢,这在实时应用中是一个突出的问题。单片机技术v412 汇编语言程序设计步骤汇编语言程序设计步骤使用汇编语言设计程序大致上可分为以下几个步骤:(1)分析题意,明确要求。解决问题之前,首先要明确所要解决的问题和要达到的

4、目的、技术指标等;(2)确定算法。根据实际问题的要求、给出的条件及特点,找出规律性,最后确定所采用的计算公式和计算方法,这就是一般所说的算法。算法是进行程序设计的依据,它决定了程序的正确性和程序的指令。(3)画程序流程图,用图解来描述和说明解题步骤。程序流程图是程序设计的依据,它直观清晰的体现了程序的设计思路。流程图是用预先约定的各种图形、流程线及必要的文字符号构成的。标准的流程图符号如图4-1所示。单片机技术(4)分配内存工作单元,确定程序与数据的存放地址。(5)编写源程序。流程图设计后,程序设计思路就比较清楚了,接下来的任务就是选用合适的汇编语言指令来实现流程图中每一框内的要求,从而编制出

5、一个有序的指令流,这就是源程序设计。(6)程序优化。程序优化的目的在于缩短程序的长度,加快运算速度和节省存储单元。如恰当的使用循环程序和子程序结构,通过改进算法和正确使用指令来节省工作单元及减少程序执行的时间。(7)上机调试、修改、最后确定源程序。只有通过上机调试并得出正确结果的程序,才能认为是正确的程序。对于单片机来说,没有自开发的功能,需要使用仿真器或利用仿真软件进行仿真调试,修改源程序中的错误,直至正确为止。单片机技术v421 伪指令伪指令v指令能使CPU执行某种操作,能生成对应的机器代码。v伪指令不能命令伪指令不能命令CPU执行某种操作,也没有对应的机器执行某种操作,也没有对应的机器代

6、码。它的作用仅用来给汇编程序提供某种信息。代码。它的作用仅用来给汇编程序提供某种信息。v常用的伪指令如下:v1汇编起始伪指令汇编起始伪指令 ORGv格式:标号:ORG 16位地址v功能:规定程序块或数据块存放的起始地址规定程序块或数据块存放的起始地址。如:v ORG 8000H START:MOV A,#30H v该伪指令规定第一条指令从地址8000H单元开始存放,即标号START的值为8000H。42 汇编语言源程序的编辑和汇编汇编语言源程序的编辑和汇编单片机技术2汇编结束伪指令汇编结束伪指令 END格式:标号:END 表达式功能:结束汇编结束汇编。汇编程序遇到END伪指令后即结束汇编。3定

7、义字节数据伪指令定义字节数据伪指令 DB格式:标号:DB 8位字节数据表功能:从标号指定的地址单元开始,将数据表中的字节数从标号指定的地址单元开始,将数据表中的字节数据按顺序依次存入据按顺序依次存入。数据表可以是一个或多个字节数据、字符串或表达式,各项数据用“,”分隔,一个数据项占一个字节单元。例如 ORG 1000HTAB:DB -2,-4,100,30H,A,C汇编后:(1000H)=FEH,(1001H)=FCH,(1002H)=64H,(1003H)=30H,(1004H)=41H,(1005H)=43H用单引号括起来的字符存其ASC码,负数存其补码。单片机技术v4定义字数据伪指令定义

8、字数据伪指令 DWv格式:标号:DW 16位字数据表v功能:从标号指定的地址单元开始,将数据表中的字从标号指定的地址单元开始,将数据表中的字数据按从左到右的顺序依次存入数据按从左到右的顺序依次存入。v应注意:16位数据存入时,先存高8位,后存低8位。ORG 1400HDATA:DW 324AH,3CHv 汇编后:(1400H)=32H,(1401H)=4AH,(1402H)=00H,(1403H)=3CHv5定义空间伪指令定义空间伪指令 DSv格式:标号:DS 表达式v功能:从标号指定的地址单元开始,保留若干个存储从标号指定的地址单元开始,保留若干个存储单元作为备用的空间。保留的数量由表达式指

9、定单元作为备用的空间。保留的数量由表达式指定。单片机技术例如 ORG 3000HBUF:DS 05Hv v汇编后,从地址3000H开始保留5个存储单元作为备用。v应注意应注意:DB、DW、DS伪指令只能对程序存储器进行定义,不能对数据存储器进行定义;DB伪指令常用来定义数据,DW伪指令常用来定义地址。6赋值伪指令赋值伪指令EQU(或(或=)v格式:符号名 EQU 表达式 或 符号名=表达式v功能:将表达式的值定义为一个指定的符号名将表达式的值定义为一个指定的符号名。v应注意:用EQU定义的符号不允许重复定义,用“=”定义的符号允许重复定义。单片机技术43 汇编语言程序设计汇编语言程序设计v4.

10、3.1 4.3.1 顺序程序设计顺序程序设计v4.3.2 4.3.2 分支程序设计分支程序设计v4.3.3 4.3.3 循环程序设计循环程序设计v4.3.4 4.3.4 子程序设计子程序设计v4.3.5 4.3.5 运算类程序设计运算类程序设计汇编语言程序共有四种结构形式,即:顺序结构、分支结构、循环结构和子程序结构。单片机技术n431 顺序程序设计顺序程序设计n 顺序结构程序是一种最简单、最基本的程序(也称为简单程序),它是一种无分支的直线型程序,按照程序编写的顺序依次执行。编写这类程序主要应注意正确地选择指令,提高程序的执行效率。n例例4-1 编写16位二进制数求补程序。设16位二进制数存

11、放在R1R0中,求补以后的结果则存放于R3R2中。n解:二进制数的求补可归结为求补可归结为“求反加求反加1”的过程的过程。求反可用CPL指令实现;加1时应注意,加1只能加在低8位的最低位上。因为现在是16位数,有两个字节,因此要考虑进位问题,即低8位取反加1,高8位取反后应加上低8位加1时可能产生的进位。单片机技术vORG 0200H MOV A,R0 ;低8位送A CPL A ;取反 ADD A,#01H ;加1 MOV R2,A ;存结果 MOV A,R1 ;高8位送A CPL A ;取反 ADDC A,#00H ;加进位 MOV R3,A ;存结果 END单片机技术v例例4-2 编程将2

12、0H单元中的8位无符号二进制数转换成三位BCD码,并存放在22H(百位)和21H(十位,个位)两个单元中。v解:因8位二进制数对应的十进制数为0255,所以先将原数除以将原数除以100,商就是百位数的,商就是百位数的BCD码码,余数作为被除数再除以10,商为十位数的BCD码,最后的余数就是个位数的BCD码,将十位、个位的BCD码合并到一个字节中,将结果存入即可。ORG 1000H MOV A,20H ;取数送A MOV B,#64H ;除数100送B中 DIV AB ;商(百位数BCD码)在A中,余数在B中 MOV 22H,A ;百位数送22H MOV A,B ;余数送A作被除数单片机技术 M

13、OV B,#0AH ;除数10送B中 DIV AB ;十位数BCD码在A中,个位数在B中 SWAP A ;十位数BCD码移至高4位 ORL A,B ;并入个位数的BCD码 MOV 21H,A ;十位、个位BCD码存入21H ENDv432 分支程序设计分支程序设计v在很多实际问题中,都需要根据不同的情况进行不同的处理。这种思想体现在程序设计中,就是根据不同条件而转到不同的程序段去执行,这就构成了分支程序。分支程序的结构有两种,如图4-2所示。单片机技术图(a)结构是用条件转移指令来实现分支。当给出的条件成立时,执行程序段A,否则执行程序段B。图(b)结构是用散转指令JMP来实现多分支转移。它首

14、先将分支程序按序号排列,然后按照序号的值来实现多分支转移。单片机技术v例例4-3 设变量X存放在30H单元,函数值Y存入31H单元。试编程,按照下式的要求给Y赋值。v Y=v解:X是有符号数,因此可以根据它的符号位来根据它的符号位来决定其正负,决定其正负,判别符号位是0还是1可利用JB或JNB指令。而判别X是否等于0则可以直接使用累加器判零JZ指令。把这两种指令结合使用就可以完成本题的要求。程序流程图如图4-3所示。单片机技术 ORG 1000H MOV A,30H ;取数X送A JZ COMP ;X=0,则转 COMP JNB ACC.7,POSI ;X0,则转POSI MOV A,#0FF

15、H ;X0,则Y=1COMP:MOV 31H,A ;存函数值 END单片机技术v例例4-4 设5AH单元中有一整数X,请编写计算下述函数式的程序,结果存入5BH单元。Y=v解:根据题意首先计算X2 ,并暂存于R1中,因为X2最大值为225,故只用一个寄存器,然后根据X值的范围,决定Y的值。在判断A15时,采用CJNE、JC指令相结合以及CJNE、JNC指令相结合的方法进行判断。程序流程图如图4-4所示。R0用做中间寄存器。单片机技术v 源程序如下:ORG 2000H MOV A,5AH ;取数X送A MOV B,A ;X送B MUL AB ;计算X2 MOV R1,A ;X2暂存R1中 MOV

16、 A,5AH ;重新把X装入A CJNE A,#0AH,L1;X与10比较L1:JC L2 ;若X15,41作为函数值送R0 CJNE A,#10H,L3;X与16比较 L3:JNC L4 ;若X16,转L4单片机技术 MOV A,R1 ;10X15,取X2送A中 ADD A,#08 ;计算X2+8 MOV R0,A ;函数值送R0 SJMP L4 ;转L4L2:MOV A,R1 ;取X2送A中 CLR C ;清CY,为减法作准备 SUBB A,#01H ;计算X2-1 MOV R0,A ;函数值送R0L4:MOV 5BH,R0 ;函数值存入指定单元 SJMP$ENDv散转程序:就是用散转指令

17、散转程序:就是用散转指令“JMP JMP A+DPTRA+DPTR”来实现多分支程序的转移。来实现多分支程序的转移。单片机技术利用JMP指令实现多分支转移时,首先应在应在ROM中建立中建立一个散转表,表中可以存放一个散转表,表中可以存放无条件转移指令无条件转移指令、地址偏地址偏移量移量或各分支入口地址或各分支入口地址。表中存放的内容不同,所编写的散转程序也就不同。v在编写散转程序时,一般是将散转表的首地址送在编写散转程序时,一般是将散转表的首地址送DPTR,分支序号送,分支序号送A,根据序号查找相应的转移指令,根据序号查找相应的转移指令或入口地址,从而实现多分支的转移或入口地址,从而实现多分支

18、的转移。假设各分支入口地址:假设各分支入口地址:OPR0:操作程序0 OPR1:操作程序1 OPR2:操作程序2 OPR3:操作程序3 OPRn:操作程序n单片机技术 对这种情况,可以先用无条件转移指令(如AJMP)按顺序组成一个转移表,将转移表首地址装到数据指针DPTR中,将分支序号装入A,执行“JMP A+DPTR”指令进入转移表后,再由“AJMP”指令转入对应程序段的入口。从而实现散转。v(1)采用转移指令组成表 在许多实际应用中,往往要根据某标志单元的内容(键盘输入或运算结果)是0,1,2,n,分别转向操作程序0,操作程序1,操作程序2,操作程序n。v例例4-5 试编程根据R7的内容,

19、转向相应的操作程序段。若 R7=0,转入OPR0段 R7=1,转入OPR1段 R7=n,转入OPRn段单片机技术 编写散转程序如下:JUMP1:MOV DPTR,#TAB1;送转移表首地址 MOV A,R7 ;序号送A ADD A,R7 ;序号2A(因AJMP指 令占2个字节,修正变址值)NOAD:JMP A+DPTR ;转入转移表内TAB1:AJMP OPR0 ;转移指令组成转移表 AJMP OPR1 AJMP OPRn 此段散转程序适用n127单片机技术v(2)采用地址偏移量组成表v当分支序号较少,各段程序较短,所有分支程序均处在256字节之内时,可使用地址偏移量组成表使用地址偏移量组成表

20、。v例例4-6 编程根据R7的内容,转向相应的操作程序。v 设(R7)=04编程如下:JUMP2:MOV DPTR,#TAB2 ;送表首地址 MOV A,R7 ;分支序号送A MOVC A,A+DPTR ;根据序号查表,取地址偏移量送A JMP A+DPTR ;表首地址地址偏移量形成目标地址 TAB2:DB OPR0-TAB2 ;分支入口地址与表首的DB OPR1-TAB2 偏移量定义到表中 DB OPR2-TAB2 DB OPR3-TAB2 DB OPR4-TAB2单片机技术v(3)采用各分支入口地址组成表v若需要转向较大的范围若需要转向较大的范围,可以建立一个转移地址表,即将所要转移的各分

21、支入口地址(即将所要转移的各分支入口地址(16位地址),组成位地址),组成一个表一个表。在散转之前,先用查表方法获得表中的转移地址,然后将该地址装入DPTR,最后按DPTR中的内容进行散转。v例例4-7 试编程根据R7的内容(即分支序号),转向相应的操作程序。设各分支转移入口地址同上,编写散转程序如下:JUMP3:MOV DPTR,#TAB3 ;首地址送DPTR MOV A,R7 ;取分支序号送A ADD A,R7 ;序号2(转移地址占2个字节)DADD:MOV R3,A ;暂存2倍序号(即索引值)MOVC A,A+DPTR ;根据序号查表,取转移地址高8位送A XCH A,R3 ;转移地址高

22、8位与R3互换单片机技术 INC A ;2倍序号加1送A(索引值加1)MOVC A,A+DPTR;查表取转移地址低8位送A MOV DPL,A ;转移地址低8位送DPL MOV DPH,R3 ;转移地址高8位DPH CLR A ;A清0 JMP A+DPTR ;按DPTR中的地址进行转移TAB3:DW OPR0 ;将各分支入口地址定义到表中 DW OPR1 DW OPRnv这种方法可以实现64KB地址空间的转移,分支数最大为128。单片机技术v433 循环程序设计循环程序设计v循环程序:需多次重复执行的某段程序。v循环程序一般由四部分组成:(1)置循环初值。如置循环次数、地址指针及工作单元清0

23、等。(2)循环体。即循环的工作部分,完成主要的计算或操作任务,是重复执行的程序段。这部分程序应特别注意,因为它要重复执行许多次,若能少写一条指令,实际上就是少执行某条指令若干次。因此,应注意优化程序。(3)循环修改。每循环一次,就要修改循环次数、数据及地址指针等。(4)循环控制。根据循环结束条件,判断是否结束循环。循环程序结构有两种,如图4-5所示。单片机技术单片机技术v 图(a)结构是“先执行后判断”,适用于循环次数已知的情况。其特点是一进入循环,先执行循环处理部分,然后根据循环次数判断是否结束循环。v图(b)结构是“先判断后执行”,适用于循环次数未知的情况。其特点是将循环控制部分放在循环的

24、入口处,先根据循环控制条件判断是否结束循环。若不结束,则执行循环操作;若结束,则退出循环。v上述两种结构的程序设计在指令系统中做过介绍,见例3-21和例3-22。v下面通过一些实际的例子,说明如何编制循环程序。单片机技术v例例4-8 编写多字节无符号数加法程序v设有两个多字节无符号数分别存放在内部RAM的DAT1和DAT2开始的区域中,字节个数存放在R2中。求它们的和,并将结果存放在DAT1开始的区域中解:多字节首地址已知,应采用间接寻址方式,多字节的求和,应采用循环程序,流程图如图4-6所示。程序如下:单片机技术 ORG 0200H MOV R0,#DAT1 ;数据块首地址送R0 MOV R

25、1,#DAT2 ;数据块首地址送R1 CLR C ;清进位CY LOOP:MOV A,R0 ;取一个数送A ADDC A,R1 ;两个数相加 MOV R0,A ;存结果 INC R0 ;修改地址指针 INC R1 DJNZ R2,LOOP ;字节数减1,不为0,继续求和 CLR A ;A清0 ADDC A,#00H ;加进位 MOV R0,A ;进位值存到高地址中 END 单片机技术v例例4-9 编写查找最大值程序v设从内部RAM30H单元开始存放着10个无符号数,找出其中的最大值送入内部RAM的MAX单元。v解:寻找最大值的方法很多,最基本的方法是比较最基本的方法是比较和交换依次进行的方法和

26、交换依次进行的方法,即先取第一个数和第二个数比较,并把前一个数作为基准。若比较结果基准数大,则不作交换,再取下一个数来作比较;若比较结果基准数较小,则用较大的数来代替原有的基准数,即做一次交换。然后再以基准数和下一个数作比较。总之,要保持基准数是到目前为止最大的数,比较结束时,基准数就是所求的最大值。v流程图如图4-7所示。程序如下:单片机技术单片机技术 ORG 0200H MOV R0,#30H ;数据区首地址送R0 MOV A,R0 ;取第一个数作基准数送A MOV R7,#09H ;比较次数送计数器R7LP:INC R0 ;修改地址,指向下一地址单元 MOV 30H,R0 ;要比较的数暂

27、存30H中 CJNE A,30H,CHK ;两数作比较CHK:JNC LP1 ;A大,则转移 MOV A,R0 ;A小,则将较大数送ALP1:DJNZ R7,LP ;计数器减1,不为0,继续 MOV MAX,A ;比较完,存结果 END单片机技术v例例4-10 编写数据检索程序v假从内部RAM60H单元开始存放着32个数据,查找是否有“$”符号(其ASCII码为24H),如果找到就将数据序号送入2FH单元,否则将FFH送入2FH单元。v解:数据检索就是在指定数据区中查找关键字。比如在考勤系统中,有时需要查找某个职工上下班情况,或磁卡就餐系统中将某个磁卡挂失或销户等就属于这类问题。v实现数据检索

28、的算法有很多,如顺序检索、对分检索等。对分检索需要先对数据排序;顺序检索是把关键字与数据区中的数据从前向后逐个比较,判断是否相等。v本例采用顺序检索进行编程。流程图如图4-8所示。单片机技术单片机技术 ORG 0300H MOV R0,#60H ;数据区首地址送R0 MOV R7,#20H ;数据长度送计数器R7 MOV 2FH,#00H ;工作单元清0LP:MOV A,R0 ;取数送A CJNE A,#24H,LP1 ;与“$”比较,不等转移 SJMP HERE ;找到,转结束LP1:INC R0 ;修改地址指针 INC 2FH ;序号加1 DJNZ R7,LP ;计数器减1,不为0,继续

29、MOV 2FH,#0FFH;未找到,标志送2FH单元HERE:AJMP HERE;程序结束(序号在2FH单元)END 单片机技术v例例4-11 编写50ms软件延时程序v解:软件延时程序一般都是由软件延时程序一般都是由DJNZ Rn,rel 指令构指令构成成。执行一条执行一条DJNZ指令需要指令需要2个机器周期个机器周期。所以,软件延时时间主要与机器周期和延时程序中的循环次数有关,在使用12MHz晶振时,一个机器周期为1s,执行一条DJNZ指令需要2个机器周期,即2s。延时50ms需用双重循环,源程序如下:DEL:MOV R7,#125 ;执行时需1个机器周期DEL1:MOV R6,#200

30、;DEL2:DJNZ R6,DEL2 ;2002=400s(内循环时间)DJNZ R7,DEL1;0.4ms125=50ms(外循环时间)RET 以上延时时间是粗略的计算,不太精确,它没有考虑到除DJNZ R6,DEL2指令外其它指令的执行时间,如把其它指令的执行时间计算在内,它的延时时间为:(400+1+2)125+1=50.375ms延时时间=(2TMR6+3TM)R7+1TM(2R6R7+3R7)TM 单片机技术v如果应用系统中对延时时间的要求不是十分严格,可按粗略计算的方法进行计算和编程,如果系统要求比较精确的延时,可按如下修改:DEL:MOV R7,#125 ;DEL1:MOV R6

31、,#198 ;NOPDEL2:DJNZ R6,DEL2 ;内循环时间1982+2=398s DJNZ R7,DEL ;外循环时间=(398+2)125+1 =50.001ms RETv上述程序延时时间为50.001ms。v应注意,用软件实现延时的系统,不允许有中断,否则将严重影响定时的准确性。v对于更长时间的延时,可采用更多重的循环,如延时1秒时,可用三重循环。单片机技术v例例4-12 编写无符号数排序程序。v假设在片内RAM中,起始地址为40H的10个单元中存放有10个无符号数。试进行升序排序。v解:数据排序常用方法是冒泡排序法数据排序常用方法是冒泡排序法。这种方法的过程类似水中气泡上浮,故

32、称冒泡法。执行时从前向后进行相邻数的比较,如数据的大小次序与要求的顺序不符就将这两个数互换,否则不互换。对于升序排序,通过这种相邻数的互换,使小数向前移动,大数向后移动。从前向后进行一次冒泡(相邻数的互换),就会把最大的数换到最后。再进行一次冒泡,就会把次大的数排在倒数第二的位置。依此类推,完成由小到大的排序。v流程图如图4-9所示。单片机技术单片机技术v编程中选用R7作比较次数计数器,初始值为09H,位地址00H作为冒泡过程中是否有数据互换的标志位,v若(00H)=0,表明无互换发生,已完成排序。v若(00H)=1,表明有互换发生。ORG 0400HSTART:MOV R0,#40H ;数据

33、区首址送R0 MOV R7,#09H ;各次冒泡比较次数送R7 CLR 00H ;互换标志位清0LOOP:MOV A,R0 ;取前数送A中 MOV 2BH,A ;暂存到2BH单元中 INC R0 ;修改地址指针 MOV 2AH,R0 ;取后数暂存到2AH单元中 CLR C ;清CY SUBB A,R0 ;前数减后数单片机技术 JC NEXT ;前数小于后数,则转(不互换)MOV R0,2BH ;前数大于后数,两数交换 DEC R0 MOV R0,2AH INC R0 ;地址加1,准备下一次比较 SETB 00H ;置互换标志NEXT:DJNZ R7,LOOP ;未比较完,进行下一次比较 JB

34、00H,STAR ;有交换,表示未排完序,进行下一轮冒泡 END单片机技术v434 子程序设计子程序设计v1子程序的结构与设计注意事项子程序的结构与设计注意事项子程序:能够完成一定功能、可以被其他程序调用的程子程序:能够完成一定功能、可以被其他程序调用的程序段。序段。调用子程序的程序称为主程序或调用程序。调用子程序的程序称为主程序或调用程序。子程序结构:与一般程序区别是在子程序末尾有一条子子程序结构:与一般程序区别是在子程序末尾有一条子程序返回指令(程序返回指令(RETRET),子程序开始处有入口地址。),子程序开始处有入口地址。设计设计子程序时注意事项注意事项:(1)要给每个子程序赋一个名字

35、,实际上是子程序入口地址的符号。(2)明确入口条件、出口条件。所谓入口条件,表明子程序需要哪些参数,放在哪个寄存器和哪个内存单元。出口条件则表明子程序处理的结果是如何存放的。单片机技术(3)注意保护现场和恢复现场。在调用子程序之前,某些寄存器中可能存放有主程序的中间结果,这些中间结果在主程序中仍有用,这就要求在子程序使用累加器和这些寄存器之前,要将其内容保护起来,即保护现场。当子程序执行完毕,既将返回主程序之前,再将这些内容取出,送到累加器或原来的寄存器中,这一过程称为恢复现场。一般使用堆栈来保护现场一般使用堆栈来保护现场。当需要保护现场时,要在子程序的开始使用压栈指令PUSH,把需要保护的寄

36、存器内容压入堆栈。在返回指令RET前边再使用弹栈指令POP,把堆栈中保护的内容弹到原来的寄存器,要注意,由于堆栈操作是堆栈操作是“先入后出先入后出”,先压入堆栈的参数应该后弹出,这样才能保证正确恢复原来的数据。单片机技术v2子程序的调用与返回v主程序调用子程序是通过子程序调用指令 LCALL add16和ACALL add11来实现的。v子程序返回是通过返回指令RET实现的。v主程序在调用子程序时要注意以下问题。v(1)在主程序中,要安排相应指令来满足子程序的入口条件,即提供子程序的入口数据。v(2)在主程序中,要安排相应的指令,处理子程序提供的出口数据。v(3)在主程序中,不希望被子程序更改

37、内容的寄存器,也可以在调用前由主程序安排压栈指令来保护现场,然后子程序返回后再安排弹栈指令恢复现场。v(4)在主程序中,要正确地设置堆栈指针。单片机技术3子程序嵌套 子程序嵌套(或称多重转子)是指在子程序执行过程中,还可以调用另一个子程序。子程序嵌套过程见图3-9所示。堆栈在子程序调用中是必不可少的。因为断点地址均是自动存入堆栈区的。单片机技术v例例4-13 用程序实现C=a2+b2。v设a、b 均小于10。a存在31H单元,b存在32H单元,把C存入33H单元。v解:因本题二次用到平方值,所以在程序中采用把求平方编为子程序的方法。v子程序名称:SQR。v功能:求X2(通过查平方表来获得)。v

38、入口参数入口参数:某个数在A中。出口参数出口参数:某数的平方在A中。v主程序是通过两次调用子程序来得到a2和b2,并在主程序中完成相加。依题意编写主程序和子程序如下:主程序:单片机技术 ORG 2200H MOV SP,#3FH;设堆栈指针 MOV A,31H ;取a值 LCALL SQR ;第一次调用,求a2 MOV R1,A ;a2值暂存R1中 MOV A,32H ;取b 值 LCALL SQR ;第二次调用,求b2 ADD A,R1 ;完成a2+b2 MOV 33H,A ;存结果到33H单元 SJMP$;暂停v子程序:ORG 2400HSQR:ADD A,#01H ;查表位置调整 MOV

39、C A,A+PC ;查表取平方值 RET ;子程序返回TAB:DB 0,1,4,9,16,25,36,49,64,81单片机技术v例例4-14 求两个无符号数据块中的最大值。v数据块的首地址分别为60H和70H,每个数据块的第一个字节都存放数据块的长度。结果存入5FH单元。v解:本例可采用分别求出两个数据块的最大值,然后比较其大小的方法。求最大值的过程可采用子程序。v子程序名称:QMAXv子程序入口条件入口条件:R1中存有数据块首地址。v 出口条件出口条件:最大值在A中。v下面分别编写主程序和子程序:ORG 2000H MOV SP,#3FH ;设堆栈指针 MOV R1,#60H;取第一数据块

40、首地址送R1中 ACALL QMAX ;第一次调用求最大值子程序 MOV 40H,A ;第一个数据块的最大值暂存40H MOV R1,#70H;取第二数据块首地址送R1中 ACALL QMAX ;第二次调用求最大值子程序单片机技术 CJNE A,40H,NEXT ;两个最大值进行比较NEXT:JNC LP ;A大,则转LP MOV A,40H ;A小,则把40H中内容送入A LP:MOV 5FH,A ;存最大值到5FH单元 SJMP$子程序:ORG 2200HQMAX:MOV A,R1 ;取数据块长度 MOV R2,A ;R2作计数器 CLR A ;A清0,准备做比较 LP1:INC R1 ;

41、指向下一个数据地址 CLR C ;0CY,准备作减法 SUBB A,R1 ;用减法作比较 单片机技术 JNC LP3 ;若A大,则转LP3 MOV A,R1;A小,则将大数送A中 SJMP LP4 ;无条件转LP4LP3:ADD A,R1 ;恢复A中值LP4:DJNZ R2,LP1 ;计数器减1,不为0,转继续比较 RET ;比较完,子程序返回单片机技术v例例4-15 在50H单元存有两位16进制数,编程将它们分别转换成ASCII码,并存入51H、52H单元。v解法1:16进制数转换成ASCII码的过程可采用子程序。v子程序名称:HASC v功能:把低4位16进制数转换成ASCII码(采用查表

42、法)v入口条件入口条件:A中存有待转换的16进制数;v出口条件出口条件:转换后的ASCII码在A中。v由于一个字节单元中有两位16进制数,而子程序的功能是一次只转换一位16进制数,所以50H单元中的两位16进制数要拆开、转换两次,因此,主程序需两次调用子程序,才能完成一个字节的16进制数向ASCII码的转换。编写主程序和子程序如下:主程序:ORG 2100H MOV SP,#3FH ;设堆栈指针 MOV A,50H ;取待转换的数送A中 ACALL HASC ;第一次调用转换子程序,单片机技术 MOV 51H,A ;存转换结果 MOV A,50H ;重新取待转换的数 SWAP A ;高4位交换

43、到低4位上,准备转换高4位 ACALL HASC ;再次调用子程序,转换高4位 MOV 52H,A ;存转换结果 END ;结束 子程序:ORG 2500HHASC:ANL A,#0FH ;只保留低4位,高4位清0 ADD A,#01H ;查表位置调整 MOVC A,A+PC ;查表取ASCII码送A中 RET ;子程序返回TAB:DB 30H,31H,32H,33H,34H,35H,36H,37H DB 38H,39H,41H,42H,43H,44H,45H,46H单片机技术v子程序在此采用的是查表法,查表法只需把转换结果按序编成表连续存放在ROM中,用查表指令即可实现转换,查表法编程方便、

44、且程序量小。v16进制数转换成ASCII码,也可以采用计算法,计算法需判断16进制数是09、还是AF,以确定转换时是+30H、还是+37H,v如果要求转换的不是某个单元的两位16进制数,而是一组数据,数据块的长度在R2中,数据块首地址在R0中,转换结果存放的首地址在R1中,则子程序不变,只修改主程序即可。由于数据块长度已知,源操作数首地址、目的操作数首地址已知,主程序可编成循环程序,故对上述主程序修改如下:单片机技术 ORG 2100H MOV SP,#3FH ;设堆栈指针LOOP:MOV A,R0 ;取待转换的数送A ACALL HASC ;调用转换子程序,MOV R1,A ;存转换结果 I

45、NC R1 ;修改目的地址 MOV A,R0 ;重新取待转换的数 SWAP A ;高4位交换到低4位上,准备转换高4位 ACALL HASC ;再次调用子程序,转换高4位 MOV R1,A ;存转换结果 INC R0 ;修改源操作数地址 INC R1 ;修改目的操作数地址 DJNZ R2,LOOP ;一组数据未转换完,继续 END ;转换完,结束 单片机技术v解法2:16进制数转换成ASCII码的过程仍采用子程序。子程序名称和功能同解法1,与解法1不同的是采用堆栈来传递参数。对应的主程序和子程序如下:v主程序:ORG 2100H MOV SP,#3FH ;设堆栈指针 PUSH 50H ;把50

46、H单元内的数压入堆栈 ACALL HASC ;调用转换子程序 POP 51H ;把已转换的低半字节的ASCII码弹入51H单元 MOV A,50H ;重取数送A SWAP A ;准备处理高半字节的16进制数 PUSH ACC ;参数进栈 ACALL HASC ;再次调用子程序 POP 52H ;把已转换的高半字节的ASCII码弹入52H单元 SJMP$单片机技术子程序:ORG 2500HHASC:DEC SP ;修改SP指针到参数位置 DEC SP POP ACC ;弹出参数到A中 ANL A,#0FH ;只保留低4位 ADD A,#07 ;修正查表位置 MOVC A,A+PC;查表,取表中的

47、ASCII码送A PUSH ACC ;把结果压入堆栈 INC SP ;修改SP指针到断点位置 INC SP RET ;子程序返回TAB:DB 30H,31H,32H,33H,34H,35H,36H,37H,38H DB 39H,41H,42H,43H,44H,45H,46H单片机技术v本例中堆栈的操作示意图见图4-10。当主程序第一次v执行PUSH 50H时,把50H中的内容压入40H单元内。v执行ACALL HASC指令后,则主程序的断点地址高低位分别压入41H、42H单元。进入子程序后,二次执行DEC SP,则把堆栈指针修正到40H。此时执行POP ACC则把40H中的数据(即50H单元内

48、容)弹入到ACC中。当查完表以后,执行PUSH ACC,则已转的ASCII码值压入堆栈的40H单元,v第二次执行INC SP,则SP变为42H,此时执行RET指令,则恰好把原断点内容又送回PC,SP又指向40H,所以返回主程序后执行 POP 51H,正好把40H的内容弹出到51H。第二次调用过程类似,不再赘述。单片机技术v435 运算类程序运算类程序v例例4-16 两个8位有符号数加法,和超过8位。v编程说明:在计算机中,有符号数一律用补码表示,两个有符号数的加法,实际上是两个数补码相加,由于和超过8位,因此,和就是一个16位符号数,其符号位在16位数的最高位。在进行这样的加法运算时,应先将8

49、位数符号扩展成16位,然后再相加。v符号扩展的原则:若是8位正数,则高8位扩展为00H;若是8位负数,则高8位扩展为FFH。经过符号扩展之后,再按双字节相加,则可以得到正确的结果。v编程时,寄存器R2和R3作两个加数的高8位,并先令其为全0,即先假定两个加数为正数,然后判别符号位,根据符号位再决定是否将其高8位改为FFH。v子程序入口:(R0)=存放加数的首地址,v (R1)=存放和的首地址v工作寄存器:R2作加数的高8位,v R3作另一个加数的高8位 单片机技术SBADD:MOV R2,#00H ;高8位先设0 MOV R3,#00H MOV A,R0 ;取出第一个加数 JNB ACC.7,

50、N1 ;若是正数,则转N1 MOV R2,#0FFH ;若是负数,高8位送全1N1:INC R0 ;修改R0指针 MOV B,R0 ;取第二个加数到B JNB B.7,N2 ;若是正数,则转N2 MOV R3,#0FFH ;是负数,高8位送全1N2:ADD A,B ;低8位相加 MOV R1,A ;存和的低8位 INC R1 ;修改R1指针 MOV A,R2 ;取一个加数的高8位送A ADDC A,R3 ;高8位相加 MOV R1,A ;存和的高8位 RETv在调用该子程序时,只需把加数加数及和的地址和的地址置入R0和R1,就可以调用这个子程序。单片机技术v例例4-17 两个8位带符号数的乘法

展开阅读全文
相似文档                                   自信AI助手自信AI助手
猜你喜欢                                   自信AI导航自信AI导航
搜索标签

当前位置:首页 > 通信科技 > 开发语言

移动网页_全站_页脚广告1

关于我们      便捷服务       自信AI       AI导航        获赠5币

©2010-2024 宁波自信网络信息技术有限公司  版权所有

客服电话:4008-655-100  投诉/维权电话:4009-655-100

gongan.png浙公网安备33021202000488号   

icp.png浙ICP备2021020529号-1  |  浙B2-20240490  

关注我们 :gzh.png    weibo.png    LOFTER.png 

客服