第3章 8051指令系统与 编程基础 1.

Slides:



Advertisements
Similar presentations
第7章 AT89S51单片机的 串行口 1.
Advertisements

本章内容: 中断的概念 MCS-51单片机中断系统 外部事件中断及应用
第四章 指令系统及汇编语言程序设计.
8051 指令.
第4章 MCS-51程序设计 4.1 汇编语言的格式与伪指令 4.2 汇编语言程序设计步骤 4.3 查表程序设计 4.4 循环程序设计
第四章 指令系统及汇编语言程序设计.
本章分为四节,主要介绍: 4.1 程序编制的方法和技巧 4.2 源程序的编辑和汇编 4.3 基本程序结构 4.4 常用程序举例.
得技通电子 问题 1 右何者非為假指令 (1) XRL (2) EQU (3) MACRO (4) ORG.
本章小结 C51单片机指令系统概述 C51单片机寻址方式 C51单片机指令系统
第3章 MCS-51指令系统 3.1 简 介 指令概述 一台微机所具有的所有指令的集合,就构成了指令系统。指令系统越丰富,说明CPU的功能越强。例如,Z80 CPU中,没有乘法和除法指令,乘法和除法运算必须用软件来实现,因此执行速度相对较慢;而MCS-51单片机提供了乘法和除法指令,实现乘法和除法运算时就要快得多。
单片机原理与应用.
第2章 MCS-51单片机指令系统与汇编语言程序设计
单片机原理与应用.
報告者:朱耿育 紀翔舜 組員:詹以群 張永傑 指導老師:梁新潁
复 习 一. 计算机中的数和编码 1. 2,10,16进制数及其之间的转换(整数) 按权展开,除x取余 2
第二部分 微机原理 第4章 汇编语言 程序设计 主讲教师:喻红.
单片机应用技术 项目一 循环彩灯装置 第6讲 指令功能及汇编语言程序设计(一) 《单片机应用技术》精品课程组 湖北职业技术学院机电工程系.
本章内容: 中断的概念 MCS-51单片机中断系统 外部事件中断及应用
第四章 指令系统及汇编语言程序设计.
本章分为七节,主要介绍: 3.1 指令格式及常用符号 C51的寻址方式 3.3 数据传送类指令(29条) 3.4 算术运算类指令(24条)
第二部分 微机原理 第3章 MCS-51的 指令系统 主讲教师:喻红.
一、任务描述 二、任务分析 三、任务演示 四、相关知识 五、任务布置. 一、任务描述 二、任务分析 三、任务演示 四、相关知识 五、任务布置.
单片机应用技术 项目二 电子打铃装置 第1讲 指令功能及汇编语言 程序设计(二) 《单片机应用技术》精品课程组 湖北职业技术学院机电工程系.
第3章 AT89C51指令系统 3.1基本概念内部结构和引脚功能 指令、指令系统、机器代码
逻辑运算类指令 包括与、或、非、异或、清0及移位等共24条;一般不影响PSW中的标志位;助记符有:ANL、ORL、XRL、RL、RLC、RR、RRC、CLR和CPL共9种。 一、逻辑与指令 ANL A,Rn ;A←(A)∧( Rn) ANL A,direct;A←(A)∧(direct)
单片机原理及应用 MCS-51系列单片机的基本硬件结构 MCS-51指令系统 MCS-51单片机的系统扩展与应用.
第八章 MCS-51与数码显示器和键盘的接口 一、MCS-51与数码显示器接口 数码显示器是单片机应用产品中最常用的廉价的输 出设备,它由8个发光二极管按一定规律排列而成, 当某一发光二极管导通时,则会被点亮,控制不同 组合的二极管导通,就能显示出各种字符。 1.显示器的结构.
本 章 重 点 单片机的简单I/O扩展 8255A可编程并口芯片 8279可编程键盘/显示器接口芯片 单片机键盘接口技术
单片机原理 单 片 机 单片机接口技术 单片机应用技术.
第一单元 初识C程序与C程序开发平台搭建 ---观其大略
第三章 指令系统.
第3章 指令系统及程序设计举例 3.1 指令格式与寻址方式 一、指令格式 1. 指令 操作码 目标操作数,源操作数
逆向工程-汇编语言
CPU结构和功能.
第10章 综合实训 课题一 水温控制系统设计 一、实训目的 二、课题要求 熟悉常用温度传感器AD590的特性及接口电路的设计方法;
6.1 输入/输出 6.2 CPU与外设数据传送方式 6. 3 MCS-51中断系统 6. 4 中断应用举例
第四章 指令系统及汇编语言程序设计.
第四章 指令系统及汇编语言程序设计.
第3章 MCS-51单片机指令系统 3.1 指令概述 3.2 寻址方式 3.3 MCS-51系列单片机的指令系统.
数码管数字时钟电路的设计 1. 系统硬件电路的设计
C语言程序设计 主讲教师:陆幼利.
得技通电子 问题 1.0 、选择题:本大题共15个小题,每小题1分,共15分,在每小题给出的四个选项中,只有一项符合题目要求,把所选项前的字母填在括号内。
第四章 MCS-51定时器/计数器 一、定时器结构 1.定时器结构框图
第3章 MCS-51指令系统 介绍MCS—51系列单片机的寻址方式 介绍MCS—51系列单片机的指令系统
第4章 80C51系列指令系统 教学目的:熟悉80C51系列单片机的寻址方式及 每一种寻址方式对应的寻址空间;掌 握每一条指令功能。
第3章 MCS-51的指令系统 介绍MCS-51汇编语言的指令系统。 3.1 指令系统概述
本章内容 MCS-51单片机指令系统的格式 MCS-51单片机寻址方式 指令系统的分析
微机原理与接口技术 微机原理与接口技术 朱华贵 2015年11月13日.
第三章 MCS 51的硬件结构.
第4章 Excel电子表格制作软件 4.4 函数(一).
第三章 计算机系统的组成与工作原理.
任务五 学习、应用控制转移类指令 单片机应用技术 认知1 掌握无条件转移指令格式及应用
汽车单片机应用技术 学习情景1: 汽车空调系统的单片机控制 主讲:向楠.
单片机原理及应用 实践部分 主讲人:刘 强 四川工商学院单片机教学团队 单片机原理及应用 实践部分 主讲人:刘 强
College of Computer Science & Technology
四、手工汇编 完成汇编的方法有两种:手工汇编和汇编程序汇编 1.手工汇编步骤 A
单片机应用技术 项目一 循环彩灯装置 第5讲 MCS-51单片机指令系统及指令格式 《单片机应用技术》精品课程组 湖北职业技术学院机电工程系.
3. 逻辑运算指令 A、简单逻辑操作指令 CLR A. (不影响CY、AC、 OV标志) CPL A
得技通电子 问题 三 判断题:.
微机原理与接口技术 西安邮电大学计算机学院 宁晓菊.
C++语言程序设计 C++语言程序设计 第一章 C++语言概述 第十一组 C++语言程序设计.
循环程序设计 在程序中包含重复执行的程序段称为循环程序设计。循环程序可以使程序结构性强、可读性好,从而大大提高了程序质量。
数据表示 第 2 讲.
4.3 汇编语言程序设计 顺序程序设计 顺序程序设计是最基本的程序设计。它是按照指令排列的先后顺序依次执行,每条指令都必须执行,且只执行一遍。顺序程序设计一般比较单一、简单,常常作为复杂程序的一部分。
单片机应用技术 (C语言版) 第3章 MCS-51指令系统及 汇编程序设计
第二章 MCS-51单片机程序设计 第一章 8086程序设计 第三章 微机基本系统的设计 第四章 存贮器与接口 第五章 并行接口
认知1 掌握“与”、“或”和“异或”指令格式及应用
第3章 80C51单片机指令系统 教学基本要求: (1)、了解单片机的指令系统、编程语言等基本概念;
第4章 MCS-51汇编语言程序设计 教学基本要求: (1)、了解MCS-51汇编语言程序设计的特点;
第1章 微型计算机基础.
Presentation transcript:

第3章 8051指令系统与 编程基础 1

第3章 8051指令系统与编程基础 3.1 指令系统概述 3.2 指令格式 3.3 指令系统的寻址方式 3.4 8051指令系统分类介绍 3.4.1 数据传送类指令 3.4.2 算术运算类指令 3.4.3 逻辑操作类指令 3.4.4 控制跳转类指令 3.4.5 位操作类指令 3.5 8051指令系统汇总 3.6 某些指令的说明 3.7 8051汇编语言程序设计基础

3.7.1 编程语言概述 3.7.2 汇编语言语句和格式 3.7.3 伪指令 3.7.4 汇编语言源程序的汇编 3.8 8051汇编语言程序设计举例 3.8.1 子程序的设计 3.8.2 查表程序设计 3.8.3 分支转移程序设计 3.8.4 循环程序设计

