单片机原理与应用:基于AT89S51+Proteus仿真
上QQ阅读APP看书,第一时间看更新

3.4 汇编语言程序设计

3.4.1 汇编程序设计概述

计算机程序设计语言通常分为3类,即机器语言、汇编语言和高级语言。

1.机器语言

用二进制代码0和1表示的语言称为机器语言。机器语言能够被计算机直接识别和执行,但它不易为人们编写和阅读,因此,人们一般不再用它来进行程序设计。

2.汇编语言

汇编语言也是一种面向机器的语言,它的助记符指令和机器语言保持着一一对应的关系。也就是说,汇编语言实际上就是机器语言的符号表示。用汇编语言编程时,编程者可以直接操作机器内部的寄存器和存储单元,能把处理过程描述得非常具体。因此通过优化能编制出高效率的程序,既可节省存储空间又可提高程序执行的速度,在空间和时间上都充分发挥了计算机的潜力。在实时控制的场合下,计算机的监控程序大多采用汇编语言编写。

用汇编语言编写的源程序称为汇编语言源程序。但是单片机不能直接识别,需要通过汇编将其转换成用二进制代码表示的机器语言程序,才能够识别和执行。汇编通常由专门的汇编程序来进行,通过编译后自动得到对应于汇编源程序的机器语言目标程序,这个过程叫作机器汇编。

汇编过程是将汇编语言源程序翻译成目标程序的过程。机器汇编通常是在计算机上通过编译程序实现汇编的。

汇编语言程序设计通常的步骤如下:

1)建立数学模型。根据课题要求,用适当的数学方法来描述和建立数学模型。

2)确定算法。绘制程序流程图算法是程序设计的基本依据。程序流程图是编程时的思路体现。

3)编写源程序。合理选择和分配内存单元、工作寄存器,按模块结构具体编写源程序。

4)汇编及调试程序。通过汇编生成目标程序,经过多次调试,对程序运行结果进行分析,不断修正源程序中的错误,最后得到正确结果,达到预期目的。

编写一个应用系统的汇编语言源程序,其程序结构一般有顺序结构、分支结构、循环结构和子程序结构等。

3.高级语言

高级语言是一种面向过程和问题并能独立于机器的通用程序设计语言,是一种接近人们自然语言和常用数字表达式的计算机语言。编程的速度快,编程者不必熟悉机器内部的硬件结构而可以把主要精力集中于掌握语言的语法规则和程序的结构设计方面。但程序执行的速度慢且占据的存储空间较大。

3.4.2 汇编程序设计举例

在使用汇编语言进行程序设计时,一般采用结构化的思想来处理问题。一般可以分为3种基本结构:顺序结构、分支结构和循环结构。在单片机应用程序中,也经常采用子程序的结构形式。下面介绍这些常用的程序设计方法及范例。

1.顺序结构程序设计

顺序程序结构是各类结构化程序块中最简单的一种。它按程序执行的顺序依次编写,在执行程序过程中不使用转移指令,只是顺序执行。

【例3-11】将片内RAM中40H单元中存储的压缩BCD数转换成二进制数并存储在工作寄存器R0中。

将压缩的BCD码转换成二进制数的方法为将压缩的BCD码的高4位乘以10,再加上低4位。程序清单如下:

978-7-111-61780-8-Chapter03-49.jpg

【例3-12】将片内RAM中40H、41H单元中的内容分别传送到片外RAM中40H、41H单元中。

将片内RAM中单元内容传送到片外RAM单元中,需要注意访问片内RAM和片外RAM单元的寻址指令是不同的。访问片内RAM时,使用MOV指令,访问片外RAM时,使用MOVX指令。程序如下:

978-7-111-61780-8-Chapter03-50.jpg

2.分支结构程序设计

分支程序主要是根据判断条件的成立与否来确定程序的走向,因此在分支程序中需要使用控制转移类指令。可组成简单分支结构和多分支结构。

当程序的判断仅有两个出口,两者选一,称为单分支结构。通常用条件判断指令来选择并确定程序的分支出口。

【例3-13】设内部RAM中40H和41H单元中存储两个8位无符号二进制数,试编程找出其中的大数存入50H单元中。

