首页计算机计算机工程单片机原理及应用 04 项目4 汇编语言程序设计.pptx

04 项目4 汇编语言程序设计.pptx

页数:36页文件大小:366.5 KB来源: 单片机原理及应用ppt课件

本课件讲解汇编语言程序设计方法:先说明程序设计步骤与流程图绘制,再逐条介绍ORG、END、EQU、DB、DW、DS、BIT七条伪指令,接着用实例拆解顺序、分支、循环、查表与子程序五种基本结构。

项目4 汇编语言程序设计封面页,标示本章讲解源程序编制、伪指令与四种基本程序结构
程序设计概念讲解页,用盖房子比喻说明程序设计等于结构加算法并介绍源程序与目标程序的转换
程序设计步骤列表页,列出从任务分析、算法优化到编译调试的七个标准步骤
查看本课件的文字版(共 36 页,供检索与复制)

第1页:项目4 汇编语言程序设计封面

项目4「汇编语言程序设计」讲解汇编语言源程序的编制与汇编、常用伪指令,以及顺序、分支、循环、查表和子程序五种程序结构。

第2页:什么是程序设计

什么是程序设计?程序设计=结构+算法。程序设计就像盖房子:数据结构就像砖、瓦,算法就是设计图纸;有了原料还要按图纸一砖一瓦地砌,才能建成想要的房子。

  • 单片机通常使用汇编语言或C语言进行程序设计,程序较大时一般采用C语言,但汇编语言编写的程序执行效率较高
  • 转换前的汇编语言或C语言程序称为源程序,转换后的机器语言程序称为目标程序
  • 转换过程也叫汇编过程,通过计算机或人工转换的方法分别称为计算机汇编或手工汇编,计算机汇编要使用专门的汇编软件

第3页:4.1.1 程序设计步骤

4.1.1 程序设计步骤:对单片机系统进行程序设计时必须考虑硬件资源的配置,硬件系统设计完成后可按以下步骤进行程序设计。

  • 1.预完成任务的分析
  • 2.进行算法的优化
  • 3.绘制程序流程图
  • 4.分配资源
  • 5.编写源程序
  • 6.程序优化
  • 7.编译,调试,修改和最后确定源程序

第4页:程序流程图的绘制

用图形符号将总体设计思路及程序流向绘制在平面图上,使程序的结构关系直观明了,便于检查和修改。

  • 绘制方法:先画出简单的功能流程图(粗框图),再对功能流程图进行扩充和具体化,即对存储器、标志位等单元做具体的分配和说明,把每一个粗框图转化为具体的存储器或地址单元,从而绘制出详细的程序流程图
  • 常用符号:流线表示程序执行顺序流向;端点符号表示程序的开始和结束;判断符号表示判断功能;处理符号表示处理功能;连接符号用来实现流程图之间的连接

第5页:汇编语言源程序的格式

4.1.2 汇编语言源程序的格式:汇编语言源程序由若干语句组成,每一语句可由4个部分组成——标号、操作码、操作数及注释,各部分以不同的分隔符分隔。

  • 标号:表示该语句所在地址的标志符号,方便程序中其他语句访问;由字母打头的1—8个字母数字串组成,指令保留符、寄存器名、位址记忆符、伪指令符等都不能作标号使用
  • 操作码:表示操作的性质,是汇编指令中唯一不能缺省的部分
  • 操作数:表示操作的对象,可能是空白或以逗号分开的几个
  • 注释:对语句或程序段功能的解释说明,有助于阅读和维护

语句格式:[标号]:操作码[目的操作数][源操作数];[注释]

第6页:汇编语言源程序的汇编

4.1.3 汇编语言源程序的汇编:将汇编语言源程序翻译成机器语言目标程序的过程称为汇编,对单片机助记符的汇编有人工汇编和机器汇编两种方法。

  • 人工汇编:用人工查表将源程序译成机器码,一般分为两步——第一步将源程序中的指令逐条译成目标码(指令中的标号地址待求);第二步由伪指令求出标号所代表的具体地址,进行有关程序存储区的数据操作并进行偏移量的计算
  • 机器汇编:将源程序输入计算机后由汇编程序实现翻译工作并产生相应的机器码,是一种高效方便的方法

第7页:汇编起始地址伪指令ORG

4.1.4 伪指令:在机器汇编时对汇编过程进行控制和指导的指令称为伪指令,供汇编程序识别和执行但不产生可执行的目标代码,如规定目标代码在ROM中的存放区域、给符号与标号赋值、指示汇编结束等。标准的MCS-51常用伪指令有以下7条。

1.汇编起始地址伪指令——ORG(Origin):格式为 ORG 16位地址,功能是规定该指令后的下一段源程序经汇编后生成代码的存放起始地址。

  • 例如:ORG 0500H START:MOV A,R0 …… END
  • ORG总是出现在每段源程序或数据块的开始,源程序中可多处使用,使程序员把子程序、数据块存放在ROM的任何位置
  • 每当ORG出现时,下条指令的存放地址由此重新定位,所以ORG定义地址的顺序应由小到大,且不能重叠

第8页:汇编结束伪指令END

2.汇编结束伪指令——END(End of Assembly):指令格式为[标号:]END,功能是结束汇编语言源程序的操作。在源程序中只能有一条END,END之后所写的指令汇编程序不予处理。

第9页:符号赋值伪指令EQU

3.符号赋值伪指令——EQU(EQUate):指令格式为「字符名称 EQU 数或汇编符号」,功能是将一个数或特定的汇编符号赋给指定的字符名称。

  • 字符名称为自定符号而不是标号,其后无「:」
  • 字符名称可用来作数据地址、立即数、位地址或代码地址,其值可以是8位数也可以是16位数
  • 例如 TEST EQU 20H 后执行 MOV A,TEST,字符名称TEST就代表内部RAM 20H地址单元
  • 又例如 A1 EQU 10H 后执行 MOV A,A1,A1代表片内RAM的直接地址单元10H

使用EQU伪指令可以把抽象的数字地址表示成有一定意义的符号,增强程序的可读性。

第10页:定义数据字节伪指令DB

4.定义数据字节伪指令——DB(Define Byte):格式为[标号:]DB 项或项表。

  • 项或项表是指一个字节、逗号隔开的8位二进制的数或字符串,或用撇号括起来的ASCII字符串
  • 功能:从标号指定的地址单元开始,在程序存储器中存入一组8位二进制数,或者将一个数据表格存入程序存储器;汇编后影响程序存储器的内容

例如:ORG 1100H TAB:DB 01H,04H,09H,10H DB 00001111B,1,A,BC

第11页:定义数据字伪指令DW

5.定义数据字命令——DW(Define Word):格式为[标号:]DW 项或项表。

  • DW的功能和DB类似,区别是从标号指定的地址开始存放16位而非8位二进制数
  • 存放时数据字的高8位在前(低地址),低8位在后(高地址)

例如:ORG 5000H MOV A,#30H …… ORG 5020H ADDTAB: DW 1234H,100H,10 …… END

一条DB和DW语句定义的数表其数的个数不得超过80个,数据较多时可使用多个定义命令;在MCS-51程序设计应用中常以DW来定义地址。

第12页:预留存储区伪指令DS

6.预留存储区伪指令——DS(Define Storage):格式为[标号:]DS 表达式,功能是从指定地址开始保留表达式的值所需数目的字节单元作为存储区以备后用,汇编时对这些单元不赋值。

例如:ORG 0100H MOV A,#50H …… ADDRTABL:DS 05H DB 20H END,即从标号ADDRTABL代表的地址开始保留5个连续的ROM地址单元,第6个单元存放20H。

对MCS-51单片机来说,DB、DW、DS伪指令只能对程序存储器使用,而不能对数据存储器进行初始化。

第13页:位地址赋值伪指令BIT

7.位地址赋值伪指令——BIT:格式为[字符名称]BIT 位地址,功能是给字符名称赋以位地址,其中位地址可以是绝对地址,也可以是符号地址(位符号名称)。

  • 例如 AQ BIT P1.0:把P1.0的位地址赋给变量AQ
  • 例如 A2 BIT 07H:把位地址07H赋给符号名A2

在其后的编程中AQ和A2就可以作为位地址使用。

第14页:模块化程序设计方法

4.1.5 程序设计技巧:1.模块化程序设计方法。单片机应用系统的程序一般由包含多个模块的主程序和各种子程序组成,每一程序模块都要完成一个明确的任务、实现某个具体的功能,如发送、接收、延时、打印、显示等。

采用模块化的程序设计方法,就是将这些不同的具体功能程序进行独立的设计和分别调试,最后将这些模块程序装配成整体程序并进行联调。

第15页:模块化程序设计的优点

把一个多功能的、复杂的程序划分为若干个简单的、功能单一的程序模块,具有以下明显优点:

  • 单个模块结构的程序功能单一,易于设计、编写、调试及修改
  • 有利于程序的优化和分工,可使多个程序员同时进行编写和调试,加快软件研制进度
  • 提高程序的阅读性和可靠性,使程序的结构层次一目了然
  • 对程序的修改可局部进行,其他部分保持不变,便于功能扩充和版本升级
  • 对于使用频繁的子程序可以建立子程序库,便于多个模块调用

第16页:模块的划分原则

模块的划分有很大的灵活性,但也不能随意划分,划分时应遵循下述原则:

  • 每个模块应具有独立的功能,能产生一个明确的结果,即单模块的功能高内聚性
  • 模块之间的控制耦合应尽量简单,数据耦合应尽量少,即模块间的低耦合性(控制耦合指模块进入和退出的条件及方式,数据耦合指模块间信息交换的方式、交换量的多少及频繁程度)
  • 模块长度适中,模块语句的长度通常在20条~100条的范围较合适;模块太长时分析和调试困难,过短则模块连接太复杂、信息交换太频繁

第17页:程序设计技巧要点

2.程序设计技巧:

  • 尽量采用循环结构和子程序
  • 尽量少用无条件转移指令
  • 对于通用的子程序,除用于存放入口参数的寄存器外,子程序中用到的其他寄存器内容应压入堆栈(返回前再弹出)进行现场保护,并特别注意堆栈操作压入和弹出的平衡;一般不必把标志寄存器压入堆栈
  • 对于中断处理子程序,除了要保护程序中用到的寄存器外,还应保护标志寄存器
  • 累加器是信息传递的枢纽

第18页:4.2.1 顺序程序

4.2 程序结构 4.2.1 顺序程序:顺序结构是按照逻辑操作顺序,从某一条指令开始逐条顺序执行,直至某一条指令为止,无分支也无循环。

顺序结构是所有程序设计中最基本、最单纯的程序结构形式,在程序设计中使用最多,是一种最简单且应用最普遍的程序结构。实际应用程序远比顺序结构复杂,但它是组成复杂程序的基础和主干。

第19页:例4.1 两个半字节数合并成一个字节

【例4.1】将两个半字节数合并成一个一字节数:设内部RAM 40H、41H单元中分别存放着8位二进制数,要求取出两个单元的低半字节,合并成一个字节后存入42H单元。流程如图4-1所示。

  • 开始:40H内容送A,屏蔽高位
  • 交换高低位,送入R1
  • 41H内容送A,屏蔽高位
  • A与R1或后送入42H单元
  • 返回

第20页:例4.2 三字节无符号数加法程序

【例4.2】用顺序结构程序编写三字节无符号数的加法程序:被加数存放在40H(高字节)、41H(中字节)、42H(低字节),加数存放在43H(高字节)、44H(中字节)、45H(低字节),运算结果仍存在被加数单元中。流程如图4-2所示。

  • 取低字节数据,相加后送回被加数单元
  • 取中字节数据,带进位位相加后送回被加数单元
  • 取高字节数据,带进位位相加后送回被加数单元
  • 返回

第21页:4.2.2 分支程序

4.2.2 分支程序:实际问题一般比较复杂,总是伴随逻辑判断或条件选择,要求计算机能根据给定条件进行判断、选择不同的处理路径。程序的流向有两个或两个以上出口、根据指定条件选择程序流向的结构称为分支程序结构。

  • 按出口个数分为单分支结构程序(两个出口)和多分支结构程序(三个或三个以上出口)
  • 通过条件判断实现单分支转移的指令有JZ、JNZ、CJNE和DJNZ等
  • 以位状态为条件进行程序分支的指令有JC、JNC、JB、JNB和JBC等

使用这些指令,可以完成为0、为1,为正、为负,以及相等、不相等各种条件判断,实现程序有条件地转移。

第22页:例4.3 两个无符号数比较(两分支)

【例4.3】两个无符号数比较(两分支):内部RAM的30H单元和31H单元各存放了一个8位无符号数,请比较这两个数的大小,大数放在32H中。流程如图4-3所示。

  • 开始:X-Y,判断Cy是否为1
  • Cy=1时:31H→32H
  • Cy=0时:30H→32H
  • 结束

第23页:例4.4 两个有符号数比较(三分支)

