目录
功能:通知汇编程序从当前ROM地址开始,保留一个字 节或字节串的存储单元,并存入DB后的数据。
注意:项或项表可以是一个字节,用逗号隔开的字节串 或括在单引号中的ASCII字符串。
4.1 伪指令
伪指令不是真正的指令,无对应的机器码,在汇编时不产 生目标程序,只是用来对汇编过程进行某种控制。
有8个伪指令: ORG ,END ,EQU , DATA , DB , DW , DS , BIT
ORG (Origin) 汇编起始命令
格式:ORG 16位地址
例如:ORG 2000H
功能:规定该伪指令后面程序的汇编地址,即汇编后生 成目标程序存放的起始地址。
使用实例: ORG 2000H START:MOV A,#64H ┇
规定了标号START的地址是2000H,又规定了汇编后 的第一条指令码从2000H开始存放。
ORG可以多次出现,重新定位下一条指令的存放地址。
END (End) 汇编结束命令
格式:END
功能:通知汇编程序结束汇编。在END之后所有的汇编 指令均不予以处理。
使用实例: ORG 100H
START:MOV A,#64H ┇
LJMP START
END
MOV A ,#00H
EQU ( Equate )赋值命令
格式:字符名称 EQU 项(数或汇编符号)
例如: X EQU 30H
AA EQU R1
功能:把“项”赋给“字符名称” 。
注意:字符名称不等于标号(其后没有冒号)。其中的 项,可以是数,也可以是汇编符号。EQU赋值过的符号 名可以用作数据、代码地址、位地址或一个立即数。可 以是8位的,也可以是16位的。
ATA (Data) 数据、地址赋值命令
格式:字符名称 DATA 表达式
例如:FRE DATA 1200
X DATA 30
Y DATA FRE/X
功能:与EQU类似,但有以下差别:
1、EQU定义的字符名必须先定义后使用,而DATA定义的 字符名可以后定义先使用。
2、用EQU伪指令可以把一个汇编符号赋给一个名字,而 DATA只能把数据赋给字符名。
3、DATA语句可以把一个表达式的值赋给字符名称,其中 的表达式应是可求值的。DATA伪指令在程序中常用来定义 数据地址。
DB (Define Byte) 定义字节命令
格式:DB 8位项或项表
例如:DB 15
功能:通知汇编程序从当前ROM地址开始,保留一个字 节或字节串的存储单元,并存入DB后的数据。
注意:项或项表可以是一个字节,用逗号隔开的字节串 或括在单引号中的ASCII字符串。
DW (Define Word)定义字命令
格式:DW 16位数据项或项表
例如:DW 1289H
功能:把DW后的16位数据项或项表从当前地址连续存放 。每项数值为16位二进制数,高8位先放,低8位后存放。 DW常用于定义一个地址表。
经汇编后,有: (1500H)=72H (1501H)=34H (1502H)=00H (1503H)=8AH (1504H)=00H (1505H)=10H
DS ( Define Storage )定义存储空间命令
格式:DS 表达式
例如:DS 08H
功能:在汇编时,从指定地址开始保留DS之后表达式的值所 规定的存储单元,以备后用。
注意:DB、DW和DS都只对程序存储器(ROM)起作用, 它们不能对数据存储器(RAM)进行初始化。
使用实例5: ORG 1000H DS 08H DB 30H,8AH 经汇编后,有: (1000H)=保留 (1001H)=保留 (1002H)=保留 (1003H)=保留 (1004H)=保留 (1005H)=保留 (1006H)=保留 (1007H)=保留 (1008H)=30H (1009H)=8AH
BIT (Bit)位地址符号命令
格式:字符名 BIT 位地址
功能:把BIT后的位地址值赋给字符名。其中字符名不 是标号,其后没有冒号,但它是必须的。
例6: A1 BIT P1.0 A2 BIT 02H 经汇编后,P1口第0位的位地址90H就赋给了A1, 而A2的值则为02H。
4.2 编程的步骤、方法和技巧
1、分析问题 2、确定算法 3、画程序流程图 4、编写程序
1、分析问题
对需要解决的问题进行分析,以求对问题有正确的理解。 解决问题的任务是什么?
工作过程? 现有的条件,已知数据,对运算的精度和速度方面的要求? 设计的硬件结构是否方便编程?
2、确定算法
算法是如何将实际问题转化成程序模块来处理。
在编程以前,先要对几种不同的算法进行分析、比较,找 出最适宜的算法。
3、画程序流程图
程序流程图是使用各种图形、符号、有向线段等来说明 程序设计过程的一种直观的表示。 流程图步骤分得越细致,编写程序是也就越方便。
画流程图是程序结构设计时采用的一种重要手段。
一个系统软件有总的流程图(主程序框图)和局部的流 程图。
流程图常采用的图形和符号。
4、编写程序
用89C51汇编语言编写的源程序行(一条语句)包括 四个部分,也叫四个字段:
〔标号:〕〔操作码〕 〔操作数〕 ;〔注释〕
每个字段之间要用分隔符分隔,而每个字段内部不能 使用分隔符。可以用作分隔符的符号包括: 空格“ ” 、冒号“ : ” 、逗号“ , ” 、分号“ ; ”
例1:LOOP:MOV A,#00H;立即数00H→A
4.2.1 编程步骤
4、编写程序
1)标号
标号是用户定义的符号地址。
一条指令的标号是该条指令的符号名字,标号的值是汇 编这条指令时指令的地址。
标号由以英文字母开始的1~8个字母或数字组成,以 冒号“ : ”结尾。
标号可以由赋值伪指令赋值,如果没有赋值,汇编程序 就把存放该指令目标码第一字节的存储单元的地址赋给 该标号,所以,标号又叫指令标号。
2)操作码
对于一条汇编语言指令,操作码是必不可少的。 它用一组字母符号表示指令的操作码。在89C51中, 由它自己的指令助记符组成。
3)操作数
汇编语言指令可能要求或不要求操作数,所以这一字段 可能有也可能没有。
若有两个操作数,操作数之间用逗号“ , ”分开。
操作数字段的内容复杂多样,它包括的内容有: (1)工作寄存器名:由PSW.3和PSW.4规定的当前工作寄存器区中的R0~ R7都可以出现在操作数字段中。 (2)特殊功能寄存器名:21个SFR的名字都可以作为操作数使用。 (3)标号名: 赋值标号—由汇编指令EQU等赋值的标号。 指令标号—指令标号指示的指令的第一字节地址是该标号的值。 (4)常数:汇编语言指令允许以各种数制表示常数,总以数字开头。 二进制(B)、十进制、十六进制(H),若常数以字符开头,前面加0。 (5)$:用来表示程序计数器的当前值。如:JNB TF0,$ (6)表达式:汇编时,计算出表达式的值填入目标码。如:MOV A,SUM+1
4)注释
注释部分不是汇编语言的功能部分,只是用于改善程序 的可读性。
良好的注释是汇编语言程序编写中的重要组成部分。
4.2.2编程的方法和技巧
1、模块化的程序设计方法 1)程序功能模块化的优点
单个模块结构的程序功能单一,易于编写、调试和修改。
便于分工,从而可使多个程序员同时进行程序的编写和调 试工作,加快软件研制进度。 程序可读性好,便于功能扩充和版本升级。
对程序的修改可局部进行,其它部分可以保持不变。
对于使用频繁的子程序可以建立子程序库,便于多个模块 调用。
1、模块化的程序设计方法 2)划分模块的原则 每个模块应具有独立的功能,能产生一个明确的结果, 即单模块的功能高内聚性。
模块之间的控制耦合应尽量简单,数据耦合应尽量少, 即模块间的低耦合性。控制耦合是指模块进入和退出的 条件及方式,数据耦合是指模块间的信息交换方式、交 换量的多少及交换频繁程度。
模块长度适中。模块含20~100条指令较合适。
2、编程技巧 尽量采用循环结构和子程序。
尽量少用无条件转移指令。
对于通用的子程序,除了用于存放子程序入口参数的寄 存器外,子程序中用到的其他寄存器的内容应压入堆栈 (返回前再弹出),即保护现场。
在中断处理程序中,除了要保护处理程序中用到的寄存 器外,还要保护标志寄存器。
用累加器传递入口参数或返回参数比较方便,在子程序 中,一般不必把累加器内容压入堆栈。
汇编语言程序的基本结构
1、顺序程序 2、分支程序 3、循环程序 4、子程序
1、顺序程序
顺序程序是最简单的程序结构,也称直线程序。 程序按顺序一条一条地执行指令。无分支、循环,也 不调用子程序。
双字节加法程序段。
设被加数存放于片内RAM的addr1(低位字节)和addr2(高位字 节),加数存放于adddr3(低位字节)和addr4(高位字节),运算结果和 数存于addr1和addr2中。其程序段如下: 这里将A原内容进栈保护,如果原R0和R1内容有用,则亦须进栈保护。
拆字。
将片内RAM 20H单元的内容拆成两段,每段四位。并将它们分别 存入21H与22H单元中。程序如下:
16位数求补。
设16位二进制数在R1和R0中,求补结果存于R3和R2中。程序如下:
2、分支程序
程序分支是通过条件转移指令实现的,即根据条件对程序 的执行进行判断:满足条件则进行程序转移,不满足条件 就顺序执行程序。
分支程序又分为单分支和多分支结构。
单分支: 在89C51指令系统中,通过条件判断实现单分 支程序转移的指令有:JZ、JNZ、CJNE、DJNZ等。此 外还有以位状态作为条件进行程序分支的指令,如JC、 JNC、JB、JNB、JBC等。使用这些指令可以完成0、1 ,正、负,以及相等、不相等作为各种条件判断依据的程 序转移。
多分支程序: 是首先把分支程序按序号排列,然后按序号 值进行转移。
128种分支转移程序。
功能:根据入口条件转移到128个目的地址。 入口:(R3)=转移目的地址的序号00H~7FH。 出口:转移到相应子程序入口。
说明:此程序要求128个转移目的地址(ROUT00 ~ROUT7F)必须驻留 在与绝对转移指令AJMP相同的一个2KB存储区内。 RL指令对变址部分乘以2,因为每条AJMP指令占两个字节。
求大数程序。
存放于addr1和addr2中的两个无符号二进制数,求其中的大数并 存于addr3中,其程序流程如图4-2所示,程序段如下:
求大数程序。
可见,CJNE 是一条 功能极强的比较指令,它 可指出两数的大、小和相 等。通过寄存器和直接寻 址方式,可派生出很多条 比较指令。同样,它也属 于相对转移。
比较无符号数大小,存较小数程序。
片内RAM的ONE和TWO两个单元中存有两个无符号数,将两个数中的 小者存入30H单元。程序如下:
分段函数程序。
汇编语言程序的基本结构
4、循环程序
循环程序是最常见的程序组织方式。在程序运行时,有时 需要连续重复执行某段程序,可以使用循环程序。 这种设计方法可以简化程序,其一般结构包括四部分:
1)置循环初值 2)循环体(循环工作部分) 3)修改控制变量 4)循环控制部分
1)置循环初值
对于循环程序中所使用的工作单元,在循环开始时应置 初值。例如,工作寄存器设置计数初值,累加器A清0, 以及设置地址指针、长度等。
2)循环体(循环工作部分)
重复执行的程序段部分,分为循环工作部分和循环控制 部分。循环控制部分每循环一次,检查结束条件,当满 足条件时,就停止循环,往下继续执行其他程序。
3)修改控制变量
在循环程序中,必须给出循环结束条件。常见的是计数循 环,当循环了一定的次数后,就停止循环。 一般用一个工作寄存器Rn作为计数器,对该计数器赋初值 作为循环次数。每循环一次,计数器的值减1,即修改循 环控制变量,当计数器的值减为0时,就停止循环。
4)循环控制部分
根据循环结束条件,判断是否结束循环。
89C51可采用DJNZ指令自动修改控制变量并结束循环。
循环组织方式如下图所示
软件延时程序
当单片机时钟确定后,每条指令的指令周期是确定的,在指令表中已 用机器周期表示出来。因此,根据程序执行所用的总的机器周期数,可以 较准确地计算程序执行完所用的时间。软件延时是实际经常采用的一种短 时间定时方法。
1) 采用循环程序进行软件延时子程序
2) 采用双重循环的延时子程序
计算延时时间t: N=1+(1+2×255+2)×250+1+1+2=128255个机器周期(T)
如果f=6MHz,T=2μs 则t=N×T=128255×2=256510μs=256.51ms
调整R0和R1中的参数,可改变延时时间。如果需要加长延时时间,则可增 加循环嵌入。 在延时时间较长,不便多占用CPU时间的情况下,一般采用定时器方法。 若需要延时更长时间,则可采用多重的循环,如1s延时可用3重循环,而 用7重循环可延时几年!
例9:多字节无符号数加法程序
设被加数低字节地址存R0中,加数低字节地址存R1中,字节数存 R3中。相加的结果依次存于原被加数单元。程序如下:
例10:搜索最大值程序。
从片内RAM的BLOCK单元开始有一个无符号数据块,其长度存于LEN 单元中,试求出其中最大的。比较和交换交替进行。第一个数作为基 准和第二个数比较:基准数大,不交换;基准数小,交换。程序如下: