单片机原理与应用
第4章 汇编语言程序设计
4.1 80C51汇编语言程序设计基础 机器语言 汇编语言 高级语言 汇编语言与高级语言相比具有以下优点: 1)占用的内存单元和CPU资源少 第4章 汇编语言程序设计 4.1 80C51汇编语言程序设计基础 机器语言 汇编语言 高级语言 汇编语言与高级语言相比具有以下优点: 1)占用的内存单元和CPU资源少 (2)程序简短,执行速度快 (3)可直接调用计算机的全部资源,并可有效地利用计算机的专有特性 (4)能难确地掌握指令的执行时间,适用于实时控制系统。
4.1 80C51汇编语言程序设计基础 汇编语言具有以下几个特点: 第4章 汇编语言程序设计 4.1 80C51汇编语言程序设计基础 汇编语言具有以下几个特点: ① 助记符指令与机器指令是一一对应的,所以用汇编语言编写的程序效率高,占用存储空间小,运行速度快,而且能反映计算机的实际运行情况,所以用汇编语言能编写出最优化的程序。 ② 汇编语言是“面向机器”的语言,编程比使用高级语言困难。 ③ 汇编语言能直接访问存储器、输入与输出接口及扩展的各种芯片(比如A/D、D/A等) ,也可直接处理中断,因此汇编语言能直接管理和控制硬件设备。 ④ 汇编语言通用性差,汇编语言和机器语言一样,都面向一台具体的机器,不同的单片微机具有不同的指令系统,并且不能通用。
4.1.1 汇编语言源程序的设计方法 程序结构 模块设计 开发方法 第4章 汇编语言程序设计 4.1.1 汇编语言源程序的设计方法 程序结构 模块设计 开发方法 自底向上开发:首先对最底层模块进行编码,测试和调试。这些模块正常工作后,就可以用它们来开发较高层的模块。 自顶向下开发:首先对最高层进行编码和调试。
4.1.2 80C51汇编语言的伪指令 1. 汇编起始地址伪指令 汇编起始地址伪指令的一般格式如下: ORG表达式 例: ORG 3000H 第4章 汇编语言程序设计 4.1.2 80C51汇编语言的伪指令 1. 汇编起始地址伪指令 汇编起始地址伪指令的一般格式如下: ORG表达式 例: ORG 3000H START:MOV A,#7AH 解:这段程序汇编后目标代码在存储器中存放的起始地址是3000H。
4.1.2 80C51汇编语言的伪指令 2. 汇编结束伪指令 汇编结束伪指令一般格式如下: 格式1:〈字符名称〉END〈表达式〉 第4章 汇编语言程序设计 4.1.2 80C51汇编语言的伪指令 2. 汇编结束伪指令 汇编结束伪指令一般格式如下: 格式1:〈字符名称〉END〈表达式〉 格式2:〈字符名称〉END或者END 该指令是汇编语言源程序的结束标志,在END以后所写的指令,汇编程序都不予处理。因此,在一个源程序中只允许出现一个END语句,它必须放在整个程序的最后。
4.1.2 80C51汇编语言的伪指令 3. 赋值伪指令 赋值伪指令一般格式如下: 〈字符名称〉EQU〈表达式〉 第4章 汇编语言程序设计 4.1.2 80C51汇编语言的伪指令 3. 赋值伪指令 赋值伪指令一般格式如下: 〈字符名称〉EQU〈表达式〉 该指令的功能是将“表达式”赋给“字符名称”。 例:LOOPEQU2007H;LOOP=2007H 解:用EQU指令给一个字符名称赋值之后,在整个程序中该字符名称的值都是固定的,不能更改。若需更改,需用伪指令DL重新定义赋值。
4.1.2 80C51汇编语言的伪指令 4. 数据地址定义指令 数据地址定义指令一般格式如下: 〈字符名称〉DATA〈表达式〉 第4章 汇编语言程序设计 4.1.2 80C51汇编语言的伪指令 4. 数据地址定义指令 数据地址定义指令一般格式如下: 〈字符名称〉DATA〈表达式〉 DATA伪指令的功能与EQU有些相似,使用时要注意它们有以下区别: ①EQU伪指令必须先定义后使用,而DATA伪指令可以后定义先使用; ②用EQU伪指令可以把一个汇编符号赋给一个字符名称,而DATA只能把数据赋给字符名称; ③DATA伪指令可将一个表达式的值赋给一个字符名称,所定义的字符名称也可以出现在表达式中,而EQU定义的字符则不能这样使用。DATA伪指令在程序中常用来定义数据地址。
4.1.2 80C51汇编语言的伪指令 5.定义标号值伪指令 定义标号值伪指令一般格式如下: 〈字符名称〉DL〈表达式〉 第4章 汇编语言程序设计 4.1.2 80C51汇编语言的伪指令 5.定义标号值伪指令 定义标号值伪指令一般格式如下: 〈字符名称〉DL〈表达式〉 例:COUNT DL4064H ;定义标号COUNT的值为4064H COUNT DL COUNT+3 ;重新定义COUNT的值为4064H+3 解:DL和 EQU的功能都是将表达式值赋予标号,但两者有差别:可用DL语句在同一源程序中给同一标号赋予不同的值,即可更改已定义的标号值;而用EQU语句定义的标号,在整个源程序中不能更改。
4.1.2 80C51汇编语言的伪指令 6.定义字节伪指令 定义字节伪指令一般格式如下: 〈字符名称〉 DB 〈表达式或表达式列表〉 第4章 汇编语言程序设计 4.1.2 80C51汇编语言的伪指令 6.定义字节伪指令 定义字节伪指令一般格式如下: 〈字符名称〉 DB 〈表达式或表达式列表〉 定义字节伪指令是在程序存储器的某一部分存入一组8位二进制数,或者将一个数据表格存入程序存储器中。这个伪指令在汇编以后,将影响程序存储器的内容。 例:ORG4000H TABLE DB45H,67,100,32,00,-2
4.1.2 80C51汇编语言的伪指令 7. 定义字伪指令 定义字伪指令一般格式如下: 〈字符名称〉 DW 〈表达式或表达式表〉 第4章 汇编语言程序设计 4.1.2 80C51汇编语言的伪指令 7. 定义字伪指令 定义字伪指令一般格式如下: 〈字符名称〉 DW 〈表达式或表达式表〉 DW是从指定的地址开始定义若干16位数据,且把字的高字节数存入低地址单元,低字节数存入高地址单元,按顺序连续存放。 例:DW 7064H,1234H,209H 说明:表示按顺序存入70H,64H,12H,34H,02H,09H。
4.1.2 80C51汇编语言的伪指令 8. 定义存储区伪指令 定义存储区伪指令一般格式如下: 〈字符名称〉 DS 〈表达式〉 第4章 汇编语言程序设计 4.1.2 80C51汇编语言的伪指令 8. 定义存储区伪指令 定义存储区伪指令一般格式如下: 〈字符名称〉 DS 〈表达式〉 定义存储区伪指令是从指定的地址开始,保留若干字节的内存空间以作备用。汇编时,对这些单元不赋值。 例:ORG 4000H DS 9H DB 86H,A7H
4.1.2 80C51汇编语言的伪指令 9. 位地址符号伪指令 位地址符号伪指令一般格式如下: 〈字符名称〉 BIT 〈位地址〉 第4章 汇编语言程序设计 4.1.2 80C51汇编语言的伪指令 9. 位地址符号伪指令 位地址符号伪指令一般格式如下: 〈字符名称〉 BIT 〈位地址〉 位地址符号伪指令是对位地址赋予所规定的字符名称。 说明:其中,位地址可以是绝对地址,也可以是符号地址。 例:A1 BIT P2.1 A2 BIT P3.0
4.1.2 80C51汇编语言的伪指令 例:8051单片机常用伪指令的应用举例。 ORG 6070H BUFFER DS 45H 第4章 汇编语言程序设计 4.1.2 80C51汇编语言的伪指令 例:8051单片机常用伪指令的应用举例。 ORG 6070H BUFFER DS 45H DW “E F” DW 1100H,209H,-814 解:① 汇编后程序将6070H至60B4H空间作为缓冲区空间; ② (60B5H)= ‘E’,(60B6H)= ‘F’; ③ 60B7H单元起存放11H、00H、02H、09H、FCH、D2H 。
第4章 汇编语言程序设计 4.2 顺序结构程序设计 单片机程序设计和其他程序设计一样,程序结构一般采用以下三种基本控制结构,即顺序结构、分支结构和循环结构来组成,再加上使用广泛的子程序及中断服务子程序,共有五种基本结构。 所谓的顺序结构程序设计顺序结构是按照逻辑操作顺序,从某一条指令开始逐条顺序执行,直至某一条指令为止。
4.2.1 数据传送程序设计 例1:将R2与R3内容互换,R4与内存70H单元内容互换。 第4章 汇编语言程序设计 4.2.1 数据传送程序设计 例1:将R2与R3内容互换,R4与内存70H单元内容互换。 解:这个程序只需要利用交换指令和传送指令就可以完成,其程序段如下: XCHR:MOV A,R2 XCH A,R3 XCH A,R2 ;R2与R3内容互换 MOV A,R4 XCH A,70H XCH A,R4 ;R4与70H单元内容互换
第4章 汇编语言程序设计 4.2.1 数据传送程序设计 例2:现有两个双字节无符号数,分别存在R3R4H,R5R6中,高字节在前,低字节在后,通过编程使两数相加,和数存放在20H21H22H单元中。 解: ORG 4000H CLR C ;清C MOV A,R4 ;把被加数的低位放到A ADD A,R6 ;将加数和被加数的低位相加 MOV 22H,A ;把结果的低位存入22H单元 MOV A,R3 ;把被加数的高位放到A ADDC A,R5 ;将加数和被加数的高位相加 MOV 21H,A ;把结果的高位存入21H单元 MOV A,#00H ;清A ADDC A,#00H ;加进位 MOV 20H,A ;存和的进位 END
第4章 汇编语言程序设计 4.2.2 算术运算程序设计 例3:若a、b、c三个数分别存放在存储器40H、41H、42H单元中,试编写计算Y=a+b-c的程序。 解:根据题意要求,可先似a+b的运算,然后再做(a+b)-c的返算,计算结果送入存储器Y的单元中,由算法分析先画出程序执行的流程图,如图4-2所示。根据图4-2所示流程图,编写Y=a+b-c源程序如下: ORG START:MOV A,40H ;将a送给A ADD A,41H ;将a+b送给A CLR C ;清c SUBB A,42H ;将(a+b)-c送给A MOV 43H,A ;将A送给43H END
第4章 汇编语言程序设计 4.2.2 算术运算程序设计 例4:设被加数存放于片内RAM的20H(低位字节)、21H(高位字节),加数存放于22H(低位字节)和23H(高位字节),运算结果的和数存放于20H(低位字节)和21H(高位字节)中。实现16位相加。其程序段如下: START:PUSH ACC ;将A中内容进栈保护 MOV R0,#20H ;将20H地址送R0 MOV R1,#22H ;将22H地址值送R1 MOV A,@R0 ;被加数低字节内容送A ADD A,@R1 ;低字节数相加 MOV @R0,A ;低字节数和存20H中 INC R0 ;指向被加数高位字节 INC R1 ;指向加数高位字节
4.2.2 算术运算程序设计 MOV A,@R0 ;被加数高位字节送A ADDC A,@R1 ;高字节数带进位相加 第4章 汇编语言程序设计 4.2.2 算术运算程序设计 MOV A,@R0 ;被加数高位字节送A ADDC A,@R1 ;高字节数带进位相加 MOV @R0,A ;高字节数和存21H中 CLR A ADDC A, #00H MOV 10H, A ;进位暂存于10H中 POP ACC ;恢复A原内容 【说明】:这里将A原内容进栈保护,如果原R0、R1 内容有用,亦需进栈保护。如果相加结果高字节的最高位产生进位且有意义时,应对标志CY位检测并处理之。
4.2.3 延时程序设计 例5: 采用查询方式实现定时延时 ORG 0000H AJMP START ORG 30H 第4章 汇编语言程序设计 4.2.3 延时程序设计 例5: 采用查询方式实现定时延时 ORG 0000H AJMP START ORG 30H START: MOV P1,#0FFH ;关所 灯 MOV TMOD,#00000001B ;定时/计数器0工作于方式1 MOV TH0,#15H MOV TL0,#0A0H ;即数5536 SETB TR0 ;定时/计数器0开始运行
LOOP: JBC TF0,NEXT ; 如果TF0等于1, 则清TF0并转 第4章 汇编语言程序设计 4.2.3 延时程序设计 LOOP: JBC TF0,NEXT ; 如果TF0等于1, 则清TF0并转 NEXT处 AJMP LOOP ;否则跳转到LOOP处运行 NEXT: CPL P1.0 MOV TH0,#15H MOV TL0,#9FH ;重置定时/计数器的初值 AJMP LOOP END AJMP LOOP END
4.2.3 延时程序设计 例6: 采用中断方式实现定时延时 ORG 000BH ;定时器0的中断向量地址 第4章 汇编语言程序设计 4.2.3 延时程序设计 例6: 采用中断方式实现定时延时 ORG 000BH ;定时器0的中断向量地址 AJMP TIME0 ;跳转到真正的定时器程序处 ORG 30H START: MOV P1,#0FFH ;关所 灯 MOV TMOD,#00000001B ;定时/计数器0工作于方式1 MOV TH0,#15H MOV TL0,#0A0H ;即数5536 SETB EA ;开总中断允许 SETB ET0 ;开定时/计数器0允许 SETB TR0 ;定时/计数器0开始运行
4.2.3 延时程序设计 LOOP: AJMP LOOP ; 真正工作时,这里可写任意程序 第4章 汇编语言程序设计 4.2.3 延时程序设计 LOOP: AJMP LOOP ; 真正工作时,这里可写任意程序 TIME0: PUSH ACC ;定时器0的中断处理程序 PUSH PSW ;将PSW和ACC推入堆栈保护 CPL P1.0 MOV TH0,#15H MOV TL0,#0A0H ;重置定时常数 POP PSW POP ACC RETI END
第4章 汇编语言程序设计 4.3 分支程序设计 简分支选择结构 如果给出的条件满足要求,则转向程序段A,执行完程序段A后继续执行下一段指令;如果给出的条件不满足要求,则不转向,自接执行下一条指令。单分支选择结构如图所示。
例:比较两个无符号8位二进制数的大小,将较大的数存入高地址中。(设两数分别存于30和31H中。) 第4章 汇编语言程序设计 例:比较两个无符号8位二进制数的大小,将较大的数存入高地址中。(设两数分别存于30和31H中。) 解:这是一个简单的分支程序,可以让两数相减,若cy=l,则被减数小于减数。其程序段如下: ORG 4000H CLR C MOV A,30H SUBB A,31H JC NEXT XCH A,31H MOV A,3OH NEXT: NOP END
例:试编写计算下式的程序 Y=a2+b (当b≥10时) Y=a2-b (当b<10时) 第4章 汇编语言程序设计 第4章 汇编语言程序设计 例:试编写计算下式的程序 Y=a2+b (当b≥10时) Y=a2-b (当b<10时) ORG 0000H START:MOV A,#a MOV B,A MUL AB ;BA= a2 MOV R0,A;R1R0= a2 MOV R1,B MOV A,#b CJNE A,#0AH,MMN;b≠10则转移 MM:ADD AR0 ;b≥10,a2+b=Y MOV R0,A MOV A,#00H ADDC A,R1 MOV R1,A JMP MMNN MMN:JNC MM;无借位(即b>10)转MM MOV R3,A ;R3←b MOV A,R0 CLR C SUBB A,R3 ; R1R0←a2-b MOV R0,A MOV A,R1 SUBB A,#00H MOV R1,A MMNN:MOV Y0,R0 ;Y1Y0←结果 MOV Y1,R1 HERE:AJMP HERE
4.3 分支程序设计 ⒉ 多分支选择结构 第4章 汇编语言程序设计 第4章 汇编语言程序设计 4.3 分支程序设计 ⒉ 多分支选择结构 多分支结构程序又称散转程序,它是根据输入条件或者根据运算结果来确定转向相应的处理程序,不仅判断一个分支条件无法解决的问题,需要判断两个或两个以上的条件,通常也称为复合条件。
4.3 分支程序设计 80C51设有两条多重分支选择指令: ① 散转指令 【格式】:JMP @A+DPTR ② 比较指令 第4章 汇编语言程序设计 4.3 分支程序设计 80C51设有两条多重分支选择指令: ① 散转指令 【格式】:JMP @A+DPTR ② 比较指令 【格式】: CJNE A,direct,rel(共4条)
第4章 汇编语言程序设计 4.3 分支程序设计
4.3 分支程序设计 CLR C START: MOV R1,A SUBB A,#64H JNC BJ MOV A,R1 第4章 汇编语言程序设计 4.3 分支程序设计 根据图4-6所示流程图编写其源程序如下: CLR C START: MOV R1,A SUBB A,#64H JNC BJ MOV A,R1 CJNE A,#32H,LOOP1 MOV B,#2H MUL A B SJMP LOOP3 LOOP1: JC LOOP2 MOV B,#3H SUBB A,#32H MOV RO,A MOV A,#32H MOV B,#2H MUL A B ADD A,RO SJMP LOOP3 LOOP2 :MOV B,#2H MUL A B LOOP3: MOV 80H,A SJMP EOF BJ: ;超重报警程序
4.4 循环程序设计 循环程序通常由以下几个部分组成 1.设置循环初值 2.循环体 3.修改循环控制变量 4.循环控制部分 5.结束部分 第4章 汇编语言程序设计 4.4 循环程序设计 循环程序通常由以下几个部分组成 1.设置循环初值 2.循环体 3.修改循环控制变量 4.循环控制部分 5.结束部分
假设该单片机晶振为6MHz,试编制一个延时程序, 延时时间为1s. 第4章 汇编语言程序设计 假设该单片机晶振为6MHz,试编制一个延时程序, 延时时间为1s. 解:软件延时时间与单片机执行指令的时间有关,由己知条件可知晶振频率为6MHz的一个机器周期为2us,计算出执行每条指令和一个循环所需要的时间,根据要求的延时时间便可确定循环次数。若单循环延时不能达到ls可以采用多重循环方式实现。所谓多重循环,就是在一个循环体中又包含了其他的循环程序,即循环中又嵌套循环,这种循环程序则称为多重循环。源程序如下: DELY: MOV R5,#05H DELY0: MOV R6,#0C8H DELY1: MOV R7,#0F8H NOP DELY2: DJNZ R7,DELY2 DJNZ R6,DELY1 DJNZ R5,DELY0
第4章 汇编语言程序设计 把内部RAM中起始地址为DATA的数据串传送到外部RAM以BUFFER为首地址的区域,直到发现“$”字符的ASCII码为止,数据串的最大长度在内存20H中。 MOV R0,#DATA ;数据区首地址 MOV DPTR,#BUFFER;数据区长度指针 LOOP: MOV A,@R0 CJNE A,#24H ,LOOP2 ;判是否为“$”符(24H) SJMP LOOP1 ;是“$”符,则结束 LOOP2:MOV A,@R0 ;不是“$”符,则传送 MOVX @DPTR,A INC R0 INC DPTR DJNZ 20H,LOOP ;数据串未查完,继续 LOOP1:RET DATA:… ;数据串
第4章 汇编语言程序设计 4.5子程序设计 子程序在结构上与主程序的结构没有根本的区别,子程序也可以由简单结构、分支结构或循环结构构成。不同的是在于程序在操作的过程中需要由其他程序来调用,执行完以后又需要将执行流程返回到调用该子程序的程序中。子程序的执行过程如图所示。
4.5子程序设计 1.子程序的调用过程 主程序与子程序之间的参数传递。 保护现场和恢复现场。 第4章 汇编语言程序设计 4.5子程序设计 1.子程序的调用过程 主程序与子程序之间的参数传递。 保护现场和恢复现场。 当然对每个具体的子程序哪些参数应当保护,是不是需要现场保护,还应视实际情况确定。
第4章 汇编语言程序设计 4.5子程序设计 ⒉ 常用子程序举例 例1: 四位BCD码整数转换成二进制整数子程序。入口参数:BCD码字节地址指针R0、位数(n-l)存于R2中。出口参数:二进制数存放于R3、R4中。处理方法:A=a3×103十a2×102+al×101+a0×100 其子程序如下:
4.5子程序设计 第4章 汇编语言程序设计 MUL AB BCDB:PUSH PSW;现场保护 ADD A,R3 PUSH ACC 第4章 汇编语言程序设计 4.5子程序设计 MUL AB ADD A,R3 XCH A,R4 INC R0 ADD A,@R0 XCH A,R3 ;(R3R4)+((R0))送R3R4 ADDC A,#0 MOV R4,A DJNZ R2,LOOP1 ;循环n-l次 POP B ;恢复现场 POP ACC POP PSW RET ;返回 BCDB:PUSH PSW;现场保护 PUSH ACC PUSH B MOV R3,#00H MOV A,@R0 MOV R4,A ;BCD码千位送R4 LOOP:MOV A,R4 MOV B,#10 MUL AB MOV R4,A MOV B,#10 ;(R3)、(R4)×10 XCH A,B ;交换 XCH A,R3
第4章 汇编语言程序设计 4.5子程序设计 例2:中值数字滤波子程序。为了保证采集数据的稳定和不受千扰影响,除了采用硬件滤波电路外,还常常应用软件来进行数字滤波。中值滤波就是连续输入三个检测信号,从中选择一个中间值为有效信号。入口条件:三次采集数据分别存储在内部存储器的20H、21H和22H中。出口结果:中间值在R0寄存器中。使用资源:累加器A、R0及内存20H、21H和22H。 其子程序如下:
第4章 汇编语言程序设计 FILLE: PUSH PSW ;PSW及ACC保护入栈 PUSH ACC MOV A,20H;取第一个数据 CLR C SUBB A,21H ;与第二个数据比较 JNC LOB1 ;第一个数据比第二个数据大,转LOB1 MOV A,20H ;第一个数据比第二个数据小,交换二个数的位置 XCH A,21H MOV 20H,A LOB1: MOV A,22H SUBB A,20H ;第三个数据与前二个数据中的较大数比较 JNC LOB3 ;第三个数据大于前二个数据中的较大数,转LOB3 MOV A,22H CLR C SUBB A,21H ;第三个数据与前二个数据中的较小数比较 JNC LOB4 MOV A,21H MOV R0,A LOB2: POP ACC ;恢复ACC和PSW POP PSW RET
4.6 单片机程序设计流程 4.6.1编程语言 80C51的软件设计可以采用汇编语言或高级语言。 第4章 汇编语言程序设计 4.6 单片机程序设计流程 4.6.1编程语言 80C51的软件设计可以采用汇编语言或高级语言。 汇编语言具有源代码小、效率高等优点,适合于对实时性要求较高的场合。 但是由于汇编语言调试比较麻烦,要求编程者对硬件的了解要很清楚。 随着高级语言的发展,编译效率的不断提高,加之应用系统的规模和复杂性都在提高。目前,在单片机的软件开发中,高级语言占据重要的地位。
4.6.2 单片机汇编语言开发流程 用汇编语言编写程序,一般可分为以下几个步骤: 第4章 汇编语言程序设计 4.6.2 单片机汇编语言开发流程 用汇编语言编写程序,一般可分为以下几个步骤: (1)建立数学模型:根据要解决的实际问题,反复研究分析并抽象出数学模型。 (2)确定算法:解决一个问题,往往有多种不同的方法,要从诸多算法中确定一种较为简捷的方法是至关重要的。 (3)制定程序流程图:算法是程序设计的依据, (4)确定数据结构:合理地选择和分配内存单元以及工作寄存器。 (5)写出源程序:根据程序流程图,精心选择合适的指令和寻址方式来编制源程序。 (6)机调试程序:将编好的源程序进行汇编,并执行目标程序,检查和修改程序中的错误的结果进行分析,直到正确为止。
4.6.3单片机C语言开发流程 1、编写C源程序 2、编译源程序生成目标文件 3、仿真调试目标文件 4、目标文件的烧写 第4章 汇编语言程序设计 4.6.3单片机C语言开发流程 1、编写C源程序 2、编译源程序生成目标文件 3、仿真调试目标文件 4、目标文件的烧写