【例4.4】两个无符号数比较(三分支程序):内部RAM的20H单元和30H单元各存放了一个8位有符号数,根据条件编程点亮相应的发光二极管,电路如图4-4所示。

  • 若(20H)=(30H),则P2.0管脚连接的黄色LED发光
  • 若(20H)>(30H),则P2.1管脚连接的绿色LED发光
  • 若(20H)<(30H),则P2.2管脚连接的红色LED发光

流程为:开始→判断X=Y?→判断X>Y?→分别点亮黄灯、绿灯或红灯→结束。

第24页:例4.5 散转程序与信号灯电路

3.散转程序:经过某个条件判断之后程序有多个流向(三个以上)的程序称为散转程序,MCS-51指令系统中专门提供了散转指令,使散转程序的编制更加简洁。

【例4.5】在例4.4电路的基础上加两个开关组成简单的信号灯电路(图4-6),编程实现按下不同开关点亮不同颜色灯的功能。

第25页:例4.5 开关状态与灯色对应关系

例4.5 开关状态与信号灯状态的对应关系:读P1口引脚状态送A,屏蔽无关位后以转移指令表基地址送DPTR,实现散转移。对应关系如下表。

开关K0、K1状态与信号灯状态对应表
K0K1状态信号灯状态
00状态1红黄绿灯全亮(都按下)
01状态2红灯亮(K0单独按下)
10状态3绿灯亮(K1单独按下)
11状态4黄灯亮(都未按下)

第26页:4.2.3 循环程序

4.2.3 循环程序:循环结构程序是把需要多次重复使用的程序段,利用转移指令反复转向该程序段,从而大大缩短程序代码、减少占用程序空间,程序结构也大大优化。如图4-8所示。

  • 循环程序可以分为单重循环和多重循环
  • 通常有两种编制方法:一种是先执行后判断,另一种是先判断后执行

第27页:例4.6 数据极值查找程序

1.单重循环程序设计 【例4.6】数据极值查找程序:设内部RAM从30H单元开始存放有8个数,找出其中最大的数放到60H单元。流程如图4-9所示。

  • 数据区首地址→R0,数据个数→R7
  • 读第一个数→A;R7-1→R7
  • 读下一个数→50H,比较(A)>(50H)?
  • 判断R7-1=0?,未完则继续比较,结束则A→(60H)

极值查找操作的主要内容是进行数值大小比较,采用先执行后判断的结构,首先设定比较次数,比较结束后把查找到的最大数送到60H单元。

第28页:例4.7 数据传送直到遇到数据100停止

【例4.7】将内部RAM中30H单元开始的数据传送到外部RAM 1200H开始的存储空间内,直到发现数据100停止传送。流程如图4-10所示。

  • 取内部RAM数据→A
  • 判断A=100?是则结束,否则传送数据到外部RAM后继续

由于循环次数事先不知道,但循环条件可以测试到,因此采用先判断后执行的程序结构。

第29页:多重循环程序与定时程序

2.多重循环程序设计—定时程序:在循环内套循环的程序结构称多重循环或循环嵌套。若把每重循环的内部看作一个整体,则多重循环的结构与单重循环一样,也由四部分组成。

  • 多重循环的执行过程是从内向外逐层展开的:内层执行完全部循环后外层完成一次循环,逐次类推
  • 每执行一次外层循环,内层必须重新设置初值,故每层均包含完整的循环程序结构;层次必须分明,层次之间不能有交叉,否则将产生错误

定时程序是一种很典型的多重循环程序,用于定时检测、定时扫描、定时中断等。所谓定时就是让CPU做一些与主程序功能无关的操作(例如将一个数字逐次减1直到为0)来空耗掉CPU的时间,由于知道CPU执行每条指令的准确时间,延时程序的时间可以精确计算出来。

第30页:例4.8 单循环延时程序与机器周期计算

【例4.8】设计一个延时50ms的程序,设单片机时钟晶振频率为fosc=12MHz。

机器周期的计算方法:T机器=12T时钟=12×(1/12M)=1μs。最简单的单循环定时程序:

  • MOV R7,#TIME
  • LOOP: NOP
  • NOP
  • DJNZ R7,LOOP

NOP指令的机器周期为1,用来提高定时精度,DJNZ指令的机器周期为2,故一次循环共4个机器周期;一个机器周期是1μs,则一次循环的延迟时间为4μs,程序总的延迟时间为4×time(μs)。

R7是8位寄存器,故这个程序的最长定时时间为256×4=1020(μs),定时范围是4~1024μs,可见单循环定时程序的时间延迟较小。

