1、第四章 指令系统及汇编语言程序设计,任课教师:刘忠国 山东大学课程中心网站:http:/ 宏晶官方网站:http:/ stc15系列单片机器件手册等 keil vision软件下载及指导手册(Helpvision Help) http:/ 何宾STC单片机原理及应用 http:/ Keil Software Cx51 编译器用户手册: Cx51编译器-对传统和扩展的8051微处理器的优化的C编译器和库参考,2,第四章 指令系统及汇编语言程序设计,本章学习目标 了解助记符、指令格式 掌握单片机寻址方式 掌握单片机指令系统 掌握单片机汇编语言程序设计及开发环境 参考资料: keil Vision软
2、件的帮助文件,3,01:46:57,第四章 指令系统及汇编语言程序设计语言,4.1 编程语言 4.2 指令格式及其分类 4.3 寻址方式 4.4 数据传送类指令 4.5 逻辑操作类指令 4.6 算术运算类指令 4.7 位操作指令 4.8 控制类转移指令 4.9 汇编语言程序设计 4.10 汇编语言程序调试 4.11利用ISP工具将程序下载到单片机中验证程序,4,01:46:57,4.9 汇编语言程序设计,4.9.1 伪指令(Pseudo- Instruction) 用户将编辑好的汇编语言源程序通过专门的软件(称为汇编程序)汇编成相应的机器语言程序时,需要有一些专门的说明性语句。 例如,指定目标
3、程序或数据存放的起始地址、给一些指定的标号赋值、在内存中予留工作单元、表示源程序结束等指令。 指令并不产生对应CPU操作的机器码, 故称伪指令, 也叫指示性语句(Directives); 相对应的,可产生实质性操作的指令叫指令性语句(Instructions), 指令性语句表示CPU要进行的某种操作。 例, MOV A, #30H, 表示将立即数30H送到寄存器A中。,5,01:46:57,4.9.1 伪指令,1、起始地址设置伪指令ORG(ORIGIN)格式为: ORG xxxxH ORG是起始地址设置伪指令的操作码,xxxx是四位十六进制地址。该指令表明其后紧跟的指令性语句的机器码放在以xx
4、xxH为起始地址的单元中。 例:ORG 0100H DELAY: MOV R0,#30H,6,01:46:57,1、起始地址设置伪指令ORG,一般,在整个程序的起始处放置一条“ORG 0000H”伪指令,表明下面开始的指令性语句从0000H开始存放。后面有一定独立性的程序段也可以用这条指令指定程序段存放的起始地址。 例如:ORG 0000H START: LJMP MAINMOV A,#00HORG 0100H DELAY: MOV R0,#30H,7,01:46:57,0003H外部中断0中服入口地址,1、起始地址设置伪指令ORG,ORG伪指令的作用 单片机复位时, 一个重要操作是将程序计数
5、器PC清零。在复位结束后, 系统从程序存储器存放的第一个地址单元0000H开始取指令。汇编时就需要告诉汇编程序将后面的语句经汇编后放在地址为0000H开始的区域; 因此, 整个程序起始地址用“ORG 0000H”伪指令说明。 后面延时子程序DELAY 在指令 “ORG 0100H”说明作用下, 经汇编后被放置在地址为0100H开始的区域。 在例子中,如果没有“ORG 0100H”这条语句,延时程序DALAY也会得到汇编,汇编后的机器码紧接着前面的程序顺序存放。,8,01:46:57,4.9.1 伪指令,2、数据定义伪指令 功能:定义一个数据存储区,其类型由数据定义伪指令指定,可以给存储区赋初值
6、,也可以仅仅给变量分配存储单元,而不赋予特定的值。 一般格式: 标号: 数据定义伪指令 操作数 ,操作数 ;注释方括号中的内容为可选项。伪指令后面的操作数可以不止一个。如有多个操作数,互相之间用逗号隔开。,9,01:46:57,例如:,SEG: DB 23H ;定义一个字节,标号SEG 可以如下方式引用:MOV R0, #SEGMOV A, R0,标号SEG 不能以变量方式被引用:MOV A, SEG,2、数据定义伪指令,常用的数据定义伪指令有DB和DW: (1)定义字节DB(Define Byte)标号: DB 项或项表其中项或项表:指一个字节、数或数字串,或以引号括起来的ASCII码字符串
7、(一个字符用ASCII码表示,相当于一个字节)。该指令的功能是把项或项表的数值存入从标号开始的连续单元中,每个操作数存放时占1个字节,多个操作数时,按排列顺序首先从低地址存放。,10,01:46:57,2、数据定义伪指令,常用的数据定义伪指令有DB和DW: (1)定义字节DB(Define Byte)标号: DB 项或项表其中项或项表:指一个字节、数或数字串,或以引号括起来的ASCII码字符串(一个字符用ASCII码表示,相当于一个字节)。MSG: DB Press A Key To Continue, 0 TAB: DB 2, 3, 5, 7, 11, 13, 17, 19, ;,11,01
8、:46:57,2、数据定义伪指令,(2)定义字DW(Define Word) DW伪指令格式:标号: DW 功能: 用于定义字变量。项或项表指所定义的一个字(两个字节)或用逗号分开的字串。可用来定义地址。 每个字变量占2字节存储单元,两个字节存储单元相邻, 低(高)位字节在低地址中, 高(低)位字节在高地址中。,12,01:46:58,TABLE: DW TABLE, TABLE+10, HERE HERE: DW 0 DW $,多个操作数时,按排列顺序从低地址开始存放。,TABLE:,HERE:,2、数据定义伪指令,(3)预留存储空间 DS (补充) 格式:标号: DS 表达式 功能:从标号
9、地址开始, 保留若干个字节的内存空间以备存放数据。保留字节单元数由表达式值决定。 例如: DSEG AT 0x30 ; 数据段起始地址30HVARIBLE: DS 5H ;该指令不能出现在代码段 汇编后从30H开始,预留5个字节的内存单元。,13,01:46:58,(DS在“5.3 单片机C语言程序调试”用到),数据段中的标号SEG 可以变量方式被引用:MOV VARIBLE, A;MOV R1, VARIBLE;,CSEG AT 0080h; 代码段可用此指令定义起始地址,或省略则默认为都是代码段。(仅作了解),仅DS伪指令需在数据段中定义,2、数据定义伪指令,例如:ORG 1000H SE
10、G: DB 23H ;定义一个字节DW 1000H ;定义一个字DB MCS-51 ;定义一个字符串END 则: (1000H)=23H SEG的地址为1000H(1001H)=00H 10H(1002H)=10H 00H(1003H)=4DH M的ASCII码(1004H)=43H C 的ASCII码(1005H)=53H S 的ASCII码(1006H)=2DH -的ASCII码(1007H)=35H 数字5的ASCII码(1008H)=31H 数字1的ASCII码,14,01:46:58,2、数据定义伪指令,由数据定义伪指令DB或者DW后面的操作数确定变量的初值,常用的有以下几种形式:
11、常数或数值表达式。 ASCII码字符串。? 表示定义的变量无确定值。可用DS预留存储空间(见后)或用EQU, DATA定义一个存储单元地址(见后),15,01:46:58,汇编程序中的常数,可采用不同的数制和不同表示方法: 十进制数:数字的后面加一个字母“D”(Decimal),表示是十进制数;或者什么也不加,默认为是十进制数。 二进制数:数字的后面加一个字母“B”(Binary),如10101001B。,2、数据定义伪指令,十六进制数: 数字后面加一个字母“H” (Hexadecimal),而且,当十六进制数字不是以数字09开始,而是以字母(AF)开头时,前面要再加一个前导数字0,这是为了在
12、进行汇编时,以区别是数字,不是符号名。 ASCII常数: 应将字符放在单引号中, 例如A,8等。,16,01:46:58,汇编语言语句中表达式为数值表达式, 由数值和运算符组成, 产生一个数值结果。运算符为算术运算符, 常用算术运算符有: 十(加), (减), *(乘), /(除)。 注意, 作为操作数部分的项或项表, 若为数值, 其取值范围为000FFH(对DB)或00FFFFH (对DW) 。,DB, DW,4.9.1 伪指令,3、等值伪指令EQU(Equate) 标号 EQU 表达式功能: 将语句操作数值赋于本语句标号。格式中表达式可以是一常数、符号、数值表达式或地址表达式等。 若源程序
13、中需多次引用某一表达式, 则可用EQU伪指令给其赋一个标号(名字), 在以后的代码中, 可用该标号来代替上述表达式,从而使程序更加简洁,便于阅读。 如欲改变表达式的值,也只需在EQU指令处修改一次,而不必修改多处,使程序易于调试、修改和维护。,17,01:46:58,注意:此伪指令中的标号后面不能加冒号 “:”,3、等值伪指令EQU(Equate),COLUMN EQU 32H ROW EQU 68H BUFFER DB ? BUFFER EQU 40H MOV A, #COLUMN MOV B, #ROWMUL ABMOV BUFFER, AMOV BUFFER+1, B,18,01:46:
14、58,(该程序段稍改一下才适于51单片机) 执行后, 就把COLUMN 和 ROW 的乘积放在了单元BUFFER和BUFFER+1中。只要改变COLUMN 和 ROW的值就可以计算不同数据的乘积。,注意:在同一程序中,用EQU伪指令对标号赋值后,该标号的值在整个程序中不能再改变。,【例】,或用DATA伪指令,可用直接寻址40H, 41H,3、等值伪指令EQU(Equate),COLUMN EQU 32H ROW EQU 68H DSEG AT 0x40 ;数据段始于40H BUFFER: DBS ? 2CSEG AT 0100h ;代码段起始地址MOV A, #COLUMN MOV B, #R
15、OWMUL ABMOV BUFFER, AMOV BUFFER+1, B,19,01:46:58,在这里BUFFER地址只能用BUFFER: DS 2在数据段(存储器)里定义,数据段里不允许用BUFFER: DB 01H定义, 若在代码段里定义BUFFER (无论是用BUFFER: DB 01H还是用BUFFER: DS 2定义),在这里BUFFER地址都不能被识别, BUFFER不能用作目的操作数地址, 因不能向程序存储器里写数据, 只能从程序存储器读数据。,注意:在同一程序中,用EQU伪指令对标号赋值后,该标号的值在整个程序中不能再改变。,【例】,4.9.1 伪指令,4、DATA指令符号名
16、 DATA 表达式该指令将一个内部RAM的地址赋给指定的符号名。表达式必须是一个简单表达式, 其值在00H0FFH之间。例如: BUFFER DATA 40H,20,01:46:58,5、XDATA指令(Extenal Data)符号名 XDATA 表达式该指令将一个外部RAM的地址赋给指定的符号名。表达式必须是简单表达式, 其值在0000H0FFFFH之间。例如: MYDATA XDATA 0100H,4.9.1 伪指令,6、定义位命令BIT 字符名称 BIT 位地址用于给字符名称定义位地址。 例如: DOGOUT BIT P3.4; 或写成P34, 0B0H.4, 0B0H4经定义后, 允
17、许在后续指令代码中用DOGOUT代替P3.4。,21,01:46:58,7、文件包含命令INCLUDE 文件包含命令INCLUDE用于将寄存器定义文件(一般的后缀名为.INC)包含于当前程序中,与C语言中的#include语句的作用类似。 使用格式为: $INCLUDE (文件名),P3,P0等已在头文件STC15.INC中定义, .是位操作符,P3 DATA 0B0H,7、文件包含命令INCLUDE,例如,为使用方便,把STC15F2K60S2单片机的寄存器定义保存在文件STC15.INC中(见附录B)。使用时,可在程序的开始处使用下面的命令将其包含到用户程序中:$INCLUDE (STC1
18、5.INC) 使用上述命令后,在用户程序中就可以直接使用STC15F2K60S2单片机的特殊寄存器名称了。 例, MOV CMOD, #10000000B ;设置PCA工作模式,22,01:46:58,因文件中有寄存器定义: CMOD DATA 0D9H,寄存器定义的指令如: P3 DATA 0B0H,4.9.1 伪指令,8、条件汇编控制指令 条件汇编控制指令的作用是使源程序中的一部分程序行根据需要决定是否进行汇编。 条件汇编控制伪指令的一般格式: IF 表达式 程序块1 ELSE 程序块2 ENDIF,23,01:46:58,8、条件汇编控制指令,当IF指令中的表达式为真时,汇编程序汇编程序
19、块1; 当IF指令中的表达式为假时,汇编程序块2。在一个条件结构中,仅有一个程序块被汇编,其它的则被忽略。 IF块可嵌套使用, 最大嵌套深度为63层(Keil Vision集成开发环境只能达10层)。 如果IF ELSEIF和ELSE块不汇编,则其嵌套的条件块也不汇编。,24,01:46:58,4.9.1 伪指令,9、汇编结束伪指令 格式:END 标号 汇编程序结束时,最后一条伪指令为END。 指令格式中的标号是整个汇编语言源程序第一条可执行语句的标号。该伪指令告诉汇编程序:整个源程序结束,汇编程序停止汇编,并指出第一条指令性语句的标号。 在一般的程序中,END后的标号都省略不写。,25,01
20、:46:58,4.9.2 汇编语言程序设计的一般步骤和基本框架,程序是指令的有序集合。编写一个功能完善的、完整的程序,正确性是最主要的; 但整个程序占内存的空间大小、每条指令的功能、长度、执行速度等都要考虑,尽可能使其优化。 一个完善的系统设计应该具有设计方案正确、程序结构规范等基本性质,这不仅给程序的设计和调试带来方便,加速调试过程,而且有益于程序的维护和升级。,26,01:46:58,4.9.2 汇编语言程序设计的一般步骤和基本框架,汇编语言程序设计的一般步骤是: 分析课题,确定算法或解题思路。 根据算法或思路画出流程图。 根据算法要求分配资源,包括内部RAM、定时器、中断等资源的分配。
21、根据流程图编写程序。 上机调试源程序,进而确定源程序。对于复杂的程序可以按功能分为不同的模块,按模块功能确定结构。编写程序时采用模块化的程序设计方法。,27,01:46:58,4.9.2 汇编语言程序设计的一般步骤和基本框架,28,01:46:58,$INCLUDE (STC15.INC) ;下面是汇编语言程序的框架;本语句包含STC15F2K60S2单片机寄存器定义头文件 ;-这里可以编写程序中用到的一些符号定义(使用EQU, DATA, BIT等伪指令)ORG 0000H START: LJMP MAIN ;跳转到主程序ORG 0003HLJMP INT0_ISR ;外部中断0入口ORG
22、000BHLJMP T0_ISR ;定时器0中断入口ORG 0013HLJMP INT1_ISR ;外部中断1入口ORG 001BHLJMP T1_ISR ;定时器1中断入口ORG 0023HLJMP UART1_ISR ;串口1中断入口,4.9.2 汇编语言程序设计的一般步骤和基本框架,ORG 002BHLJMP ADC_ISR ;ADC中断服务程序入口 ORG 0033HLJMP LVD_ISR ;低电压检测中断服务程序入口ORG 003BHLJMP PCA_ISR ;PCA中断服务程序入口 ORG 0043HLJMP UART2_ISR ;串口2中断服务程序入口ORG 004BH LJM
23、P SPI_ISR ;SPI中断服务程序入口,29,01:46:58,4.9.2 汇编语言程序设计的一般步骤和基本框架,ORG 0053HLJMP INT2_ISR ;INT2中断服务程序入口ORG 005BHLJMP INT3_ISR ;INT3中断服务程序入口ORG 0063HLJMP T2_ISR ;定时器2中断服务程序入口ORG 0083HLJMP INT4_ISR ;INT4中断服务程序入口,30,01:46:58,4.9.2 汇编语言程序设计的一般步骤和基本框架,ORG 0100H MAIN: MOV SP, #70H ;设置堆栈指针(可根据实际情况进行修改);初始化内存区域内容;
24、设置有关特殊功能寄存器(SFR)的控制字;根据需要开放相应的中断控制 MAINLOOP:;主程序循环LJMP MAINLOOP,31,01:46:58,4.9.2 汇编语言程序设计的一般步骤和基本框架,;下面是各个中断服务子程序的入口 INT0_ISR: ;外部中断0服务子程序 ;根据需要填入适当的内容RETI INT1_ISR: ;外部中断1服务子程序 ;根据需要填入适当的内容RETI T0_ISR: ;定时器0中断服务子程序 ;根据需要填入适当的内容RETI T1_ISR: ;定时器1中断服务子程序 ;根据需要填入适当的内容RETI UART1_ISR: ;串口1中断服务子程序 ;根据需要
25、填入适当内容(注意中断请求标志位清零)RETI,32,01:46:58,4.9.2 汇编语言程序设计的一般步骤和基本框架,33,01:46:58,UART2_ISR: ;串口2中断服务子程序 ;根据需要填入适当内容(注意中断请求标志位清零)RETI ADC_ISR: ;ADC中断服务子程序 ;根据需要填入适当内容(注意中断请求标志位清零)RETI SPI_ISR: ;SPI通信中断服务子程序 ;根据需要填入适当内容(注意中断请求标志位清零)RETI LVD_ISR: ;低电压检测服务子程序 ;根据需要填入适当内容(注意中断请求标志位清零)RETI PCA_ISR: ;PCA和PWM中断服务子程
26、序 ;根据需要填入适当内容(注意中断请求标志位清零)RETI,4.9.2 汇编语言程序设计的一般步骤和基本框架,INT2_ISR: ;INT2中断服务子程序 ;根据需要填入适当的内容RETI INT3_ISR: ;INT3中断服务子程序 ;根据需要填入适当的内容RETI T2_ISR: ;定时器2中断服务子程序 ;根据需要填入适当的内容RETI INT4_ISR: ;INT4中断服务子程序 ;根据需要填入适当的内容RETI ;下面可以编写其他子程序或者定义程序中所用的常数END,34,01:46:58,4.9.2 汇编语言程序设计的一般步骤和基本框架,注意 由于地址0003H、000BH、00
27、13H、001BH、0023H 、002BH、0033H、003BH、0043H、004BH、0053H、005BH、0063H和0083H是专门为中断处理子程序分别预留的入口地址, 所以第一条指令是一条长跳转指令,跳到避开上述中断处理子程序入口地址的0100H的地址,主程序MAIN从这个地址开始存放; MAIN 语句前面的伪指令“ORG 0100H”表示,以标号MAIN表示的主程序放在0100H开始的区域,当然也可以是跳到能够避开上述入口地址的其他地址。,35,01:46:58,4.9.2 汇编语言程序设计的一般步骤和基本框架,如果用户系统根本没有任何中断源,或者没有使用全部中断源,就可以不
28、用或者少用中断的功能; 0003H到0083H的区域也就无须全部或部分用于中断处理。没有任何中断的情况下,主程序甚至可以从0000H开始连续存放下去。 主程序的末尾是一条长跳转指令,跳转到某个合适的地方反复执行主程序。 一般的子程序不可形成死循环,但是作为整个主程序却应该是一个最大的死循环。无论执行哪个子程序,之后都要回到主程序,反复循环运行。,36,01:46:58,4.9.2 汇编语言程序设计的一般步骤和基本框架,程序流程图 在程序编制以前,先根据系统方案绘制程序流程图是一个很好的方法。 程序流程图可以简洁清晰地将程序的分支走向标示清楚,尤其是在程序复杂,编写人员较多相互衔接容易出错的的情
29、况下,利用流程图理顺各部分关系显得尤为重要。,37,01:46:58,画流程图有两个常用的结构:顺序执行的矩形框和条件分支的菱形框。,画流程图两结构:顺序执行矩形框和条件分支菱形框,顺序执行:某个局部功能或者顺序执行的语句使用矩形方框表示,矩形方框内注明程序的功能,各方框之间用箭头表示执行顺序,一目了然; 条件分支: 遇到需要根据条件判断是否转移时,使用菱形方框表示, 菱形框内注明分支条件, 不同出口表明分支的去向: 可以向后跳转, 也可向前跳转。,38,01:46:58,顺序结构,分支结构,分支结构另种画法,例: DJNZ R0, L1,图4-17 典型循环程序结构的流程图,程序流程图,循环
30、程序设计 当程序处理的对象具有重复性规律时,可以使用循环程序设计。一个循环表示重复执行一组指令(程序段)。,39,01:46:58,画流程图两结构:顺序执行矩形框和条件分支菱形框,条件分支: 菱形框内注明分支条件, 不同出口表明分支的去向: 可以向后跳转, 也可向前跳转。一般框图如下所示:,40,01:46:58,二分支结构,多分支结构,用: CJNZ, JZ, J(N)C, J(N)B等,4.9.3 典型汇编语言程序设计举例,1、分支程序设计 2、查表程序设计 3、循环程序设计 4、定点数运算子程序设计 5、数据排序程序设计 6、代码转换程序设计,41,01:46:58,1、分支程序设计,程
31、序分支是通过条件转移指令实现的,即根据条件进行判断后决定程序的走向。条件满足则进行程序转移,不满足就顺序执行程序。 通过条件判断实现单分支程序转移的指令有JZ、JNZ、CJNE (4条)和DJNZ(2条)等。 以位状态为条件,进行程序分支的指令JC、JNC、JB、JNB和JBC等。,42,01:46:58,1、分支程序设计,【例4-9】编程实现下面的比较函数。设变量x存放在R0,求得的y 值存入SIGN单元。,43,01:46:58,解:可以利用比较转移CJNE指令和进位位C状态控制转移(JC指令)来实现三分支转移。,2)比较转移指令(4条),CJNE (目的字节), (源字节),rel,44
32、,01:46:58,比较转移指令有4条:CJNE A, #data8,rel CJNE A, addr8,rel,CJNE Ri, #data8, rel CJNE Rn, #data8, rel,该指令比较前面两个操作数的大小,如果它们的值不相等则转移,相等则继续执行。 三字节指令,PC当前值(PC3 PC)与指令第三字节带符号的偏移量相加即得到转移地址。 对进位位CY有影响: 如果目的字节的无符号整数值小于源字节的无符号整数值,则置位进位标志,否则清“0”进位位,指令不影响任何一个操作数。,机器码:B8BF,【例4-9】程序,SIGN EQU 50H ;求得的y 值存入SIGN单元ORG
33、0000HLJMP MAINORG 0100H MAIN: CJNE R0, #37, NOTEQ ;R0与37比较, 不相等则转NOTEQMOV SIGN, #00H ;若比较相等,则SIGN0LJMP ENDM ;转到程序结束 NOTEQ:JC NEG ;两数不相等, 若R037则C=1, 转NEG处理MOV SIGN,#01H ;R037时,SIGN+1LJMP ENDM ;转到程序结束 NEG:MOV SIGN, #0FFH ;R037时, SIGN-1 ENDM:NOPEND,45,01:46:58,设变量x值存放在R0,2、查表程序设计,查表法产生的背景 参数的计算非常复杂; 公式
34、计算法计算程序长,难于计算; 需要耗费大量时间; 非线性参数,无法用一般算术运算就可以计算出来,如指数、对数、三角函数以及积分、微分等运算; 数学计算无法建立相应的数学模型。 查表法定义就是把事先计算或测得的数据按一定顺序编制成表格,查表程序根据被测参数的值或中间结果, 查出最终所需的结果。它具有程序简单, 执行速度快等优点。,46,01:46:58,2、查表程序设计,应用: 在键盘处理程序中,查找按键相应的命令处理子程序的入口地址; 在一些快速计算的场合,根据自变量的值,从函数表上查找出相应的函数值以及实现非线性修正、代码转换等等。 常用MOVC A,ADPTR查找程序存储器空间的代码或常数
35、,每次传送一个字节。 举例: 在LED显示程序中, 获得LED数码管显示字模;,47,01:46:58,2、查表程序设计,48,01:46:58,例如, 假如要显示的数据需放到累加器A中, 采用共阳极LED显示, 则可采用下面查表法程序获得LED显示字模: MOV DPTR, #SEGTAB ;获得字模表的首地址MOVC A, A+DPTR ;查表获得字模 ;下面可以送出字模进行显示 SEGTAB: DB 0C0H ;0的字模DB 0F9H ;1的字模DB 0A4H ;2的字模DB 0B0H ;3的字模DB 99H ;4的字模DB 92H ;5的字模DB 82H ;6的字模DB 0F8H ;7
36、的字模DB 80H ;8的字模DB 90H ;9的字模,A中存要显示的09的数,如何转换,数字的字模,3、循环程序设计,49,01:46:58,延时程序是典型的循环程序。 下面就以延时程序为例, 说明循环程序的设计方法。 流程图如图所示。,图4-18 延时程序流程图,DJNZ R7, LOOP,3、循环程序设计,简单延时子程序如下(注释部分为指令的时钟周期数):MOV R7,#150 ;2T LOOP: DJNZ R7, LOOP ;4T,;R7R7-1, 若R70, 则转到LOOP执行RET STC15F2K60S2为1T的8051单片机, 当系统时钟为6MHz时, 每时钟周期为1/6us,
37、 上述程序可延时约0.1ms。为达到准确延时的目的, 可在适当地方加入NOP指令。,50,01:46:58,延时时间: 15041/6s=100s,3、循环程序设计,若需加长延时时间, 可采用多重循环延时程序方法。 以下程序, 内循环延时0.1ms, 外循环次数可在调用前(入口)设定, 根据设定值不同, 可在0.125.5ms间延时。 入口: 设置延时时间N (以0.1ms为单位) 送入R0。 出口: 若延时到(R0减到0), 则退出程序, 无参数传递。MOV R0, #100 ;2T, R0控制外循环次数 DELAY: MOV R7, #150 ;2T, R7控制内循环次数 LOOP: DJ
38、NZ R7, LOOP ;4T,当6MHz时钟时,延时约0.1msDJNZ R0, DELAY ;4T,外循环次数0.1ms延时时间RET,51,01:46:58,延时时间: 1002+(1504)+4 1/6 s =10100 s=10.1ms 1000.1 ms,4、定点数运算子程序设计,多字节无符号加法子程序和减法子程序设计较简单,在此介绍有代表性的多字节BCD码减法程序和多字节乘法程序的设计。 (1)多字节十进制BCD码减法 因指令系统中只有十进制加法调整指令DA A, 也即该指令只有在加法指令(ADD、ADDC)后, 才能得到正确的结果。 为了用十进制加法调整指令对十进制减法进行调整
39、,必须采用补码相加的办法,用9AH (100)减去减数即得以10(100)为模的减数的补码。,52,01:46:58,参考例4-8,GO,(1)多字节十进制BCD码减法,求BCD码8943H - 7649H=? 编程前由实例测算计算过程。 先对低位字节运算43H - 49H:1001 1010 模9A -) 0100 1001 减数490101 0001 得49对100补码51 +)0100 0011 加被减数430 1001 0100 差94,53,01:46:58,再对高字节运算89H -76H - C:1001 1010 9A-) 0111 0110 760010 0100 得76对10
40、0补码为24-)0000 0001 减去借位位C=1 0010 0011 减借位1后的值为23 +)1000 1001 加被减数891010 1100 结果0AC +) 0110 0110 对结果加66修正10001 0010 差为12,C=0无进位, 表示二者相减有借位。应对借位C求反使C=1。,DA A 调整,高字节减数变补与被减数相加调整后有进位1, 表示两者相减无借位, 为正确反映借位情况应对进位C求反使C=0(减法时C=1,表示有借位; C=0, 表示无借位)。最后结果为1294H, 且无借位, 计算正确。,43向高位借位与49相减的结果,应理解为,以十六进制形式表示,后C=0,(1
41、)多字节十进制BCD码减法,程序说明(减法运算化成100的补码加法运算) 程序中,减数求补后与被减数相加,方可利用DA A指令进行调整; 若二者相加调整(DA A)后结果无进位(C=0),实际上表示二者相减有借位; 若二者相加调整(DA A)后有进位(C=1),实际上表示二者相减没有借位(教材加文字); 参考例4-8 因此, 都需对进位位C进行求反操作。,54,01:46:58,BCD码减法程序举例:采用补码相加的办法,用9AH(100)减去减数即得以10(100)为模的减数的补码。,(1)多字节十进制BCD码减法,入口:被减数低字节地址存放于R1,减数低字节地址存放于R0,字节数存放于R2。
42、 出口:差 (补码) 的低字节地址存放于R0,字节数存放于R3。 07H为符号位。0表示结果为正,1表示结果为负。,55,01:46:58,多字节十进制BCD码在RAM中存放地址:,(1)多字节十进制BCD码减法 编程代码:,56,01:46:58,R1: 被减数低字节地址; R2: 字节数; R3: 差的字节数。 R0: 减数低字节地址;也是最后结果差(BCD码)的低字节地址 07H位地址存最终结果符号位。0表示结果为正,1表示结果为负。,SUBCD: MOV R3, #00H ;差的字节数置0CLR 07H ;符号位单元清0CLR C ;下面用带进位减法指令SUBB, 借位位C清0 SUB
43、CD1: MOV A, #9AHSUBB A, R0 ;求减数的100的补码ADD A, R1 ;补码与被减数相加DA A ;十进制加法调整指令MOV R0, A ;结果差送到R0间接寻址单元INC R0 ;减数地址值增1, 指向高字节INC R1 ;被减数地址值增1, 指向高字节INC R3 ;差的字节数增1,CPL C ;进位求反,以形成正确借位 DJNZ R2, SUBCD1 ;每字节减法算法相同,未完循环, 减完顺序执行, JNC SUBCD2 ;无借位去SUBCD2返主, 否则继续 SETB 07H ;差为负置符号位07H为“1” SUBCD2: RET ;返回,(2)多字节乘法运算
44、子程序,单片机指令系统中只有单字节乘法指令MUL AB, 而工程应用中常需8位乘16位、两个16位数相乘的运算。,57,01:46:58,以两个16位无符号数相乘为例说明多字节乘法程序设计。 设被乘数放在R2、R3两单元(高字节在前), 乘数放在R6、R7两单元, 两个双字节无符号数相乘, 结果送33H、32H、31H、30H。,(R3R7)L表示R3R7的低8位, (R3R7)H表示R3R7的高8位, 其余几项的含义类似。 程序如下:,算法示意图如图所示。,GO,(2)多字节乘法运算子程序,DMUL: MOV A, R3 MOV B, R7 MUL AB ;R3R7 MOV 30H, A ;
45、(30H) (R3R7)L MOV 31H, B ;(31H) (R3R7)H MOV A, R2 MOV B, R7 MUL AB ;R2R7 ADD A, 31H ;(R3R7)H+(R2R7)L MOV 31H, A CLR A ADDC A, B ;进位位C与(R2R7)H加 MOV 32H, A ;(32H) (R2R7)H,58,01:46:58,(2)多字节乘法运算子程序,MOV A, R3MOV B, R6MUL AB ;R3R6ADD A, 31HMOV 31H, AMOV A, BADDC A, 32H ;(R2R7)H+(R3R6)HMOV 32H, AMOV F0, C
46、 ;暂存Cy;因下面乘法使C清0;也可CLR A, ADDC A, #0,MOV 33H, A;下面程序相应修改,59,01:46:58,程序状态标志寄存器PSW,F0: 用户标志位,(2)多字节乘法运算子程序,60,01:46:58,MOV A, R2MOV B, R6MUL AB ;R2R6ADD A, 32HMOV 32H, ACLR AMOV ACC.0, C ;或 ADDC A, #0MOV C, F0 ;前次加法进位送C, 为ADDC加(R2R6)H准备ADDC A, BMOV 33H, ARET,MOV F0, C ;暂存Cy,程序状态标志寄存器PSW,F0: 用户标志位,5、数
47、据排序程序设计,数据排序是将数据块中的数据按升序或降序排列。下面以数据升序排序为例, 说明数据排序程序设计方法。 数据升序排列常采用冒泡法。冒泡法是一种相邻数据互换的排列方法,同查找极大值方法一样,一次冒泡即找到数据块的极大值放到数据块最后,,61,01:46:58,例, 将片内RAM 30H37H中的数据从小到大升序排列。 设R6为循环次数计数器, R7为比较次数计数器。 F0为冒泡过程中是否有数据交换的状态标志,F0=0表示无交换发生,F0=1表示有互换发生,须继续循环。 R0为指向RAM单元的地址指针初值为30H。,再一次冒泡,次大数排在倒数第二位置,多次冒泡实现升序排列。,冒泡法数据排序程序流程图,62,01:46:58,数据在30H37H中; R6为循环次数计数器 R7为比较次数计数器; F0为数据交换状态标志; R0地址指针.,比较次数,循环次数,冒泡法数据排序程序,SORT: MOV R6,#07H ;循环次数送到R6 GOON: CLR F0 ;交换标志清0 MOV R0, #30H ;数据首址送R0MOV A, R6MOV R7, A ;各次冒泡比较次数送R7 LOOP: MOV A, R0 ;取前数MOV 3BH, A ; 3BH单元存前数INC R0MOV 3AH, R0 ;取后数送3AH单元CLR CCJNE A, 3AH, EXCHLJMP NEXT,