内容概要 凡是8051内核的单片机均使用8051的汇编语言指令系统。介绍指令系统寻址方式 对111条基本指令按功能分类详细讲解。 指令---是CPU按照人们的意图来完成某种操作的命令,它以英文名称或缩写形式作为助记符。 汇编语言指令---用助记符、符号地址、标号等表示的书写程序的语言。 熟知并掌握8051指令系统的各类指令是AT89S51/52单片机汇编语言源程序的设计基础。

3.1 指令系统概述 简明、易掌握、效率较高的指令系统,复杂指令集。 按所占字节分,分三种: (1)单字节指令49条; (2)双字节指令45条; (3)三字节指令17条。 按执行时间来分,分三种: (1)1个机器周期(12个时钟振荡周期)的指令64条; (2)2个机器周期指令45条; (3)4个机器周期——乘、除指令。 5

12MHz晶振,每个机器周期为1µs。 AT89S52一大特点是在硬件结构中有一个位处理机,一个处理位变量的指令子集。 3 6

(1)单字节指令:操作码和操作数同在一个字节中。 (2)双字节指令:一个字节为操作码,另一个字节是操作数。 (3)三字节指令:操作码占一个字节,操作数占二个字节。 3.3 指令系统的寻址方式 寻址方式——在指令中说明操作数所在地址的方法。 一般说,寻址方式越多,功能就越强,灵活性则越大,指令系统就越复杂。 寻址方式所要解决的主要问题就是如何在整个存储器和寄存器的寻址空间内快速地找到指定的地址单元。 下面介绍指令系统7种寻址方式。 7

1.寄存器寻址方式 指令中的操作数为某一寄存器的内容。 例如:MOV A,Rn ;(Rn)→A,n =0~7 把Rn中的源操作数送入到累加器A中。由于指令指定了从寄存器Rn中取得源操作数,所以称为寄存器寻址方式。 2.直接寻址方式 指令中直接给出操作数的单元地址,该单元地址中的内容就是操作数,直接的操作数单元地址用“direct”表示。 例如: MOV A,direct “direct”就是操作数的单元地址。 8

例如: MOV A,40H 表示把内部RAM 40H单元(direct)的内容传送到A。指令中源操作数(右边的操作数)采用的是直接寻址方式。 指令中两个操作数都可由直接寻址方式给出。 例如: MOV direct1,direct2 具体指令:MOV 42H,62H 把片内RAM中62H单元的内容送到片内RAM中的42H单元中。 直接寻址是访问片内所有特殊功能寄存器的唯一寻址方式。 9

3. 寄存器间接寻址方式 寄存器中存的是操作数地址,即先从寄存器中找到操作数的地址,再按该地址找到操作数。 为了区别寄存器寻址和寄存器间接寻址,在寄存器间接寻址方式中,应在寄存器名称前面加前缀标志“@”。 例如:MOV A,@Ri ;i=0或1 其中, Ri的内容为40H,即把内部RAM 40H地址单元中的内容传送给A。 10

4.立即数寻址方式 直接在指令中给出操作数——也称立即数。为了与直接寻址指令中的直接地址加以区别,需在操作数前加前缀标志“#”。 例如: MOV A,#40H 第一个字节是操作码,第二字节是立即数,就是放在程序存储器内的常数。 11

5.基址寄存器加变址寄存器间址寻址方式 以DPTR或PC作为基址寄存器,以累加器A作为变址寄存器,以两者内容相加形成的16位地址作为目的地址进行寻址。例如指令: MOVC A,@A+DPTR 其中,(A)=05H,(DPTR)=0400H,指令执行结果是把程序存储器0405H单元的内容传送给A。 本寻址方式的指令有3条: MOVC A,@A+DPTR MOVC A,@A+PC JMP A,@A+DPTR 前两条指令适用于读程序存储器中固定的数据。例如,将固 12

定的、按一定顺序排列的表格存放在程序存储器中,在程序运行中由A的动态参量来确定读取对应的表格参数。 第3条为散转指令,A中内容为程序运行后的动态结果,可根据A中不同内容,实现跳向不同程序入口的跳转。 6.相对寻址方式 解决程序转移。该寻址是以该转移指令的地址(PC值)加上它的字节数,再加上相对偏移量(rel),形成新的转移目的地址,从而程序转移到该目的地址。转移的目的地址用下式计算: 目的地址=转移指令所在的地址+转移指令字节数+rel

其中,偏移量rel是带符号8位二进制补码数,–128~+127。 程序转移范围是以转移指令的下条指令首地址为基准地址,相对偏移在–128~+127之间。 例如, SJMP rel 程序要转移到该指令的PC值加3再加上rel的目的地址处。编写程序时,只需在转移指令中直接写要转向的地址标号。 例如: SJMP LOOP “LOOP” 为目的地址标号。汇编时,由汇编程序自动计算和填入偏移量。但手工汇编时,偏移量的值由手工计算。 14

7.位寻址方式 对内部RAM和特殊功能寄存器具有位寻址功能的某位内容进行置1和清0操作。 位地址一般以直接位地址给出,位地址符号为“bit”。 例如:MOV C,bit 其具体指令: MOV C,40H 把位地址为40H的值送到进位位C。 由于AT89S52具有位处理功能,可直接对数据位方便地实现置1、清0、求反、传送、判跳和逻辑运算等操作,为测控系统的应用提供了最佳代码和速度,增强了实时性。 15

7种寻址方式已介绍完毕。 问题:当一条指令给定后,如何来确定该指令的寻址方式?例如: MOV A,#40H,属于立即数寻址还是寄存器寻址? 要看以哪个操作数作为参照系。 操作数分为源操作数和目的操作数。对于源操作数“#40H”来说,是“立即数寻址”方式,但对目的操作数“A”来说,是属于“寄存器寻址”方式。 一般而言,寻址方式指的是源操作数,所以此例为立即数寻址方式。 对指令系统7种寻址方式总结,概括见表3-1。 16

表3-1 7种寻址方式及其寻址空间 17

3.4 8051指令系统分类介绍 共111条指令,按功能分为五类: (1)数据传送类(28条) (2)算术运算类(24条) 3.4 8051指令系统分类介绍 共111条指令,按功能分为五类: (1)数据传送类(28条) (2)算术运算类(24条) (3)逻辑操作类(25条) (4)控制转移类(17条) (5)位操作类(17条) 先简单介绍指令用到的符号。 Rn 当前寄存器区的8个工作寄存器R0~R7(n=0~7)。 Ri 当前寄存器区中作为间接寻址寄存器的2个寄存器R0、R1(i=0,1)。 18

直接地址,即8位内部数据存储器单元或特殊功能寄存器的地址。 direct 直接地址,即8位内部数据存储器单元或特殊功能寄存器的地址。 #data 指令中的8位立即数。 #data16 指令中的16位立即数。 rel 偏移量,8位的带符号补码数。 DPTR 数据指针,可用作16位数据存储器单元地址的寄存器。 bit 内部RAM或特殊功能寄存器中的直接寻址位。 C或Cy 进位标志位或位处理机中的累加器。 addr11 11位目的地址。 addr16 16位目的地址。 @ 间接寻址寄存器前缀,如@Ri,@A+DPTR。 (х) 表示х地址单元或寄存器中的内容。 ((х)) 表示以х单元或寄存器中的内容作为地址间接寻址单元的内容。 → 箭头右边的内容被箭头左边的内容所取代。 19

3.4.1 数据传送类指令 使用最频繁。一般数据传送类指令的助记符为“MOV”,通用格式如下: MOV <目的操作数>,<源操作数> 数据传送类指令是把源操作数传送到目的操作数。指令执行之后,源操作数不改变,目的操作数修改为源操作数。所以数据传送类操作属“复制”性质,而不是“搬家”。 本类指令不影响标志位:Cy、Ac和OV,但不包括奇偶标志位P。 20

把源操作数内容送累加器A,源操作数有寄存器寻址、直接寻址、间接寻址和立即数寻址等方式,例如: 1.以累加器为目的操作数的指令 MOV A,Rn ; (Rn)→A,n =0~7 MOV A,@ Ri ; ((Ri))→A i =0,1 MOV A,direct ; (direct)→A MOV A,#data ; #data→A 把源操作数内容送累加器A,源操作数有寄存器寻址、直接寻址、间接寻址和立即数寻址等方式,例如: MOV A,R6 ;(R6)→A,寄存器寻址 MOV A,@R0 ;((R0))→A,间接寻址 MOV A,70H ;(70H)→A,直接寻址 MOV A,#78H ;78H→A,立即数寻址 21

2.以Rn为目的操作数的指令 MOV Rn ,A ;(A)→Rn ,n =0~7 MOV Rn ,direct ;(direct)→Rn ,n =0~7 MOV Rn ,#data ;#data→Rn ,n =0~7 把源操作数送入当前寄存器区的R0~R7中的某一寄存器。 3.以直接地址direct为目的操作数的指令 MOV direct,A ; (A)→direct MOV direct,Rn ; (Rn)→direct,n =0~7 MOV direct1,direct2 ;(direct2)→direct1 MOV direct,@Ri ; ((Ri))→direct,i =0,1 MOV direct,#data ; #data→direct 22

把源操作数送入直接地址指定的存储单元。direct指的是内部RAM或SFR地址。 4.以寄存器间接地址为目的操作数的指令 MOV @Ri,A ;(A)→((Ri)), i=0,1 MOV @Ri,direct ;(direct)→((Ri)),i=0,1 MOV @Ri,#data ;#data→((Ri)), i=0,1 功能是把源操作数内容送入R0或R1指定的存储单元中。 5.16位数传送指令 MOV DPTR,#data16;#data16→DPTR 功能是把16位立即数送入DPTR,用来设置数据存储器的地址指针。 23

AT89S52有两个DPTR,通过设置特殊功能寄存器AUXR1中的DPS位来选择。当DPS=1,则指令中的DPTR即为DPTR1,DPTR0被屏蔽,反之亦然。 DPTR为16位的数据指针,分为DPH和DPL。操作十分灵活方便。设有两个DPTR后,就可避免频繁的出入堆栈操作。 对于所有MOV类指令,累加器A是一个特别重要的8位寄存器,CPU对它具有其他寄存器所没有的操作指令。后面将要介绍的加、减、乘、除指令都是以A作为目的操作数。

Rn为所选择的寄存器组中的R0~R7,直接地址direct为内部RAM的00H~7FH和特殊功能寄存器(地址范围80H~FFH) 在间接地址中,用R0或R1作为内部RAM的地址指针,可访问内部RAM的00H~7FH共128个单元。 6.堆栈操作指令 内部RAM中设定一个后进先出(LIFO,Last In First Out)的区域,称为堆栈。在特殊功能寄存器中有一个堆栈指针SP,指示堆栈的栈顶位置。堆栈操作有进栈和出栈两种,因此,在指令系统中相应有两条堆栈操作指令。 25

(1)进栈指令 PUSH direct 首先将栈指针SP加1,然后把direct中的内容送到SP指示的内部RAM单元中。 例如:当(SP)=60H,(A)=30H,(B)=70H时,执行下列指令 PUSH Acc ;(SP)+1=61H→SP,(A)→61H PUSH B ;(SP)+1=62H→SP,(B)→62H 结果:(61H)=30H,(62H)=70H,(SP)=62H。 (2)出栈指令 POP direct 将SP指示的栈顶单元的内容送入direct字节中,SP减1。 26

例如:当(SP)=62H,(62H)=70H,(61H)=30H时,执行指令 POP DPH ;((SP))→DPH,(SP)-1→SP POP DPL ;((SP))→DPL,(SP)-1→SP 结果为(DPTR)=7030H,(SP)=60H。 7.累加器A与外部数据存储器RAM/IO传送指令 MOVX A,@DPTR ;((DPTR))→A,读外部RAM/IO MOVX A,@Ri ;((Ri))→A,读外部RAM/IO MOVX @DPTR,A ;(A)→((DPTR)),写外部RAM/IO MOVX @Ri ,A ;(A)→((Ri)),写外部RAM/IO 27

MOV的后面加“X”,表示访问的是片外RAM或I/O口,在执行前两条指令, (P3. 7)有效;后两条指令, (P3 MOV的后面加“X”,表示访问的是片外RAM或I/O口,在执行前两条指令, (P3.7)有效;后两条指令, (P3.6)有效。 采用16位的 DPTR间接寻址,可寻址整个64KB片外数据存储器空间,高8位地址(DPH)由P2口输出,低8位地址(DPL)由P0口输出。 采用Ri(i =0,1)进行间接寻址,可寻址片外256个单元的数据存储器。8位地址由P0口输出,锁存在地址锁存器中,然后P0口再作为8位数据口。 8.查表指令 共两条,仅有的两条读程序存储器中表格数据的指令。由于程序 28

存储器只读不写,因此传送为单向,从程序存储器中读出 数据到A中。两条查表指令均采用基址寄存器加变址寄存器间接寻址方式。 (1)MOVC A,@A+PC 以PC作为基址寄存器,A的内容(无符号数)和PC的当前值(下一条指令的起始地址)相加后得到一个新的16位地址,把该地址的内容送到A。 例如:当 (A)=30H时,执行地址1000H处的指令 1000H: MOVC A,@A+PC 29

该指令占用一个字节,下一条指令的地址为1001H,(PC)=1001H再加上A中的30H,得1031H,结果把程序存储器中1031H的内容送入累加器A。 优点:不改变特殊功能寄存器及PC的状态,根据A的内容就可以取出表格中的常数。 缺点:表格只能存放在该指令所在地址的+256个单元之内,表格大小受到限制,且表格只能被一段程序所用。 (2)MOVC A,@A+DPTR DPTR为基址寄存器,A的内容(无符号数)和DPTR的内容相加得到一个16位地址,把由该地址指定的程序存储器单

元的内容送到累加器A。 例如:(DPTR)=8100H,(A)=40H,执行指令 MOVC A,@A+DPTR 将程序存储器中8140H单元内容送入A中。 本指令执行结果只与指针DPTR及累加器A的内容有关,与该指令存放的地址及常数表格存放的地址无关,因此表格的大小和位置可以在64KB程序存储器空间中任意安排,一个表格可以为各个程序块公用。 两条指令的助记符都是在MOV的后面加“C”,是CODE的第一个字母,即表示程序存储器中的代码。 31

执行上述两条指令时,单片机的 PSEN*引脚信号(程序存储器读)有效,这一点读者要牢记。 9.字节交换指令 XCH A,Rn ; (A) ( Rn),n =0~7 XCH A,direct ; (A) ( direct) XCH A,@Ri ; (A) (( Ri)),i=0,1 这组指令的功能是将累加器A的内容和源操作数的内容相互交换。源操作数有寄存器寻址、直接寻址和寄存器间接寻址等方式。例如: (A)=80H,(R7)=08H,(40H)=F0H (R0)=30H,(30H)=0FH 执行下列指令: 32

结果为(A)=0FH,(R7)=80H,(40H)=08H,(30H)=F0H。 XCH A,R7 ;(A) ((R7) XCH A,40H ;(A) ((40H) XCH A,@R0 ;(A) (((R0)) 结果为(A)=0FH,(R7)=80H,(40H)=08H,(30H)=F0H。 10.半字节交换指令 XCHD A,@Ri 累加器的低4位与内部RAM低4位交换。 例如:(R0)=60H,(60H)=3EH,(A)=59H 执行完“XCHD A,@R0”指令,则(A)=5EH,(60H)=39H。

3.4.2 算术运算类指令 指令系统中,有单字节的加、减、乘、除法指令,算术运算功能比较强。 算术运算指令都是针对8位二进制无符号数的,如要进行带符号或多字节二进制数运算,需编写具体的运算程序,通过执行程序实现。 算术运算的结果将使PSW的进位(Cy)、辅助进位(Ac)、溢出(OV)3种标志位置1或清0。 但增1和减1指令不影响这些标志。 34

使用本指令时,要注意累加器A中的运算结果对各个标志位的影响: 1.加法指令 4条指令: ADD A,Rn ;(A)+(Rn)→A ,n=0~7 ADD A,direct ;(A)+(direct)→A ADD A,@Ri ;(A)+((Ri))→A,i=0,1 ADD A,#data ;(A)+#data→A 8位加法指令的一个加数总是来自累加器A,而另一个加数可由寄存器寻址、直接寻址、寄存器间接寻址和立即数寻址等不同的寻址方式得到。加的结果总是放在累加器A中。 使用本指令时,要注意累加器A中的运算结果对各个标志位的影响: (1)如果位7有进位,则进位标志Cy置1,否则Cy清0。 35

(2)如果位3有进位,辅助进位标志Ac置1,否则Ac(Ac为PSW寄存器中的一位)清0。 (3)如果位6有进位,而位7没有进位,或者位7有进位,而位6没有进位,则溢出标志位OV置1,否则OV清0。 溢出标志位OV的状态,只有带符号数加法运算时才有意义。当两个带符号数相加时,OV=1,表示加法运算超出了累加器A所能表示的带符号数的有效范围(-128~+127),即产生了溢出,表示运算结果是错误的,否则运算是正确的,即无溢出产生。 36

【例3-1】 (A)=53H,(R0)=FCH,执行指令 ADD A,R0 运算式为 结果:(A)=4FH,Cy=1,Ac=0,OV=0,P=1(A中1的位数为奇数)。 注意:在上面的运算中,由于位6和位7同时有进位,所以标志位OV=0。 37

【例3-2】 (A)= 85H,(R0)=20H,(20H)=AFH,执行指令 ADD A,@R0 运算式为 结果:(A)=34H,Cy=1,Ac=1,OV=1,P=1。 注意:由于位7有进位,而位6无进位,所以标志位OV=1。 38

特点是进位标志位Cy参加运算,三个数相加。 4条指令: 2.带进位加法指令 特点是进位标志位Cy参加运算,三个数相加。 4条指令: ADDC A,Rn ;(A)+(Rn)+C→A ,n =0~7 ADDC A,direct ;(A)+(direct)+C→A ADDC A,@Ri ;(A)+((Ri))+C→A,i =0,1 ADDC A,#data ;(A)+#data+C→A 如果位7有进位,则进位标志Cy置“1”,否则Cy清“0”; 如果位3有进位,则辅助进位标志Ac置“1”,否则Ac清“0”; 如果位6有进位而位7没有进位,或者位7有进位而位6没有进位,则溢出标志OV置“1”,否则标志OV清“0”。 39

【例3-3】 (A)=85H,(20H)=FFH,Cy=1,执行指令 ADDC A,20H 运算式为 结果为 (A)=85H,Cy=1,Ac=1,OV=0,P=1 (A中1的位数为奇数。 )。 40

把指令中所指出的变量增1,且不影响PSW中的任何标志。 3.增1指令 5条指令: INC A INC Rn ;n=0~7 INC direct INC @Ri ;i =0,1 INC DPTR 把指令中所指出的变量增1,且不影响PSW中的任何标志。 指令“INC DPTR”,16位数增1指令。首先对低8位指针DPL执行加1,当溢出时,就对DPH的内容进行加1,不影响标志Cy。 41

4.十进制调整指令 用于对BCD码加法运算结果的内容修正,指令格式为: DA A 是对压缩的BCD码(一个字节存放2位BCD码)的加法结果进行十进制调整。 两个BCD码按二进制相加之后,必须经本指令的调整才能得到正确的压缩BCD码的和数。 (1)十进制调整问题 对BCD码加法运算,只能借助于二进制加法指令。但二进制数加法原则上并不适于十进制数的加法运算,有时会产生错误结果。例如: 42

上述的BCD码运算中: (a)结果正确。 (b)结果不正确,因为BCD码中没有1111这个编码。 (c)结果不正确,正确结果应为17,而运算结果却是11。 可见,二进制数加法指令不能完全适用于BCD码十进制数的加法运算,要对结果做有条件的修正,这就是所谓的十进制调整问题。 43

(2)出错原因和调整方法 出错原因在于BCD码共有16个编码,但只用其中的10个,剩下6个没用到。这6个没用到的编码(1010,1011,1100,1101,1110,1111)为无效编码。 在BCD码加运算中,凡结果进入或者跳过无效编码区时,结果出错。因此1位BCD码加法运算出错的情况有两种: ① 加结果大于9,说明已经进入无效编码区。 ② 加结果有进位,说明已经跳过无效编码区。 无论哪种错误,都因为6个无效编码造成的。因此,只要出现上述两种情况之一,就必须调整。方法是把运算结果加6调整,即十进制调整修正。 44

① 累加器低4位大于9或辅助进位位Ac=1,则低4位加6修正。 ② 累加器高4位大于9或进位位Cy=1,则高4位加6修正。 十进制调整方法如下: ① 累加器低4位大于9或辅助进位位Ac=1,则低4位加6修正。 ② 累加器高4位大于9或进位位Cy=1,则高4位加6修正。 ③ 累加器高4位为9,低4位大于9,高4位和低4位分别加6修正 上述调整修正,是通过执行指令“DA A”来自动实现的。 【例3-4】 (A)=56H,(R5)=67H,把它们看作两个压缩的BCD数,进行BCD加法。执行指令: ADD A,R5 DA A 高4位和低4位分别大于9,所以“DA A”指令要分别加6,对结果修正。 45

结果为(A)=23H,Cy=1。 由上可见,56+67=123,结果正确。 46

从A的内容减去指定变量和进位标志Cy的值,结果存在A中。 如果位7需借位则Cy置1,否则Cy清0; 如果位3需借位则Ac置1,否则Ac清0; 5.带借位的减法指令 4条指令: SUBB A,Rn ; (A)-(Rn)-Cy→A,n =0~7 SUBB A,direct ; (A)-(direct)-Cy→A SUBB A,@Ri ; (A)-((Ri))-Cy→A, i =0,1 SUBB A,#data ; (A)-#data-Cy→A 从A的内容减去指定变量和进位标志Cy的值,结果存在A中。 如果位7需借位则Cy置1,否则Cy清0; 如果位3需借位则Ac置1,否则Ac清0; 如果位6借位而位7不借位,或者位7借位而位6不借位,则溢出标志位OV置“1”,否则OV清“0”。 47

【例3-5】 (A)=C9H,(R2)=54H,Cy=1,执行指令 SUBB A,R2 运算式为 结果: (A)=74H,Cy=0,Ac=0,OV=1(位6向位7借位)。 48

功能是指定的变量减1。若原来为00H,减1后下溢为FFH,不影响标志位(P标志除外)。 6.减1指令 DEC A ;(A)-1→A DEC Rn ;(Rn)-1→Rn,n=0~7 DEC direct ;(direct)-1→direct DEC @Ri ;((Ri))-1→(Ri),i =0,1 功能是指定的变量减1。若原来为00H,减1后下溢为FFH,不影响标志位(P标志除外)。 【例3-6】 (A)=0FH,(R7)=19H,(30H)=00H,(R1)=40H,(40H)=0FFH,执行指令 DEC R7 ;(R7)-1→R7 DEC 30H ;(30H)-1→30H DEC @R1 ;((R1))-1→(R1) 49

结果:(A)=0EH,(R7)=18H,(30H)=0FFH,(40H)=0FEH,P=1,不影响其他标志。 7.乘法指令 MUL AB ;A×B→BA 积的低字节在累加器A中,高字节在B中。如果积大于255,则OV置1,否则OV清0。Cy标志总是清0。 8.除法指令 DIV AB ;A/B→A(商),余数→B 商(为整数)存放在A中,余数存放在B中,且Cy和溢出标志位OV清“0”。 如果B的内容为0(即除数为0),则存放结果的A、B中的内容不定,并溢出标志位OV置1。 50

【例3-7】(A)=FBH,(B)=12H,执行指令 DIV AB 结果: (A)=0DH,(B)=11H,Cy=0,OV=0。 3. 4 【例3-7】(A)=FBH,(B)=12H,执行指令 DIV AB 结果: (A)=0DH,(B)=11H,Cy=0,OV=0。 3.4.3 逻辑操作类指令 1.累加器A 清“0”指令 CLR A 累加器A清0。不影响Cy、Ac、OV等标志位。 2.累加器A求反指令 CPL A 将累加器A的内容按位逻辑取反,不影响标志位。 51

3.左环移指令 RL A 功能是A向左循环移位,位7循环移入位0,不影响标志位,如图3-1所示。 图3-1 左环移操作 52

将累加器A的内容和进位标志位Cy一起向左环移一位,如 图3-2 所示。 4.带进位左环移指令 RLC A 将累加器A的内容和进位标志位Cy一起向左环移一位,如 图3-2 所示。 图3-2 带进位左环移指令的移位示意图

5.右环移指令 RR A 这条指令的功能是A的内容向右环移一位不影响其他标志位,如图3-3所示。 6.带进位右环移指令 RRC A A的内容和进位标志Cy一起向右环移一位,如图3-4所示。 图3-3 右环移操作 54 图3-4 带进位右环移操作

是将累加器A的高半字节(Acc.7~Acc.4)和低半字节(Acc.3~Acc.0)互换。 7.累加器半字节交换指令 SWAP A 是将累加器A的高半字节(Acc.7~Acc.4)和低半字节(Acc.3~Acc.0)互换。 【例3-8】(A)= 95H,执行指令 SWAP A 结果为 (A)=59H。 8.逻辑与指令 ANL A,Rn ;(A)∧(Rn)→A,n=0~7 ANL A,direct ;(A)∧(direct)→A ANL A,#data ;(A)∧#data→A ANL A,@Ri ;(A)∧((Ri))→A,i =0~1 ANL direct,A ;(direct)∧(A)→direct ANL direct,#data ;(direct)∧#data→direct 55

是在指定的变量之间以位为基础进行“逻辑与”操作,结果存放到目的变量所在的寄存器或存储器中。 【例3-9】 (A)=07H,(R0)=0FDH,执行指令 ANL A,R0 运算式为 56

是在所指定的变量之间执行位的“逻辑或”操作,结果存到目的变量寄存器或存储器中。 9.逻辑或指令 ORL A,Rn ;(A)∨(Rn)→A ,n =0~7 ORL A,direct ;(A)∨(direct)→A ORL A,#data ;(A)∨ #data→A ORL A,@Ri ;(A)∨((Ri))→A,i =0,1 ORL direct,A ;(direct)∨(A)→direct ORL direct,#data ;(direct)∨#data→direct 是在所指定的变量之间执行位的“逻辑或”操作,结果存到目的变量寄存器或存储器中。 57

【例3-10】 (P1)=05H,(A)=33H,执行指令 ORL P1,A 运算式为 结果:(P1)=35H。 58

功能是在所指定的变量之间执行以位的“逻辑异或”操作,结果存到目的变量寄存器或存储器中。 10.逻辑异或指令 XRL A,Rn ;(A)⊕(Rn)→A,n=0~7 XRL A,direct ;(A)⊕(direct)→A XRL A,@Ri ;(A)⊕((Ri))→A ,i =0,1 XRL A,#data ;(A)⊕#data→A XRL direct,A ;(direct)⊕(A)→direct XRL direct,#data ;(direct)⊕#data →direct 功能是在所指定的变量之间执行以位的“逻辑异或”操作,结果存到目的变量寄存器或存储器中。 59

【例3-11】 (A)=90H,(R3)=73H,执行指令 XRL A,R3 运算式为 结果: (A)=E3H。 60

3.4.4 控制转移类指令 1.长转移指令 LJMP addr16 3.4.4 控制转移类指令 1.长转移指令 LJMP addr16 指令执行时,把转移的目的地址,即指令的第二和第三字节分别装入PC的高位和低位字节中,无条件地转向addr16指定的目的地址:64KB程序存储器地址空间的任何位置。 2.相对转移指令 SJMP rel 无条件转移,rel为相对偏移量,是一单字节的带符号8位二进制补码数,因此程序转移是双向的。rel如为正,向地址增大的方向转移;rel如为负,向地址减小的方向转移。 61

执行时,在PC加2(本指令为2B)之后,把指令的有符号的偏移量rel加到PC上,并计算出目的地址。 编程时,只需写上目的地址标号, 相对偏移量由汇编程序自动计算。例如: LOOP: MOV A,R6          ……                   SJMP LOOP   …… 汇编时,跳到LOOP处的偏移量由汇编程序自动计算和填入。 3.绝对转移指令 AJMP addr11 62

指令双字节,格式如下: 指令提供11位地址A10~A0(即addr11),其中A10~A8则位于第1字节的高3位,A7~A0在第2字节。操作码只占第1字节的低5位。 指令构造转移目的地址:执行本指令,PC加2,然后把指令中的11位无符号整数地址addr11(A10~A0)送入PC.10~PC.0,PC.15~PC.11保持不变,形成新的16位转移目的地址。

需注意,目标地址必须与AJMP指令的下一条指令首地址的高5位地址码A15~A11相同,否则将混乱。所以,是2KB范围内的无条件跳转指令。 4.间接跳转指令 JMP @A+DPTR 单字节转移指令,目的地址由A中8位无符号数与DPTR的16位无符号数内容之和来确定。以DPTR内容为基址,A的内容作为变址。给A赋予不同值,即可实现多分支转移。

执行指令时,如条件满足,则转移;不满足,则顺序执行下一指令。转移目的地址在以下一条指令首地址为中心的256B范围内(-128~+127)。 5.条件转移指令 执行指令时,如条件满足,则转移;不满足,则顺序执行下一指令。转移目的地址在以下一条指令首地址为中心的256B范围内(-128~+127)。 JZ rel ;如果累加器内容为0,则执行转移 JNZ rel ;如果累加器内容非0,则执行转移 6.比较不相等转移指令 CJNE A,direct,rel CJNE A,#data,rel CJNE Rn,#data,rel CJNE @Ri,#data,rel

比较前两个操作数大小,如果值不相等则转移,并转向目的地址。 如果第一操作数(无符号整数)小于第二操作数(无符号整数),则进位标志位Cy置1,否则Cy清0。该指令的执行不影响任何一个操作数的内容。 7.减1不为0转移指令 把减1与条件转移两种功能合在一起。两条: DJNZ Rn,rel ;n =0~7 DJNZ direct,rel

用于控制程序循环。预先装入循环次数,以减1后是否为“0”作为转移条件,即实现按次数控制循环。 8.调用子程序指令 (1)长调用指令 LCALL addr16 可调用64KB范围内程序存储器中的任何一个子程序。执行时,先把PC加3获得下一条指令的地址(断点地址),并压入堆栈(先低位字节,后高位字节),堆栈指针加2。 接着把指令的第二和第三字节(A15~A8,A7~A0)分别装入PC的高位和低位字节中,然后从PC指定的地址开始执行程序。执行后不影响任何标志位。

(2)绝对调用指令 ACALL addr11 与AJMP指令类似,为兼容MCS–48的CALL指令而设,不影响标志位。格式如下: 2KB范围内的调用子程序的指令。子程序地址必须与ACALL指令下一条指令的16位首地址中的高5位地址相同,否则将混乱。

功能: 从堆栈中退出PC的高8位和低8位字节,把栈指针减2,从PC值处开始继续执行程序。不影响任何标志位。 9.子程序的返回指令 RET 执行本指令时 (SP)→PCH,然后(SP)-1→SP (SP)→PCL,然后(SP)-1→SP 功能: 从堆栈中退出PC的高8位和低8位字节,把栈指针减2,从PC值处开始继续执行程序。不影响任何标志位。 10.中断返回指令 RETI 与RET指令相似,不同处:该指令清除了中断响应时被置1的内部中断优先级寄存器的中断优先级状态,其他相同。

不进行任何操作,耗一个机器周期时间,执行(PC)+1→PC操作 3.4.5 位操作类指令 内部有一个位处理机,对应位操作指令。 11.空操作指令 NOP 不进行任何操作,耗一个机器周期时间,执行(PC)+1→PC操作 3.4.5 位操作类指令 内部有一个位处理机,对应位操作指令。 1.数据位传送指令 MOV C,bit MOV bit,C 把源操作数指定的位变量送到目的操作数指定处。一个操作数必须为进位标志,另一个可以是任何直接寻址位。不影响其他寄存器或标志位。

06H是位地址,20H是内部RAM字节地址。06H是内部RAM 20H字节位6的位地址。 例如: MOV C,06H ;(20H).6→Cy 06H是位地址,20H是内部RAM字节地址。06H是内部RAM 20H字节位6的位地址。 MOV P1.0,C ;Cy→P1.0 2.位变量修改指令 CLR C ;Cy位清0 CLR bit ;bit位清0 CPL C ;Cy位求反 CPL bit ;bit位求反 SETB C ;Cy位置1 SETB bit ;bit位置1

这组指令将操作数指定的位清0、求反、置1,不影响其他标志位。例如: CLR C ;Cy位清0 CLR 27H ;0→(24H).7位 CPL 08H ; →(21H).0位 SETB P1.7 ; P1.7位置1 3.位变量逻辑与指令 ANL C,bit ;bit∧Cy→Cy ANL C,/bit ; ∧Cy→Cy

第2条指令先对直接寻址位求反,然后与进位标志位C进行“逻辑与”运算,结果送回到位累加器中。 4.位变量逻辑或指令 ORL C,bit ORL C,/bit 第1条指令是直接寻址位与进位标志位Cy(位累加器)进行“逻辑或”运算,结果送回到进位标志位中。 第2条指令先对直接寻址位求反,然后与位累加器(进位标志位)进行“逻辑或”运算,结果送回到进位标志位中。

表3-2列出了按功能排列的全部的指令助记符及功能简要说明,以及指令长度、执行时间和指令代码(机器代码)。 5.条件转移类指令 JC rel ;如进位标志位Cy=1,则转移 JNC rel ;如进位标志位Cy=0,则转移 JB bit,rel ;如直接寻址位=1,则转移 JNB bit,rel ;如直接寻址位=0,则转移 JBC bit,rel ;如直接寻址位=1,转移,并把寻址位 ;清0 3.5 AT89S51指令汇总 表3-2列出了按功能排列的全部的指令助记符及功能简要说明,以及指令长度、执行时间和指令代码(机器代码)。

由于指令条数多,读者不宜死记硬背,应在程序的编写中多加练习,在实践中不断掌握和巩固常用的指令。读者应熟练地查阅表3-2,正确地理解指令的功能及特性并正确地使用指令。

76

77

78

79

80

82

3. 6 某些指令的说明 111条指令介绍完毕。一些细节问题,还需要说明。 1 3.6 某些指令的说明 111条指令介绍完毕。一些细节问题,还需要说明。 1. 关于并行I/O口的“读引脚”和“读锁存器”指令的区别 例如,当P1口的P1.0引脚外接一个发光二极管LED的阳极,LED的阴极接地。 若想查看一下单片机刚才向P1.0脚输出的信息是0还是1,不能直接从P1.0脚读取,因为单片机刚才向P1.0输出的信息如果是1的话,则LED导通点亮,此时P1.0引脚就为0电平,如果直接读引脚,结果显然错误。

正确的做法是读D锁存器的Q端状态,那里储存的才是前一时刻送给P1 正确的做法是读D锁存器的Q端状态,那里储存的才是前一时刻送给P1.0的真实值。就是说,凡遇“读取P1口前一状态以便修改后再送出”的情形,都应当“读锁存器”的Q端信息,而不是读取引脚的信息。 当P1口外接输入设备时,要想P1口引脚上反映的是真实的输入信号,必须要设法先让该引脚内部的场效应管截止才行(见图2-11),否则当场效应管导通时,P1口引脚上将永远为低电平,无法正确反映外设的输入信号。让场效应管截止,就是用指令给P1口的相应位送一个“1”电平,这就是为什么读引脚之前,一定要先送出1的原因。

指令“MOV C,P1.0”读的是P1.0脚,同样,指令“MOV A,P1”也是读引脚指令,读引脚指令之前一定要有向P1.0写“1”的指令。 而指令“CPL P1.0”则是“读锁存器”,也即“读—修改—写”指令,它会先读P1.0的锁存器的Q端状态,接着取反,然后再送到P1.0引脚上。而指令“ANL P1,A” 也是“读锁存器”命令。类似的“读—修改—写”指令举例如下: INC P1 XRL P3,A ORL P2,A ANL P1,A CPL P3.0

2. 关于操作数的字节地址和位地址的区分问题 如何区别指令中出现的字节变量和位变量? 例如指令“MOV C,40H”和指令“MOV A,40H”两条指令中源操作数“40H”都是以直接地址形式给出的,“40H” 是字节地址还是位地址?对于助记符相同指令,观察操作数就可看出。 显然前条指令中的“40H”肯定是位地址,因为目的操作数C是位变量。 后条指令的“40H” 是字节地址,因为目的操作数A是字节变量。

3. 关于累加器A与Acc的书写问题 累加器可写成A或Acc,区别是什么? Acc汇编后的机器码必有一个字节的操作数是累加器的字节地址E0H,A汇编后则隐含在指令操作码中。 例如: “INC A”的机器码,查表3-2是04H。 如写成“INC Acc”后,则成了“INC direct”的格式,再查表3-2,对应机器码为“05H E0H”。在对累加器A直接寻址和累加器A的某一位寻址要用Acc,不能写成A。

例如,指令“POP Acc”不能写成“POP A”; 指令“SETB Acc.0”,不能写成“SETB A.0”。 4.书写2位十六进制数据前要加“0” 经常遇到必须在某些数据或地址的前面多填一个“前导”0。否则汇编就通不过?这是汇编语言的严格性和规范性的体现。 由于部分十六进制数是用字母来表示的,而程序内的标号也常用字母表示,为了将标号和数据区分开,几乎所有的汇编语言都规定,凡是以字母开头(对十六进制数而言,就是A~F开头)的数字量,应当在前面添加一个数字0。

至于地址量,它也是数据量的一种,前面也应该添加“0”。 例如: MOV A,#0F0H ;“F0”以字母开头的数据量 MOV A,0F0H ;“F0”以字母开头的地址量 如不加“前导”0,就会把字母开头的数据量当作标号来处理,从而出错以及不能通过汇编。

3.7 8051汇编语言程序设计概述 程序是指令的有序集合。 单片机运行就是执行指令序列的过程。 编写这一指令序列的过程称为程序设计。 3.7.1 编程语言概述 常用的编程语言是汇编语言和高级语言。 1.汇编语言 用英文字符来代替机器语言,这些英文字符被称为助记符 汇编语言:用助记符表示的指令。 汇编语言源程序:用汇编语言编写的程序。

“汇编”:汇编语言源程序需转换(翻译)成为二进制代码表示的机器语言程序,才能识别和执行。 完成“翻译”的程序称为汇编程序。经汇编程序“汇编”得到的以“0”、“1”代码形式表示的机器语言程序称为目标程序。 优点:用汇编语言编写程序效率高,占用存储空间小,运行速度快,能编写出最优化的程序, 缺点:可读性差,离不开具体的硬件,是面向“硬件”的语言通用性差。 91

2.高级语言 不受具体“硬件”的限制,优点:通用性强,直观、易懂、易学,可读性好。 目前多数的51单片机用户使用C语言(C51)来进行程序设计,已公认为高级语言中高效简洁而又贴近51单片机硬件的编程语言。 将C语言向单片机上移植,始于20世纪80年代的中后期。 92

经过十几年努力,C51已成为单片机的实用高级编程语言。 尽管目前已有不少设计人员使用C51来进行程序开发,但在对程序的空间和时间要求较高的场合,汇编语言仍必不可少。 在这种场合下,可使用C语言和汇编语言混合编程。在很多需要直接控制硬件且对实时性要求较高的场合,则更是非用汇编语言不可。 掌握汇编语言并能进行程序设计,是学习和掌握单片机程序设计的基本功之一。 3.7.2 汇编语言语句和格式 两种基本语句:指令语句和伪指令语句。 93

(1)指令语句 已在第3章介绍。每一指令语句在汇编时都产生一个指令代码(机器代码),执行该指令代码对应着机器的一种操作。 (2)伪指令语句 是控制汇编(翻译)过程的一些控制命令。在汇编时没有机器代码与之对应。 下面介绍指令语句格式。伪指令语句将在3.7.3节介绍。

汇编语言语句是符合典型的汇编语言的四分段格式: 标号字段和操作码字段之间要有冒号“:”分隔; 操作码字段和操作数字段间的分界符是空格; 双操作数之间用逗号相隔; 操作数字段和注释字段之间的分界符用分号“;”。 任何语句都必须有操作码字段,其余各段为任选项。 95

【例4-1】下面是一段程序的四分段书写格式。 标号字段 操作码字段 操作数字段 注释字段 标号字段 操作码字段 操作数字段 注释字段 START:MOV A,#00H ;0→A       MOV R1,#10 ;10→R1 MOV R2,#00000011B ;03H→R2 LOOP: ADD A,R2 ;(A)+(R2)→A DJNZ R1,LOOP ;R1减1不为零,则跳LOOP处 NOP HERE: SJMP HERE 上述4个字段应该遵守的基本语法规则如下。 96

1.标号字段 语句所在地址的标志符号,才能被访问。如标号“START”和“LOOP”等。有关标号规定如下: (1)标号后必须跟冒号“:”。 (2)标号由1~8个ASCII码字符组成,第一个字符必须是字母。 (3)同一标号在一个程序中只能定义一次,不能重复定义。 (4)不能使用汇编语言已经定义的符号作为标号,如指令助记符、伪指令以及寄存器的符号名称等。 (5)标号的有无,取决于本程序中的其他语句是否访问该条语句。如无其他语句访问,则该语句前不需标号。 97

2.操作码字段 操作码字段规定了语句执行的操作,操作码是汇编语言指令中唯一不能空缺的部分。 3.操作数字段 指令的操作数或操作数地址。 在本字段中,操作数的个数因指令的不同而不同。通常有单操作数、双操作数和无操作数三种情况。 如果是多操作数,则操作数之间要以逗号隔开。

操作数表示时,几种情况需注意: (1)十六进制、二进制和十进制形式的操作数表示 多数情况,操作数或操作数地址是采用十六进制形式来表示的。则需加后缀“H”。 在某些特殊场合用二进制表示,需加后缀“B” 若操作数采用十进制形式,则需加后缀“D”,也可省略。 若十六进制操作数以字符A~F开头,需在它前面加一个 “0”,以便汇编时把它和字符A~F区别开。 99

(2)工作寄存器和特殊功能寄存器的表示 当操作数为工作寄存器或特殊功能寄存器时,允许用工作寄存器和特殊功能寄存器的代号表示。 例如,工作寄存器用R7~R0,累加器用A(或Acc)表示。另外,工作寄存器和特殊功能寄存器也可用其地址来表示,如累加器A可用其地址E0H来表示。 4.注释字段 用于解释指令或程序的含义,对可读性非常有用。 使用时须以分号开头,长度不限,一行写不下可换行书写,但注意也要以分号开头。 100

汇编时,遇到“;” 就停止“翻译”。因此,注释字段不会产生机器代码。 3. 7 汇编时,遇到“;” 就停止“翻译”。因此,注释字段不会产生机器代码。 3.7.3 伪指令 在汇编语言源程序中应有向汇编程序发出的指示信息,告诉它如何完成汇编工作,这是通过伪指令来实现。 伪指令不属于指令系统中的汇编语言指令,它是程序员发给汇编程序的命令,也称为汇编程序控制命令。 只有在汇编前的源程序中才有伪指令。 “伪”体现在汇编后,伪指令没有相应的机器代码产生。 伪指令具有控制汇编程序的输入/输出、定义数据和符号、条件汇编、分配存储空间等功能。 101

不同汇编语言的伪指令有所不同,但基本内容相同。 介绍常用的伪指令。 1.ORG(ORiGin)汇编起始地址命令 源程序的开始,用一条ORG伪指令规定程序的起始地址。如果不用ORG,则汇编得到的目标程序将从0000H地址开始。例如: ORG 2000H START: MOV A,#00H …… 即规定标号START代表地址为2000H开始。 在一源程序中,可多次用ORG指令,规定不同的程序段的起始地址。但是,地址必须由小到大排列,且不能交叉、

这种顺序是正确的。若按下面顺序的排列则是错误的,因为地址出现了交叉。 重叠。例如: ORG 2000H …… ORG 2500H ORG 3000H 这种顺序是正确的。若按下面顺序的排列则是错误的,因为地址出现了交叉。 103

2. END(END of Assembly)汇编终止命令 源程序结束标志,终止源程序的汇编工作。整个源程序中只能有一条END命令,且位于程序的最后。如果END出现在程序中间,其后的源程序,将不进行汇编处理。 3.EQU(EQUate)标号赋值命令 用于给标号赋值。赋值后,标号值在整个程序有效。 例如:TEST: EQU 2000H 表示TEST=2000H,汇编时,凡是遇到TEST时,均以2000H来代替。 104

4.DB(Define Byte)定义数据字节命令 用于从指定的地址开始,在程序存储器连续单元中定义字节数据。例如: ORG 2000H DB 30H,40H,24,"C","B" 汇编后 (2000H)=30H (2001H)=40H (2002H)=18H(十进制数24) (2003H)=43H(字符“C”的ASCII码) (2004H)=42H(字符“B”的ASCII码) 105

显然,DB功能是从指定单元开始定义(存储)若干字节,十进制数自然转换成十六进制数,字母按ASCII码存储。 5.DW(Define Word)定义数据字命令 该命令用于从指定的地址开始,在程序存储器的连续单元中定义16位的数据字。例如: ORG 2000H DW 1246H,7BH,10 汇编后 (2000H)=12H ;第1个字 (2001H)=46H (2002H)=00H ;第2个字

6.DS(Define Storage)定义存储区命令 从指定地址开始,保留指定数目的字节单元作为存储区,供程序运行使用。例如: (2003H)=7BH (2004H)=00H ;第3个字 (2005H)=0AH 6.DS(Define Storage)定义存储区命令 从指定地址开始,保留指定数目的字节单元作为存储区,供程序运行使用。例如: TABEL:DS 10 表示从TABEL代表的地址开始,保留10个连续的地址单元。又例如: ORG 2000H DS 10 H 表示从2000H地址开始,保留16个连续地址单元。 107

注意:DB、DW和DS命令只能对程序存储器有效,不能对数据存储器使用。 7.BIT 位定义命令 用于给字符名称赋以位地址,位地址可以是绝对位地址,也可是符号地址。例如: QA BIT P1.6 功能是把P1.6的位地址赋给变量QA。 3.7.4 汇编语言源程序的汇编 “汇编”----可分为手工汇编和机器汇编两类。 108

1.手工汇编 通过查指令的机器代码表(表3-2),逐个把助记符指令“翻译”成机器代码,再进行调试和运行。 手工汇编遇到相对转移偏移量的计算时,较麻烦,易出错,只有小程序或受条件限制时才使用。实际中,多采用“汇编程序”来自动完成汇编。 109

2. 机器汇编 用微型计算机上的软件(汇编程序)来代替手工汇编。 在微机上用编辑软件进行源程序编辑,然后生成一个ASCII码文件,扩展名为 “.ASM”。在微机上运行汇编程序,译成机器码。 机器码通过微机的串口(或并口)传送到用户样机(或在线仿真器),进行程序的调试和运行。 有时,在分析某些产品的程序的机器代码时,需将机器代码翻译成汇编语言源程序,称为“反汇编”。 110

【例3-13】 表3-3是一段源程序的汇编结果,可查表3-2,手工汇编,来验证下面的汇编结果是否正确。机器码从1000H单元开始存放。 111

3. 8 8051汇编语言程序设计举例 介绍常用的汇编语言程序的设计。 3. 8 3.8 8051汇编语言程序设计举例 介绍常用的汇编语言程序的设计。 3.8.1 子程序的设计 将那些需多次应用的、完成相同的某种基本运算或操作的程序段从整个程序中独立出来,单独编成一个程序段,需要时进行调用。这样的程序段称为子程序。 优点:采用子程序可使程序结构简单,缩短程序的设计时间,减少占用的程序存储空间。 子程序在程序设计中非常重要,读者应熟练掌握子程序的设计方法。 112

主程序调用子程序,是通过调用指令来实现。有两条子程序调用指令: 1.子程序的设计原则和应注意的问题 编写子程序应注意以下问题: 子程序的入口地址,前必须有标号。 主程序调用子程序,是通过调用指令来实现。有两条子程序调用指令: (1)绝对调用指令ACALL addr11。双字节,addr11指出了调用的目的地址,PC中16位地址中的高5位不变,被调用的子程序的首地址与绝对调用指令的下一条指令的高5位地址相同,即只能在同一个2KB区内。 (2)长调用指令LCALL addr16。三字节,addr16为直接调用的目的地址,子程序可放在64KB程序存储器区任意位置。 113

子程序结构中必须用到堆栈,用来进行断点和现场的保护。 子程序返回主程序时,最后一条指令必须是RET指令,功能是把堆栈中的断点地址弹出送入PC指针中,从而实现子程序返回后从主程序断点处继续执行主程序。 子程序可以嵌套,即主程序可以调用子程序,子程序又可以调用另外的子程序。 114

2.子程序的基本结构 典型的子程序的基本结构如下: MAIN: …… ;MAIN为主程序入口标号 …… LCALL SUB ;调用子程序SUB     …… 子程序 SUB: PUSH PSW ;现场保护 PUSH Acc POP Acc ;现场恢复,注意要先进后出 POP PSW RET ;最后一条指令必须为RET 子程序 子程序处理程序段 115

注意:上述子程序结构中,现场保护与现场恢复不是必需的,要根据实际情况而定。 3.8.2 查表程序设计 查表程序是一种常用程序,避免复杂的运算或转换过程,可完成数据补偿、修正、计算、转换等各种功能,具有程序简单、执行速度快等优点。 查表是根据自变量x,在表格寻找y,使y =f(x)。单片机中,数据表格存放于程序存储器内,在执行查表指令时,发出读程序存储器选通脉冲 。两条极为有用的查表指令如下: (1)MOVC A,@A+DPTR (2)MOVC A,@A+PC 116

两条指令的功能完全相同,具体使用有差别。 指令“MOVC A,@A+DPTR” 把A中内容与DPTR中的内容相加,结果为某一程序存储单元的地址,然后把该地址单元的内容送到A中。 指令“MOVC A,@A+PC” ,PC的内容与A的内容相加后所得的数作为某一程序存储器单元的地址,根据地址取出程序存储器相应单元中的内容送到累加器A,指令执行后,PC的内容不发生变化,仍指向该查表指令的下一条指令。 优点:在于预处理较少且不影响其他特殊功能寄存器的值,不必保护其他特殊功能寄存器。 117

缺点:在于该表格只能存放在这条指令的地址X3X2X1X0以下00H~FFH之中,即只能存放在地址范围X3X2X1X0+1~X3X2X1X0+100H中,这就使得表格所在的程序空间受到了限制。 1. x和y均为单字节数的查表程序设计 下面举例说明查表指令的用法以及计算偏移量时应该注意的问题。

【例3-14】 设计一子程序,功能是根据累加器A中的数x(0~9之间)查x的平方表y,根据x的值查出相应的平方y。本例中的x和y均为单字节数。    地 址 子程序 Y3Y2Y1Y0 ADD A,#01H Y3Y2Y1Y0+2 MOVC A,@A+PC Y3Y2Y1Y0+3 RET Y3Y2Y1Y0+4 DB 00H,01H,04H,09H,10H DB 19H,24H,31H,40H,51H ;数0~9的平方表 119

第一条指令“ADD A,#01H”的作用是A中的内容加上 “01H”,“01H” 为查表的偏移量,即查表指令与平方表之间的所有指令所占的字节数。这里的指令为“RET”,为单字节指令。加上“01H”后,可保证PC指向表首,累加器A中原来的内容反映的仅是从表首开始向下查找多少个单元。 在进入程序前,A的内容在00~09H之间,如A中的内容为02H,它的平方为04H,可根据A的内容查出x的平方 由于 “MOVC A,@A+DPTR”不必计算偏移量,一般情况下,大多使用该指令。不必计算偏移量,优点是表格可以设在64KB程序存储器空间内的任何地方,而不像“MOVC A,@A+PC”那样只设在PC下面的256个单元中,所以使用较方便。 120

如果DPTR已被使用,则在查表前必须保护DPTR,且结束后恢复DPTR,【例3-14】可改成如下形式:   PUSH DPH ;保存DPH PUSH DPL ;保存DPL    MOV DPTR,#TAB1 MOVC A,@A+DPTR POP DPL ;恢复DPL POP DPH ;恢复DPH RET TAB1: DB 00H,01H,04H,09H,10H ;平方表    DB 19H,24H,31H,40H,51H 121

2. x为单字节数y为双字节数的查表程序设计 实际查表,有时x为单字节数,y为双字节数。来看下例。 【例3-15】有一巡回检测报警装置,需对16路(x)输入进行检测,每路有一个最大允许值(y),为双字节数。需根据测量的路数(x),查表找出对应该路的最大允许值(y),看输入值是否大于最大允许值,如果大于就报警。 取路数为x(0≤x≤15),y为最大允许值,放在表格中。设进入查表程序前,假设路数x已放于R2中,查表后该路的最大允许值y放于R3R4中。查表的程序如下: 122

123

表格长度不能超过256B,且表格只能存放于“MOVC A,@A+PC”指令以下的256个单元中,如需把表格放在程序存储器空间的任何地方,应使用指令“ MOVC A,@A+DPTR”。 【例3-16】以AT89S52为核心的温度控制器,温度传感器输出的电压与温度为非线性关系,传感器输出的电压已由A/D转换为10位二进制数。测得的不同温度下的电压值数据构成一个表,表中温度值为y(双字节无符号数),x(双字节无符号数)为电压值数据。设测得电压值x放入R2R3中,根据电压值x,查找对应的温度值y,仍放入R2R3中。参考程序: 124

125

由于使用了指令“MOVC A,@A+DPTR”,表TAB2可放入64KB程序存储器空间任何位置,表格的长度可大于256B。 如果表格的长度超过256B,且需要把表格放在64KB程序存储器空间的任何地方,且应使用指令“MOVC A,@A+DPTR”,并对DPH、DPL进行运算,求出表格的目的地址。 3.x和y均为双字节数的查表程序设计 下面来看一个x与y均为双字节数的查表例子。 【例3-16】在一个以AT89S52为核心的温度控制器中,温度传感器输出的电压x与温度值为非线性关系。假设温度传感器输出的电压值x(已由A/D转换器转换为10位二进制数,并存入 126

R2R3中),查找到对应的温度值y,仍放入R2R3中。温度值表的首地址为TAB2,表中元素为y(双字节无符号数)。 参考程序如下: 127

128

3.8.3 分支转移程序设计 分为无条件转移和有条件转移。 无条件分支转移程序很简单,不讨论。有条件分支转移程序按结构类型来分,又分为单分支选择结构和多分支选择结构。 1.单分支选择结构 仅有两个出口,两者选一。一般根据运算结果的状态标志,用条件判跳指令来选择并转移。 【例3-17】 求单字节有符号数的二进制补码 正数补码是其本身,负数补码是其反码加1。因此,应首先判被转换数的符号,负数进行转换,正数本身即为补码。 129

设二进制数放在A中,其补码放回到A中,框图如图3-5所示。参考程序如下: 130

图3-5 求单字节有符号二进制数补码的框图

此外,单分支选择结构还有图3-6、图3-7所示的几种形式。 图3-6 单分支选择结构2 图3-7 单分支选择结构3 132

2.多分支选择结构 当程序的判别部分有两个以上的出口时,为多分支选择结构。有两种形式,如图3-8和图3-9所示。 图3-8 多分支选择结构1 图3-9 多分支选择结构2 133

指令系统提供了非常有用的两种多分支选择指令: 间接转移指令 JMP @A+DPTR 比较转移指令 CJNE A,direct,rel CJNE A,#data,rel CJNE Rn,#data,rel CJNE @Ri,#data,rel 间接转移指令“JMP @A+DPTR”由数据指针DPTR决定多分支转移程序的首地址,由A的内容选择对应分支。 4条比较转移指令CJNE能对两个欲比较的单元内容进行比较,当不相等时,程序实现相对转移;若两者相等,则顺序往下执行。 134

简单的分支转移程序的设计,常采用逐次比较法,就是把所有不同的情况一个一个地进行比较,发现符合就转向对应的处理程序。缺点是程序太长,有n种可能的情况,就需有n个判断和转移。 【例3-18】 求符号函数的值。符号函数定义如下: X存放在40H单元,Y存放在41H单元,如图3-7所示。 135

程序如下: 136

【例3-19】 根据寄存器R2的内容,转向各个处理程序PRGX(X=0~n)。 实际中,经常遇到图3-9的分支转移程序设计,典型例子就是当单片机系统中的键盘按下时,就会得到一个键值,根据不同的键值,跳向不同的键处理程序入口。此时,可用直接转移指令(LJMP或AJMP指令)组成一个转移表,然后把该单元的内容读入累加器A,转移表首地址放入DPTR中,再利用间接转移指令实现分支转移。 【例3-19】 根据寄存器R2的内容,转向各个处理程序PRGX(X=0~n)。 (R2)=0,转PRG0 (R2)=1,转PRG1 …… (R2)=n,转PRGn 137

程序如下: 138

R2中的分支转移参量乘3是由于长跳转指令LJMP要占3个单元。 3. 8 139

1.循环程序的结构 主要由以下四部分组成。 (1)循环初始化 完成循环前的准备工作。例如,循环控制计数初值的设置、地址指针的起始地址的设置、为变量预置初值等。 (2)循环处理 完成实际的处理工作,反复循环执行的部分,故又称循环体。 (3)循环控制 在重复执行循环体的过程中,不断修改循环控制变量,直到符合结束条件,就结束循环程序的执行。 140

循环结束控制方法分为循环计数控制法和条件控制法。 (4)循环结束 这部分是对循环程序执行的结果进行分析、处理和存放。 2.循环结构的控制 分为循环计数控制结构和条件控制结构。图3-10是计数循环控制结构,图3-11是条件控制结构。 141

图3-10 计数循环控制结构 图3-11 条件控制结构 142

依据计数器的值来决定循环次数,一般为减1计数器,计数器减到“0”时,结束循环。计数器初值在初始化设定。 (1)计数循环控制结构 依据计数器的值来决定循环次数,一般为减1计数器,计数器减到“0”时,结束循环。计数器初值在初始化设定。 MCS—51指令系统提供了功能极强的循环控制指令: DJNZ Rn,rel ;以工作寄存器作控制计数器 DJNZ direct,rel ;以直接寻址单元作控制计数器 例如,计算n个数据的和,计算公式为 。 如直接按公式编写程序,则n=100时,需编写连续的100次加法。这样程序将太长,并且n可变时,将无法编写出程序。 143

公式要改写为用程序实现的形式,用下式表示 程序框图见图3-12。 图3-12 求数据和的程序框图 144

【例3-20】 求n个单字节无符号数xi的和,xi按i顺序存放在AT89S51单片机内部RAM从50H开始的单元中,n放在R2中,和(双字节)放在R3R4中。 程序如下: 145

用寄存器R2作为计数控制变量,R0作为变址单元,用它来寻址xi。 一般来说,循环工作部分中的数据应该用间接方式来寻址,如这里用:ADD A,@R0 计数控制只有在循环次数已知的情况下才适用。循环次数未知,不能用循环次数来控制,往往需要根据某种条件来判断是否应该终止循环。 146

(2)条件控制结构 结构见图3-11。循环控制中,设置一个条件,判是否满足该条件,如满足,则循环结束。如不满足该条件则循环继续。 【例3-21】 一串字符,依次存放在内部RAM从30H单元开始的连续单元中,字符串以0AH为结束标志,测试字符串长度。 采用逐个字符依次与“0AH”比较(设置的条件)的方法。设置一个累计字符串长度的长度计数器和一个用于指定字符串指针。 如果字符与“0AH”不等,则长度计数器和字符串指针都加1;如果比较相等,则表示该字符为“0AH”,字符串结束,计数器值就是字符串的长度。 程序如下: 147

上面两例都是在一个循环程序中不再包含其他循环程序,则称该循环程序为单循环程序。如果一个循环程序中包含了其他循环程序,则称为多重循环程序。 最常见的多重循环是由DJNZ指令构成的软件延时程序,是常用程序之一。 148

【例3-22】 50ms延时程序。 软件延时程序与指令执行时间有很大的关系。在使用12MHz晶振时,一个机器周期为1µs,执行一条DJNZ指令的时间为2µs。可用双重循环方法的延时50ms程序: 149

以上延时程序不是太精确,如把所有指令的执行时间计算在内,它的延时时间为 [1+(1+250+2)× 200+2]µs=50 以上延时程序不是太精确,如把所有指令的执行时间计算在内,它的延时时间为 [1+(1+250+2)× 200+2]µs=50.603ms 如要求比较精确的延时,应对上述程序进行修改,才能达到较为精确的延时时间。但要注意,用软件实现延时程序,不允许有中断,否则将严重影响定时的准确性。 对于延时更长的时间,可采用多重的循环,如1s延时,可用三重循环。 150