将两个数中的大数找出来,需要对这两个数进行比较。在单片机中有一条比较指令CJNE可以实现这个功能,在比较完之后,指令根据两个数是否相等进行跳转,并根据其大小对进位标志CY置位或复位。程序如下:

978-7-111-61780-8-Chapter03-51.jpg

当程序的判别部分有两个以上的出口流向时,称为多分支选择结构。

【例3-14】设变量x的值存储在内部RAM的50H单元中,编程求解下列函数式,将求得的函数值y存入40H单元。

978-7-111-61780-8-Chapter03-52.jpg

变量x的值在3个不同的区间所得到的函数值y值也不同,在编程时要注意区间的划分,采用CJNE指令完成。程序如下:

978-7-111-61780-8-Chapter03-53.jpg

978-7-111-61780-8-Chapter03-54.jpg

利用基址寄存器加变址寄存器间接转移指令JMP @A+DPTR,可以根据累加器A的内容实现程序多路分支,又称为散转程序。

【例3-15】某段程序的运算结果在R0中,要求根据R0的内容,分别转向0~255个操作程序段。

978-7-111-61780-8-Chapter03-55.jpg

3.循环结构程序设计

循环结构由4部分组成:初始化部分、循环处理部分、循环控制部分和循环结束部分。

1)初始化部分用来设置循环处理之前的初始状态,如循环次数的设置、变量初值的设置和地址指针的设置等。

2)循环处理部分又称为循环体,是重复执行的数据处理程序段,它是循环程序的核心部分。

3)循环控制部分用来控制循环继续与否。

4)结束部分是对循环程序全部执行结束后的结果进行分析、处理和保存。

根据循环程序的结构不同也可分为单重循环和多重循环。在一个循环程序的循环体中不包含另外的循环结构称为单重循环。

对循环次数的控制有多种:循环次数是已知的,可用循环次数计数器控制循环;若循环次数是未知的,可以按条件控制循环。

【例3-16】设内部RAM存储有一无符号数数据块,长度为128B,在以30H单元为首址的连续单元中。试编程找出其中最小的数,并存储在20H单元。

978-7-111-61780-8-Chapter03-56.jpg

4.子程序设计

完成某一特定功能、反复使用的程序可以设计成子程序,这样可使应用程序结构清晰紧凑,节省代码空间,也使应用程序便于阅读和调试。子程序在结构上仍然采用前面介绍的一般程序的3种结构。

【例3-17】设计一个软件延时子程序DELAY。

程序清单如下:

978-7-111-61780-8-Chapter03-57.jpg

若单片机的晶振频率为12MHz,则一个机器周期是1μs,延时子程序DELAY的延时时间计算如下:

因为0FAH=250,0AH=10,所以程序执行总时间也就是延时时间T

T=((250×2+3)×10+3)μs=5033μs

若想加长延时时间,则可以增加循环次数;若想缩短延时时间,则可以减少循环次数。

【例3-18】电路如图3-7所示,AT89S51单片机的P2口做输出,经上拉电阻驱动连接8只发光二极管D1~D8,当输出位为1时发光二极管点亮;输出位为0时发光二极管熄灭。试编制程序实现以下发光二极管点亮的功能:D1D8亮其余灭→延时→D2D7亮其余灭→延时→D3D6亮其余灭→延时→D4D5亮其余灭→延时→D3D6亮其余灭→延时→D2D7亮其余灭→延时→D1D8亮其余灭,重复上述过程。

利用子程序DELAY实现延时功能,完整的程序清单如下:

978-7-111-61780-8-Chapter03-58.jpg

978-7-111-61780-8-Chapter03-59.jpg

图3-7 控制发光二极管电路原理图

978-7-111-61780-8-Chapter03-60.jpg

将此汇编语言源程序在Keil uVision开发环境进行编辑、汇编,生成hex执行文件,然后加载到Proteus电路图中的单片机中执行,可看到发光二极管按程序要求点亮。仿真运行结果如图3-8所示。

978-7-111-61780-8-Chapter03-61.jpg

图3-8 控制发光二极管仿真运行结果

978-7-111-61780-8-Chapter03-62.jpg

二维码3-1