1、第四章 MCS-51汇编语言程序设计,4.1 机器语言和汇编语言 指令系统:一台计算机所能识别、执行的指令的集合就是它的指令系统。 机器语言:指令系统是一套控制计算机执行操作的二进制编码,称为机器语言。机器语言指令是计算机唯一能识别和执行的指令。 汇编语言:指令系统是利用指令助记符来描述的,称为汇编语言。 计算机的指令系统一般都是利用汇编语言描述的,是由计算机硬件设计所决定的。指令系统没有通用性。 单片机一般是空机,未含任何系统软件。因此在第一次使用前,必须对其进行编程,4.1 单片机程序设计语言概述,高级语言:BASIC、PL/M、C语言,应用最广泛的是C语言,优点: 可以大大提高单片机应用
2、系统研制开发的效率 易移植,有助于打破不同单片机之间的界限,缺点:生成的目标程序代码较长,导致程序运行速度较慢,支持写入单片机或仿真调试的目标程序有两种文件格式:BIN文件和HEX文件。BIN文件是由编译器生成的二进制文件,是程序的机器码;HEX文件是由INTEL公司定义的一种格式,这种格式包括地址、数据和校验码,并用ASCII码来存储,可供显示和打印。HEX文件需通过符号转换程序OHS51进行转换,两种语言的操作过程见图4.1。现在通常采用uV2集成开发环境可将A51汇编、C51编译、L51连接、OHS51转换一次完成。,4.1.2 汇编语言指令格式与伪指令,1常用单位与术语 位(bit):
3、位是计算机所能表示的最小的、最基本的数据单位,位通常是指一个二进制位。 字节(Byte):一个连续的8位二进制数码称为一个字节,即1Byte=8bit。 字(Word):通常由16位二进制数码组成,即1Word=2Byte。 字长:字长是指计算机一次处理二进制数码位的多少。MCS-51型单片机是8位机,所以说它的字长为8位。 MCS-51系列单片机都是以Intel公司最早的典型产品8051为核心,增加了一定的功能部件后构成的。本章以8051为主介绍MCS-51系列单片机 。,2汇编语言指令格式,指令格式:指令的表示方式称为指令格式,它规定了指令的长度和内部信息的安排。完整的指令格式如下:标号:
4、 操作码 操作数 ,操作数 ;注释其中: 项是可选项。标号:指本条指令起始地址的符号,也称为指令的符号地址。代表该条指令在程序编译时的具体地址。操作码:又称助记符,它是由对应的英文缩写构成的,是指令语句的关键。它规定了指令具体的操作功能,描述指令的操作性质,是一条指令中不可缺少的内容。操作数:它既可以是一个具体的数据,也可以是存放数据的地址。注释:注释也是指令语句的可选项,它是为增加程序的可读性而设置的,是针对某指令而添加的说明性文字,不产生可执行的目标代码。,伪指令(也称为汇编程序的控制命令)是程序员发给汇编程序的命令,用来设置符号值、保留和初始化存储空间、控制用户程序代码的位置。 伪指令只
5、出现在汇编前的源程序中,仅提供汇编用的某些控制信息,不产生可执行的目标代码,是CPU不能执行的指令。(1)定位伪指令ORG 格式:ORG n 其中:n通常为绝对地址,可以是十六进制数、标号或 表达式。 功能:规定编译后的机器代码存放的起始位置。 在一个汇编语言源程序中允许存在多条定位伪指令,但 每一个n值都应和前面生成的机器指令存放地址不重叠。 例如程序:ORG1000H START:MOVA,#20H MOVB,#30H ,3伪指令,(2)结束汇编伪指令END 格式:标号: END 表达式 功能:放在汇编语言源程序的末尾,表明源程序的汇编到此结束,其后的任何内容不予理睬。,(3)赋值伪指令E
6、QU 格式:字符名称x EQU 赋值项n 功能:将赋值项n的值赋予字符名称x。程序中凡出现该字符名称x就等同于该赋值项n,其值在整个程序中有效。赋值项n可以是常数、地址、标号或表达式。在使用时,必须先赋值后使用。 “字符名称”与“标号”的区别是“字符名称”后无冒号,而“标号”后面有冒号。,(4)定义字节伪指令DB 格式:标号: DB x1, x2, xn 功能:将8位数据(或8位数据组)x1, x2, xn顺序存放在从当前程序存储器地址开始的存储单元中。xi可以是8位数据、ASCII码、表达式,也可以是括在单引号内的字符串。两个数据之间用逗号“,”分隔。 xi为数值常数时,取值范围为00HFF
7、H。xi为ASCII码时,要使用单引号,以示区别。xi为字符串常数时,其长度不应超过80个字符。,例如:DB -2,-4,-6,10,11,17把6个数转换为十六进制表示(即FEH,0FCH,0FAH,0AH,0BH,11H),并连续存放在6个程序存储单元中,例如:存放数码管显示的十六进制数的字形码,可使用 多条DB命令定义:,(5)定义双字节伪指令DW 格式:标号: DW x1, x2, xn 功能:将双字节数据或双字节数据组顺序存放在从标号指定地址单元开始的存储单元中。其中,xi为16位数值常数,占两个存储单元,先存高8位(存入低位地址单元中),后存低8位(存入高位地址单元中)。,例如:,
8、注意:DB和DW定义的数表,数的个数不得超过80个。如数据的数目较多时,可使用多个定义命令一般以DB来定义数据,以DW来定义地址,(6)预留存储空间伪指令DS 格式:标号: DS n 功能:从标号指定地址单元开始,预留n个存储单元,汇编时不对这些存储单元赋值。n可以是数据,也可以是表达式。(7)定义位地址符号伪指令BIT 格式:字符名称x BIT 位地址n 功能:将位地址n的值赋予字符名称x。程序中凡出现该字符名称x就代表该位地址。位地址n可以是绝对地址,也可以是符号地址。,AQ BIT P1.0,(8)数据地址赋值伪指令DATA 格式:字符名称x DATA 表达式n 功能:把表达式n的值赋值
9、给左边的字符名称x。n可以是数据或地址,也可以是包含所定义的“字符名称x”在内的表达式,但不能是汇编符号。 DATA与EQU的主要区别是:EQU定义的“字符名称”必须先定义后使用,而DATA定义的“字符名称”没有这种限制。所以,DATA伪指令通常用在源程序的开头或末尾。,4.2.1 手工编程和汇编4.2.2 机器编辑和交叉汇编机器编辑:借助与PC机或开发器进行程序设计.其扩展名为*.asm交叉汇编:借助PC机运行汇编程序将汇编语言转换成单片机能识别的机器码过程.,4.2 单片机汇编语言源程序的编辑和汇编,4.3 单片机汇编语言程序设计,设计步骤1、拟定设计任务书2、建立数学模型3、确定算法4、
10、分配内存单元,编制程序流程图5、编制源程序6、上机调试及程序优化,单片机汇编语言程序的基本结构形式,3种形式,顺序结构,分支结构,循环结构,4.3.1 简单程序设计,简单程序也叫顺序结构程序,是最简单的程序结构,在顺序程序中既无分支、循环,也不调用子程序,程序执行时一条一条地按顺序执行指令。,例4.6 将片内RAM 35H单元中的两位压缩BCD码转换成二进制 数送到片内RAM 40H单元中。,解:两位压缩BCD码转换成十进制数的算法为:,(a1a0)BCD=10a1a0,程序流程图:,程序如下:,ORG 0800H BCD EQU 35H ; 将35H单元定义为压缩BCD码地址 BIN EQU
11、 40H ;将40H单元定义为二进制数地址START:MOV A, BCD ; 取两位BCD压缩码a1a0送A ANL A, #0F0H ; 取高4位BCD码a1 SWAP A ; 高4位与低4位换位 MOV B, #0AH ; 将十进制数10送入B MUL AB ; 将10a1送入A中 MOV R0, A ; 结果送入R0中保存 MOV A, BCD ; 再取两位BCD压缩码a1a0送A ANL A, #0FH ; 取低4位BCD码a0 ADD A, R0 ; 求和10a1+ a0 MOV BIN, A ; 结果送入40H保存 SJMP $ ; 程序执行完,“原地踏步” END,例4.7 将
12、内部RAM中20H单元的压缩BCD码拆开,转换成相应 的ASC码,存入21H、22H,高位存22H.,解:BCD码的09对应的ASCII码为30H39H,先将BCD码 拆分,将拆分后的BCD码送入A,再加上30H即得结果, 然后存入21H、22H中。,程序如下:,ORG 1000H BCD EQU 20H ;将20H单元定义为压缩BCD码地址 ASC EQU 21H ;将21H定义为ASCII码低地址START:MOVA,BCD ; 取压缩BCD码 ANL A,#0FH ; 取低位BCD码 ADDA,#30H ; 转换为低位ASCII码 MOVASC,A ; 保存低位ASCII码 MOVA,B
13、CD ; 重新取压缩BCD码 ANLA,#0F0H ; 分离高位BCD码 SWAPA ; 得到高位BCD码 ADDA,#30H ; 转换为高位ASCII码 MOVASC+1,A ; 保存高位ASCII码 SJMP$ END,4.3.2 分支程序设计,分支程序的三种基本形式:即单分支、双分支、多分支。,分支程序的设计要点如下:(1)先建立可供条件转移指令测试的条件。(2)选用合适的条件转移指令。(3)在转移的目的地址处设定标号。,1.单(双)分支程序,使用条件转移指令实现,即根据条件对程序的执行进行判断,满足条件则进行程序转移,否则程序顺利执行。,可实现单分支程序转移的指令有:,JZ、JNZ、C
14、JNE、DJNZ等,还有以位状态作为条件进行程序分支的指令:,JC、JNC、JB、JNB和JBC等,例4.8 求符号函数的值。已知片内RAM的 40H单元内有一自变量 X,编制程序按如下条件求函数Y的值,并将其存入片内 RAM 的41H单元中。,解:此题有三个条件,所以有三个分支程序。 这是一个三分支归一的条件转移问题。 X是有符号数,判断符号位是0还是1可利用JB或JNB指令。 判断X是否等于0则直接可以使用累加器A的判0指令。,程序流程图,程序如下:,ORG 1000HSTART: MOV A, 40H ; 将X送入A中 JZ DONE ; 若A为0,转至DONE处 JNB ACC.7,
15、POST ; 若A第7位不为1(X为正数),则程序转到 ; POST处,否则(X为负数)程序往下执行 MOV A, #0FFH ; 将1(补码)送入A中 SJMP DONE ; 程序转到DONE处POST: MOV A, #01H ; 将+1送入A中DONE: MOV 41H, A ; 结果存入Y SJMP $ ; 程序执行完,“原地踏步” END,二、散转程序设计举例,MCS-51指令系统中没有多分支转移指令,可使用JMP A+DPTR实现多分支程序转移,但需要有数据表格配合,2. 多分支程序,多分支程序是一种并行分支程序,也叫散转程序,它是根据某种输入或运算结果,分别转向各个处理程序。在M
16、CS-51中用JMP A+DPTR指令来实现程序的散转,转移的地址最多为256个。,例4.9 编制程序用单片机实现四则运算。,解:在单片机的键盘上设置“、”四个运算按键。 其键值存放在寄存器R2中, 当(R2)00H时做加法运算, 当(R2)01H时做减法运算, 当(R2)02H时做乘法运算, 当(R2)03H时做除法运算。,P1口输入被加数、被减数、被乘数、被除数,输出商或运算结果的低8位;P3口输入加数、减数、乘数、除数,输出余数或运算结果的高8位。,程序简化流程图,程序如下:,ORG 1000HSTART: MOV P1, #DATA1 ; 给P1口送入数据DATA1, 用于计算 MOV
17、 P3, #DATA2 ; 给P3口送入数据DATA2,用于计算 MOV DPTR, #TABLE ;将基址TABLE送DPTR CLR C ; Cy清0 MOV A, R2 ;将运算键键值送A SUBB A, #04H ;将键值和04H相减,用于产生Cy标志 JNC ERROR ;若输入按键不合理,程序转ERROR处; ;否则,按键合理,程序继续执行 ADD A, #04H ; 还原键值 CLR C ; Cy清0 RL A ; 将A左移,即键值2,形成正确的散转偏移量 JMP A+DPTR ; 程序跳到(A)+(DPTR)形成的新地址TABLE: AJMP PRG0 ; 程序跳到PRG0处,
18、将要做加法运算 AJMP PRG1 ; 程序跳到PRG1处,将要做减法运算 AJMP PRG2 ; 程序跳到PRG2处,将要做乘法运算 AJMP PRG3 ; 程序跳到PRG3处,将要做除法运算 ERROR:(按键错误的处理程序)(略),PRG0: MOV A, P1 ; 被加数送A ADD A, P3 ; 做加法运算,结果送入A,并影响进位Cy MOV P1, A ; 和的低8位结果送P1 CLR A ; A清0 ADDC A, #00H ; 将进位Cy送入A,作为和的高8位 MOV P3, A ; 和的高8位结果送P3 RET ; 返回开始程序PRG1: MOV A, P1 ; 被减数送A
19、 CLR C ; Cy清0 SUBB A, P3 ; 做减法运算,结果送入A,并影响借位Cy MOV P1, A ; 差的低8位结果送P1 CLR A ; A清0 RLC A ; 将借位Cy左移进A,作为差的高8位(负号) MOV P3, A ; 差的高8位(负号)结果送P3 RET ; 返回开始程序,PRG2: MOV A, P1 ; 第一个因数送A MOV B, P3 ; 第二个因数送B MUL AB ; 做乘法运算,积的低8位送入A,高8位送入B, MOV P1, A ; 积的低8位结果送P1 MOV P3, B ; 积的低8位结果送P3 RET ; 返回开始程序PRG3: MOV A,
20、 P1 ; 被除数送A MOV B, P3 ; 除数送B DIV AB ; 做除法运算,商送入A,余数送入B MOV P1, A ; 商送入P1 MOV P3, B ; 余数送入P3 RET ; 返回主程序,4.3.3、循环程序,重复执行一个程序段,使用条件转移指令通过条件判断来控制循环是继续还是结束。,1单重循环程序,循环体内部不包括其他循环的程序称为单重循环程序。,例4.10 已知片内RAM 38H47H单元中存放了16个二进制无符 号数,编制程序求它们的累加和,并将其和数存放在R4, R5中。,解:每次求和的过程相同,可以用循环 程序实现。 16个二进制无符号数求和,循环程 序的循环次数
21、应为16次(存放在R2 中),它们的和放在R4, R5中(R4 存高8位,R5存低8位)。,程序流程图,程序如下:,ORG 0800HSTART: MOV R0, #38H MOV R2, #10H ; 设置循环次数(16) MOV R4, #00H ; 和高位单元R4清0 MOV R5, #00H ; 和低位单元R5清0LOOP: MOV A, R5 ; 和低8位的内容送A ADD A, R0 ; 将R0与R5的内容相加并产生进位Cy MOV R5, A ; 低8位的结果送R5 CLR A ; A清0 ADDC A, R4 ; 将R4的内容和Cy相加 MOV R4, A ; 高8位的结果送R
22、4 INC R0 ; 地址递增(加1) DJNZ R2, LOOP ; 若循环次数减1不为0,则转到LOOP处循环 ;否则,循环结束 SJMP $ END,例4.11 编制程序将片内RAM的30H4FH单元中的内容传送至 片外RAM的1800H开始的单元中。,解:每次传送数据的的过程相同,可以 用循环程序实现。 30H4FH共32个单元,循环次数 应为32次(保存在R2中), 为了方便每次传送数据时地址的修 改,送片内RAM数据区首地址送 R0,片外RAM数据区首地址送 DPTR。 程序流程图如图所示。,程序如下:,ORG 1000HSTART: MOV R0, #30H ; 数据源首地址 M
23、OV DPTR, #1800H ; 数据转移目标首地址 MOV R2, #20H ; 设置循环次数LOOP: MOV A, R0 ; 将片内RAM数据区内容送A MOVX DPTR, A ; 将A的内容送片外RAM数据区 INC R0 ; 源地址递增 INC DPTR ; 目的地址递增 DJNZ R2, LOOP ; 若R2的内容不为0,则转到LOOP处继续循环 ;否则循环结束 SJMP $ END,2多重循环程序,对于一些复杂问题或者循环控制数超过256,则需采用多重循环的程序结构,即循环程序中包含循环程序或一个大循环中包含多个小循环程序,称多重循环程序结构,又称循环嵌套。循环的重数不限,但
24、必须每循环的层次分明,不能有相互交叉!图 给出了多重循环示意图。,例4.12 编制程序设计50ms延时程序。,解:延时程序与MCS-51指令执行时间(机器周期数)和晶振 频率有直接的关系。 当fOSC=12MHz时,机器周期(1T)为1s,执行一条DJNZ 指令需要2个机器周期(2T),时间为2s。 50ms 2s=25000255, 因此单重循环程序无法实现,可采用双重循环的方法编写 50ms延时程序。,程序如下:,ORG 0800HDELAY: MOV R7, #200 ; 设置外循环次数(1T)DLY1: MOV R6, #123 ; 设置内循环次数 (1T)DLY2: DJNZ R6,
25、 DLY2 ;(R6)-1=0,则顺序执行,否则转回DLY2继续循环 ; (2T),内循环的延时时间为 2s123=246s NOP ; 延时时间为(1T) DJNZ R7,DLY1 ;(R7)-1=0,则顺序执行,否则转回DLY1继续循环 ; (2T), RET ; 子程序结束(2T)总延时时间为(246211)T2002T1T=50.003ms,3循环程序时应注意的问题(1)循环程序是一个有始有终的整体,它的执行是有条件的, 所以要避免从循环体外直接转到循环体内部。(2)多重循环程序是从外层向内层一层一层进入,循环结束时 是由内层到外层一层一层退出的。在多重循环中,只允许 外重循环嵌套内重
26、循环。不允许循环相互交叉,也不允许 从循环程序的外部跳入循环程序的内部。(3)编写循环程序时,首先要确定程序结构,处理好逻辑关系。 一般情况下,一个循环体的设计可以从第一次执行情况入 手,先画出重复执行的程序框图,然后再加上循环控制和 置循环初值部分,使其成为一个完整的循环程序。(4)循环体是循环程序中重复执行的部分,应仔细推敲,合理 安排,应从改进算法、选择合适的指令入手对其进行优化, 以达到缩短程序执行时间的目的。,4循环程序设计举例,(1)多分支循环程序:可用于内部数据形式的变换, 如取绝对值、变为显示码等。,例4.13 有一数据块从片内RAM的30H单元开始存入,设数据 块长度为10个
27、单元。根据下式:,求出Y值,并将Y值放回原处。,解:程序流程图如图所示。,程序如下:,ORG 2000H MOV R0,#10 MOV R1,#30HSTART: MOV A,R1 ;取数 JB ACC.7,NEG ;负数转NEG JZ ZERO ;为零转ZERO ADD A,#03H ;正数求X+3 AJMP SAVE ;转到SAVEZERO: MOV A,# 64H ;为零Y=100 AJMP SAVE ; 转到SAVENEG: DEC A CPL A ;求XSAVE: MOV R1,A ;保存数据 INC R1 ;地址指针指向下一个地址 DJNZ R0,START ;数据未处理完,继续处
28、理 SJMP $ ;暂停,(2)长数运算循环程序:可用于两个多字节数的加减运算,例4.14 两个三字节无符号数,数据存于内部RAM中,起始地址 为50H;将两数相加,并将结果存于50H起始的单元中。 (数据均低位在前),解:程序流程图如图所示。,程序如下:,Data1 EQU 50H Data2 EQU53H BnumEQU03H ORG0100HLOOP:MOVR0,#Data1 MOVR1,#Data2 MOVR2,#Bnum CLR CY MOVA,R0 ADDCA,R1 MOVR0,A INC R0 INC R1 DJNZR2,LOOP JNC END0 MOVR0,#01HEND0:
29、LJMP$,(3)数组运算循环程序:可用于一维数组的相关运算,包括 累加、倍数、偏移等。,例4.15 10个三字节无符号数,数据存于内部RAM中,起始地址为30H;将两数相加,并将结果存于30H起始的单元中。(数据均低位在前),解:程序流程图如图所示。,程序如下:,Data1 EQU 30HData2 EQU33HBnumEQU03Hnum EQU0AH-01H ORG0100HMOVR1,#data2MOVR3,#numMOVR4,#00HNEXT: MOVR0,#data1 MOVR2,#BnumCLR CY LOOP: MOVA,R0ADDCA,R1MOVR0,A INC R0INC R
30、1 DJNZR2,LOOPJNC NEXT0INC R4NEXT0: DJNZR3,NEXTMOVR0,R4LJMP$,(4)数据检索循环程序:可用于数组内的数据检索、分类等。,例4.16 200名学生参加考试,成绩放在8031的外部RAM的一个 连续存储单元,95100分颁发A级证书,9094分颁发B 级证书,编一程序,统计获A、B级证书的人数。将结 果存入内部RAM的两个单元。,解:本题的程序流程图如图所示。,程序如下所示:,ScoreTab EQU 1000H GradeA EQU 20H GradeB EQU 21H Num EQU 200 ORG 0060HSTART: MOV Gr
31、adeA,#00H MOV GradeB,#00H MOV DPTR,# ScoreTab MOV R2,# NumLOOP: MOVX A,DPTR CJNE A, #95, LOOP1 LOOP1: JNC NEXT1 CJNE A, #90, LOOP2LOOP2: JC NEXT INC GradeB SJMP NEXTNEXT1: INC GradeANEXT: INC DPTR DJNZ R2, LOOP SJMP $,(5)数据排序循环程序:可用于数组内数据的排序、统计等。,常用冒泡法对数据进行排序,其特点是两两比较。如有n个数先将Dn和Dn-1进行比较,若Dn Dn-1,则两数
32、交换, ,然后Dn-1和Dn-2进行比较,按同样的原则,决定是否交换,一直比较下去,最后完成D2和D1的比较及交换。经过n-1次比较后, D1位置必然得到数组中的最大值。犹如一个气泡冒到水顶。最多经过n-1次这样的比较过程,便完成n个数据的排序。,例:将下列数据排序(n=8) 冒泡次数 比较次数38,5,13,47,44,62,22,78 1 8-1=75,13,38,44,47,22,62 2 65,13,38,44,22,47 3 55,13,38,22,44 4 45,13,22,38 5 35,13,22 6 2,例4.17 将起始地址为20H的100个数据,从小到大进行排序。,解:程
33、序流程图如图所示。,程序如下:,SORT: MOV R2,#100 ;共100个数据CHANG:MOV R0,#20H ; 数据起始地址 CLR F0 ;互换标志清0 DEC R2 ;R2冒泡计数器 CJNE R2,#0,GO LJMP BACKGO: MOV 7FH,R2 ;比较计数器CONT: MOV A,R0 ;取前数 INC R0 MOV B,R0 ;取后数 CJNE A,B,LOOPLOOP: JC NEXT;后前,CY=1 MOV R0,A DEC R0 MOV R0,B INC R0 ;指针+1 SETB F0 ;互换标志置1NEXT: DJNZ 7FH,CONT JB F0,CHANGBACK: SJMP $,