第31页:多重循环延时程序与定时时间计算

为了加长定时时间,通常采用多重循环方法,流程如图4-11所示,程序如下:

  • MOV R7,#TIME1
  • LOOP2:MOV R6,#TIME2
  • LOOP1:NOP
  • DJNZ R6,LOOP1
  • DJNZ R7,LOOP2
  • RET

流程为:外循环次数TIME1→R7,内循环次数TIME2→R6,空操作后判断R6-1=0?再判断R7-1=0?,完成后返回。

最大定时时间计算公式为:(256×2+2+2)×256+1=132097(μs)。若定时50ms,采取合适的TIME1和TIME2即可,如TIME1=200和TIME2=123。

第32页:循环控制与循环结束处理

循环控制:在重复执行循环体的过程中,不断修改和判别循环变量,直到符合循环结束条件。一般情况下循环控制有以下几种方式:

  • 计数循环:循环次数已知时,用计数器计数来控制循环次数,这种方式用得比较多;循环次数要在初始化部分预置,在控制部分修改,每循环一次计数器内容减1
  • 条件控制循环:循环次数未知时,一般通过设立结束条件来控制循环的结束
  • 循环结束处理:用于存放执行循环程序所得结果以及恢复各工作单元的初值等

第33页:4.2.4 查表程序

4.2.4 查表程序:在微型机控制系统中,有些参数的计算非常复杂,用计算法不仅程序长、难于计算,而且耗费大量时间;还有一些非线性参数要涉及指数、对数、三角函数以及积分、微分等运算,用汇编语言编程都比较复杂,甚至无法建立数学模型,这时可以采用查表法。

所谓查表法,就是把事先计算或测得的数据按一定顺序编制成表格,查表程序的任务就是根据被测参数的值或者中间结果查出最终所需要的结果,具有程序简单、执行速度快等优点。

  • 在键盘处理程序中查找按键相应的命令处理子程序入口地址
  • 在LED显示程序中获得LED数码管的显示代码
  • 根据自变量的值从函数表上查找出相应的函数值,实现非线性修正、代码转换等

第34页:例 查表计算函数y=x!的值

【例】查表计算函数 y=x!(x=0、1、2、…、7)的值:每个阶乘值占两个字节,以TABLE为起始地址按x的顺序依次存放,查表时用 MOVC A,@A+DPTR 取出对应结果。

函数y=x!的查表数据表
Y地址Y值
TABLE00H
TABLE+100H
TABLE+201H
TABLE+300H
TABLE+402H
TABLE+500H
TABLE+606H
TABLE+700H
TABLE+824H
TABLE+900H
TABLE+A20H
TABLE+B01H
TABLE+C20H
TABLE+D07H
TABLE+E40H
TABLE+F50H

说明:源文本中本表地址与数值完全粘连(例如「TABLE+A205」),此处按地址顺序拆分为相邻两字节的BCD结果(如x=6时为0720,即720;x=7时为5040),建议对照原课件图片核对后再入库。

第35页:4.2.5 子程序

4.2.5 子程序:在实际程序设计中,常会遇到多次应用的、完成相同的某种基本运算或操作的程序段。如果每用一次都从头编写一次,不仅麻烦、使程序冗长,而且浪费存储空间,还使出错率增加、给调试带来困难。

因此将那些需多次应用的、完成相同基本运算或操作的程序段从整个程序中独立出来,单独编制成一个程序段,尽量使其标准化,并存放于某一存储区域,需要时通过调用指令进行调用,这样的程序段称为子程序。

第36页:子程序的编制原则与说明

子程序作为一个具有独立功能的程序段,编程时需遵循以下原则:

  • 子程序的第一条指令必须有标号,明确子程序入口地址
  • 以返回指令RET结束子程序
  • 编写简明扼要的子程序说明部分
  • 具有较强的通用性和可浮动性,尽可能避免使用具体的内存单元和绝对转移地址等
  • 注意保护现场和恢复现场

编制子程序前,最好以程序注释的形式对子程序进行说明,说明内容包括:

  • 子程序名:提供给主程序调用的名字
  • 子程序功能:简要说明子程序能完成的主要功能
  • 入口参数:主程序需要向子程序提供的参数
  • 出口参数:子程序执行完之后向主程序返回的参数
  • 占用资源:该子程序中使用了哪些存储单元、寄存器等
顶部目录