78
第 4 第 第第第第第第第第第第第 第 4 第 第第第第第第第第

第 4 章 汇编语言程序设计

  • Upload
    yorick

  • View
    148

  • Download
    0

Embed Size (px)

DESCRIPTION

第 4 章 汇编语言程序设计. 4.1 单片机程序设计语言概述. 所谓程序设计,就是按照给定的任务要求,编写出完整的计算机程序。要完成同样的任务,使用的方法或程序并不是唯一的。因此,程序设计的质量将直接影响到计算机系统的工作效率、运行可靠性。. 4.1.1 按照语言的结构及其功能可以分为三种 1 .机器语言:机器语言是用二进制代码 0 和 1 表示指令和数据的最原始的程序设计语言。 2 .汇编语言:在汇编语言中,指令用助记符表示,地址、操作数可用标号、符号地址及字符等形式来描述。 3 .高级语言:高级语言是接近于人的自然语言,面向过程而独立于机器的通用语言。. - PowerPoint PPT Presentation

Citation preview

Page 1: 第 4 章 汇编语言程序设计

第 4 章 单片机汇编语言程序设计

第 4 章 汇编语言程序设计

Page 2: 第 4 章 汇编语言程序设计

第 4 章 单片机汇编语言程序设计

所谓程序设计,就是按照给定的任务要求,编写出完整的计算机程序。要完成同样的任务,使用的方法或程序并不是唯一的。因此,程序设计的质量将直接影响到计算机系统的工作效率、运行可靠性。

4.1 单片机程序设计语言概述

Page 3: 第 4 章 汇编语言程序设计

第 4 章 单片机汇编语言程序设计

4.1.1 按照语言的结构及其功能可以分为三种

• 1 .机器语言:机器语言是用二进制代码 0 和 1 表示指令和数据的最原始的程序设计语言。

• 2 .汇编语言:在汇编语言中,指令用助记符表示,地址、操作数可用标号、符号地址及字符等形式来描述。

• 3 .高级语言:高级语言是接近于人的自然语言,面向过程而独立于机器的通用语言。

Page 4: 第 4 章 汇编语言程序设计

第 4 章 单片机汇编语言程序设计

机器语言( Machine Language )

直接用机器码编写程序、能够为计算机直接执行的机器级语言。机器码是一串由二进制代码“ 0” 和“ 1” 组成的二进制数据,其执行速度快,但是可读性极差。机器语言一般只在简单的开发装置中使用,程序的设计、输入、修改和调试都很麻烦。

Page 5: 第 4 章 汇编语言程序设计

第 4 章 单片机汇编语言程序设计

汇编语言( Assembly Language )

指用指令助记符代替机器码的编程语言。汇编语言程序结构简单,执行速度快,程序易优化,编译后占用存储空间小,是单片机应用系统开发中最常用的程序设计语言。汇编语言的缺点是可读性比较差,只有熟悉单片机的指令系统,并具有一定的程序设计经验,才能研制出功能复杂的应用程序。

Page 6: 第 4 章 汇编语言程序设计

第 4 章 单片机汇编语言程序设计

高级语言( High-Level Language )

在汇编语言的基础上用自然语言的语句来编写程序,例如 PL/M-51 、 C51 等,程序可读性强,通用性好,适用于不熟悉单片机指令系统的的用户。

高级语言编写程序的缺点是实时性不高,结构不紧凑,编译后占用存储空间比较大,这一点在存储器有限的单片机应用系统中没有优势。

因而,单片机的汇编语言不但不会被高级语言完全取代,甚至还将继续占据重要地位。

Page 7: 第 4 章 汇编语言程序设计

第 4 章 单片机汇编语言程序设计 4.1.2 汇编语言语句的种类和格式

汇编语言语句有三种基本类型:指令语句、伪指令语句和宏指令语句。

指令语句:每一个指令语句都在汇编时产生一个目标代码,对应着机器的一种操作。

例如: MOV A , #0

伪指令语句:主要是为汇编语言服务的,在汇编时没有目标代码与之对应。

例如: ONE EQU 1

宏指令语句:用以代替汇编语言源程序中重复使用的程序段的一种语句,由汇编程序在汇编时产生相应的目标代码。

Page 8: 第 4 章 汇编语言程序设计

第 4 章 单片机汇编语言程序设计

汇编语言语句的格式

指令语句和伪指令语句的格式是类似的。

指令语句的格式为:

【标号】:助记符 ( 操作码)【操作数】 ;【注释】

伪指令语句的格式:

名字 定义符 参数 ;注释

两种语句都由四个部分组成。其中每一部分称为域也称为字段,各字段之间用一个空格或字段定界符分隔,常用的字段定界符有冒号“:” 、逗号“,”和分号“;”。其中方括号括起来的是可选择部分。

Page 9: 第 4 章 汇编语言程序设计

第 4 章 单片机汇编语言程序设计

4.2 80C51 汇编语言程序设计 汇编语言程序设计,就是采用汇编指令来编写计算机程

序。要对应用中需使用的寄存器、存储单元、 I/O 端口等先要作出具体安排。在实际编程中,如何正确选择指令、寻址方式和合理使用工作寄存器,包括数据存储器单元,如何对扩展的 I/O 端口进行操作等,都是基本的汇编语言程序设计技巧。

程序结构一般采用以下三种基本控制结构,即顺序结构、分支结构和循环结构来组成,再加上使用广泛的子程序及中断服务子程序,共有五种基本结构。

Page 10: 第 4 章 汇编语言程序设计

第 4 章 单片机汇编语言程序设计

4.2.1 顺序程序结构

例 1 两个无符号双字节数相加。

设被加数存放于内部 RAM 的 40H (高位字节) , 41H

(低位字节) , 加数存放于 50H (高位字节) , 51H (低位字节) , 和数存入 40H 和 41H 单元中。

Page 11: 第 4 章 汇编语言程序设计

第 4 章 单片机汇编语言程序设计

程序如下 :

START: CLR C ; 将 Cy 清零

MOV R0, # 41H ; 将被加数地址送数据指针 R0

MOV R1, # 51H ; 将加数地址送数据指针 R1

AD1: MOV A, @R0 ; 被加数低字节的内容送入 A

ADD A,@R1 ; 两个低字节相加

MOV @R0, A ; 低字节的和存入被加数低字节中

DEC R0 ; 指向被加数高位字节

DEC R1 ; 指向加数高位字节

MOV A, @R0 ; 被加数高位字节送入 A

ADDC A, @R1 ; 两个高位字节带 Cy 相加

MOV @R0, A ; 高位字节的和送被加数高位字节

RET

Page 12: 第 4 章 汇编语言程序设计

第 4 章 单片机汇编语言程序设计

例 2 将两个半字节数合并成一个一字节数。

设内部 RAM 40H#, 41H 单元中分别存放着 8 位二进制数 , 要求取出两个单元中的低半字节 , 并成一个字节后 , 存入 50H 单元中。 程序如下 :

START: MOV R1, # 40H ; 设置 R1 为数据指针

MOV A, @R1 ; 取出第一个单元中的内容

ANL A, # 0FH ; 取第一个数的低半字节

SWAP A ; 移至高半字节

INC R1 ; 修改数据指针

XCH A, @R1 ; 取第二个单元中的内容

ANL A, # 0FH ; 取第二个数的低半字节

ORL A, @R1 ; 拼字

MOV 50H, A ; 存放结果

RET

Page 13: 第 4 章 汇编语言程序设计

第 4 章 单片机汇编语言程序设计

4.2.2 分支程序设计

分支结构框图(a) 单分支流程 ; (b) 多分支流程

Page 14: 第 4 章 汇编语言程序设计

第 4 章 单片机汇编语言程序设计

例 3 x, y 均为 8 位二进制数 , 设 x 存入 R0, y 存入 R1, 求解 :

0

1

1

y

0

0

0

x

x

x

Page 15: 第 4 章 汇编语言程序设计

第 4 章 单片机汇编语言程序设计

程序如下 :

START: CJNE R0, # 00H, SUL1; R0 中的数与 00 比较不等转移 MOV R1, # 00H; 相等 , R1← 0

SJMP SUL2

SUL1: JC NEG ; 两数不等 , 若( R0 ) <0, 转向 NEG

MOV R1, # 01H ; ( R0 ) >0, 则 R1←01H

SJMP SUL2

NEG: MOV R1, # 0FFH ; ( R0 ) <0, 则 R1←0FFH

SUL2: RET

Page 16: 第 4 章 汇编语言程序设计

第 4 章 单片机汇编语言程序设计 例 4 比较两个无符号数的大小。

设外部 RAM 的存储单元 ST1 和 ST2 中存放两个不带符号的二进制数 , 找出其中的大数存入外部 RAM 中的 ST3 单元中。

Page 17: 第 4 章 汇编语言程序设计

第 4 章 单片机汇编语言程序设计

程序如下:

ORG 1000H

ST1 EQU 2000H

ST2 EQU 2100H

ST3 EQU 2200H

START: CLR C ; 清零 Cy

MOV DPTR, # ST1 ; 第一个数的指针

MOVX A, @DPTR ; 取第一个数

MOV R2, A ; 保存

MOV DPTR, # ST2 ; 第二个数的指针

MOVX A, @DPTR ; 取第二个数

CLR C

Page 18: 第 4 章 汇编语言程序设计

第 4 章 单片机汇编语言程序设计

SUBB A, R2; 两数比较

JNC BIG1 ; 若第二个数大 , 则转

XCH A, R2; 第一个数大

BIG0: MOV DPTR, # ST3

MOVX @DPTR, A ; 存大数

AJMP B

BIG1: MOVX A, @DPTR; 第二个数大

SJMP BIG0

B: RET

Page 19: 第 4 章 汇编语言程序设计

第 4 章 单片机汇编语言程序设计

Page 20: 第 4 章 汇编语言程序设计

第 4 章 单片机汇编语言程序设计

4.2.3 循环程序设计 一、 循环程序

Page 21: 第 4 章 汇编语言程序设计

第 4 章 单片机汇编语言程序设计

循环程序一般由四个主要部分组成 :

(1) 初始化部分 : 为循环程序做准备 , 如规定循环次数、 给各变量和地址指针预置初值。

(2) 处理部分 : 为反复执行的程序段 , 是循环程序的实体 ,

也是循环程序的主体。

(3) 循环控制部分 : 这部分的作用是修改循环变量和控制变量 , 并判断循环是否结束 , 直到符合结束条件时 , 跳出循环为止。

(4) 结束部分 : 这部分主要是对循环程序的结果进行分析、 处理和存放。

Page 22: 第 4 章 汇编语言程序设计

第 4 章 单片机汇编语言程序设计

例 5 工作单元清零。

在应用系统程序设计时 , 有时经常需要将存储器中各部分地址单元作为工作单元 , 存放程序执行的中间值或执行结果 , 工作单元清零工作常常放在程序的初始化部分中。

设有 50 个工作单元 , 其首址为外部存储器 8000H 单元 ,

则其工作单元清零程序如下 :

Page 23: 第 4 章 汇编语言程序设计

第 4 章 单片机汇编语言程序设计

CLEAR: CLR A

MOV DPTR, # 8000H ; 工作单元首址送指

针 MOV R2, #50 ; 置循环次数

CLEAR1: MOVX @DPTR, A

INC DPTR ; 修改指针

DJNZ R2, CLEAR1; 控制循环

RET

Page 24: 第 4 章 汇编语言程序设计

第 4 章 单片机汇编语言程序设计 例 6 设在内部 RAM 的 BLOCK 单元开始处有长度为 LEN 的无符号数据块 , 试编一个求和程序 , 并将和存入内部 RAM 的 SUM 单元(设和不超过 8 位)。

BLOCK EQU 20H

LEN EQU 30H

SUM EQU 40H

START: CLR A ; 清累加器 A

MOV R2, # LEN; 数据块长度送 R2

MOV R1, # BLOCK ; 数据块首址送 R1

LOOP: ADD A, @R1 ; 循环加法

INC R1; 修改地址指针

DJNZ R2, LOOP ; 修改计数器并判断

MOV SUM, A; 存和

RET

Page 25: 第 4 章 汇编语言程序设计

第 4 章 单片机汇编语言程序设计 二、 多重循环

例 7 10 秒延时程序。

延时程序与 MCS - 51 执行指令的时间有关 , 如果使用 12 MHz晶振 , 一个机器周期为 1 μs, 计算出一条指令以至一个循环所需要的执行时间 , 给出相应的循环次数 , 便能达到延时的目的。 10 秒延时程序如下 :

DELAY: MOV R5, # 100

DEL0: MOV R6, # 200

DEL1: MOV R7, # 248

NOP

DEL2: DJNZ R7, DEL2

DJNZ R6, DEL1

DJNZ R5, DEL0

RET

Page 26: 第 4 章 汇编语言程序设计

第 4 章 单片机汇编语言程序设计

上例程序中采用了多重循环程序 , 即在一个循环体中又包含了其它的循环程序 , 这种方式是实现延时程序的常用方法。 使用多重循环时 , 必须注意 :

(1 ) 循环嵌套 , 必须层次分明 , 不允许产生内外层循环交叉。

(2 ) 外循环可以一层层向内循环进入 , 结束时由里往外一层层退出。

(3 ) 内循环可以直接转入外循环 , 实现一个循环由多个条件控制的循环结构方式。

Page 27: 第 4 章 汇编语言程序设计

第 4 章 单片机汇编语言程序设计

外循环

中循环

内循环

外循环

内循环

外循环

内循环

内循环

( a )嵌套正确

( b )嵌套正确 ( c )交叉不正确

多重循环示意图

Page 28: 第 4 章 汇编语言程序设计

第 4 章 单片机汇编语言程序设计

例 8 设某系统的模数转换器是 ADC0809, 它的转换结束信号 EOC连接到 8031 的 P1.7端 , 当 EOC 的状态由低变高时 , 则结束循环等待 , 并读取转换值 , 其程序如下 :

START: MOV DPTR, # addr ; 0809端口地址送 DPTR

MOV A, # 00H ; 启动 0809 转换

MOVX @DPTR, A

LOOP: JNB P1.7, LOOP; 检测 P1.7状态 , 判是否转换结束

MOVX A, @DPTR; 读取转换结果…

Page 29: 第 4 章 汇编语言程序设计

第 4 章 单片机汇编语言程序设计

例 9 在内部 RAM 中从 50H 单元开始的连续单元依次存放了一串字符 , 该字符串以回车符为结束标志 , 要求测试该字符串的长度。

Page 30: 第 4 章 汇编语言程序设计

第 4 章 单片机汇编语言程序设计

ASCII 码 表

Page 31: 第 4 章 汇编语言程序设计

第 4 章 单片机汇编语言程序设计

程序如下 :

START: MOV R2, # 0FFH

MOV R0, # 4FH ; 数据指针 R0 置初值

LOOP: INC R0

INC R2

CJNE @R0, # 0DH, LOOP

RET

Page 32: 第 4 章 汇编语言程序设计

第 4 章 单片机汇编语言程序设计

4.2.4 散转程序设计

散转程序是分支程序的一种 , 它可根据运算结果或输入数据将程序转入不同的分支。 MCS - 51 指令系统中有一条跳转指令 JMP@A+DPTR, 用它可以很容易地实现散转功能。该指令把累加器的 8 位无符号数与 16 位数据指针的内容相加 , 并把相加的结果装入程序计数器 PC, 控制程序转向目标地址去执行。此指令的特点在于 , 转移的目标地址不是在编程或汇编时预先确定的 , 而是在程序运行过程中动态地确定的。目标地址是以数据指针 DPTR 的内容为起始的 256

字节范围内的指定地址 , 即由 DPTR 的内容决定分支转移程序的首地址 , 由累加器 A 的内容来动态选择其中的某一个分支转移程序。

Page 33: 第 4 章 汇编语言程序设计

第 4 章 单片机汇编语言程序设计

K=?

转 SUB0 转 SUB1 转 SUB6

K=0 K=1 …… K=6

开始

JMP@A+DPTR,

Page 34: 第 4 章 汇编语言程序设计

第 4 章 单片机汇编语言程序设计

数据排序程序数据的排序,其算法很多,常用的有插入排序法、冒泡排

序法、快速排序法、选择排序法、堆积排序法、二路归并排序法及基数排序法等。

冒泡法是一种相邻数互换的排序方法,其过程类似水中气泡上浮。执行时从前向后进行相邻数比较,若数据的大小次序与要求的顺序不符时 ( 逆序 ) ,就将二数互换,正序时不交换,假定是升序排序,则通过这种相邻数互换方法,使小数向前移,大数向后移,为此从前向后进行一次冒泡(相邻数互换),就会把最大数换到最后,再进行一次冒泡,就会把次大数排在倒数第二,直至冒泡结束。

应用举例:

Page 35: 第 4 章 汇编语言程序设计

第 4 章 单片机汇编语言程序设计

说明:

⑴ 每次冒泡都从向后排定了一个大数(升序),每次冒泡所需进行 的比较次数都递减,例如有 n 个数排序,则第一次冒泡需比较( n-1 )次,第二次冒泡则需( n-2 )次,依此类推,但实际编程中为了简化程序,往往把各次比较次数都固定为( n-1 )次。

⑵ 对于 n 个数,理论上说应进行( n-1 )次冒泡才能完成排序,但实际上往往不到( n-1 )次就已排好序。判定排序是否完成的最简单方法是每次冒泡中是否有互换发生,如果有互换发生,说明排序还没完成,否则就表示已排好序,为此控制排序结束常不使用计数方法,而使用设置互换标志的方法,以其状态表示在一次冒泡中有无数据互换进行。

Page 36: 第 4 章 汇编语言程序设计

第 4 章 单片机汇编语言程序设计

统计的数值分别存入 20H~ 29H 中。

CLR A ;结果单元 20H~ 29H清零

MOV R0,#10

MOV R1,#20H

LP : MOV @R1,A

INC R1

DJNZ R0,LP

MOV R0,#100 ; 100 个数的计数器

READ : MOV A,P1 ;读入 P1

例 10. 对从 P1 口输入的 100 个 0~ 9 的数进行概率统计。

Page 37: 第 4 章 汇编语言程序设计

第 4 章 单片机汇编语言程序设计

CHK0 : CJNE A,#0,CHK1 ;比较,不为“ 0” ,继续比较

INC 20H ;是“ 0” ,则“ 0” 计数单元加 1

SJMP END0 ;是否全部统计完?

CHK1 : CJNE A,#1,CHK2

INC 21H ;是“ 1” ,则“ 1” 计数单元加 1

SJMP END0

CHK2 : CJNE A,#2,CHK3

INC 22H ;是“ 2” ,则“ 2” 计数单元加 1

SJMP END0

Page 38: 第 4 章 汇编语言程序设计

第 4 章 单片机汇编语言程序设计

CHK3 : CJNE A,#3,CHK4

INC 23H ;是“ 3” ,则“ 3” 计数单元加 1

SJMP END0

CHK4 : CJNE A,#4,CHK5

INC 24H ;是“ 4” ,则“ 4” 计数单元加 1

SJMP END0

CHK5 : CJNE A,#5,CHK6

INC 25H ;是“ 5” ,则“ 5” 计数单元加 1

SJMP END0

Page 39: 第 4 章 汇编语言程序设计

第 4 章 单片机汇编语言程序设计

CHK6 : CJNE A,#6,CHK7

INC 26H ;是“ 6” ,则“ 6” 计数单元加 1

SJMP END0

CHK7 : CJNE A,#7,CHK8

INC 27H ;是“ 7” ,则“ 7” 计数单元加 1

SJMP END0

Page 40: 第 4 章 汇编语言程序设计

第 4 章 单片机汇编语言程序设计

CHK8 : CJNE A,#8,CHK9

INC 28H ;是“ 8” ,则“ 8” 计数单元加 1

SJMP END0

CHK9 : CJNE A,#9,ERR

INC 29H ;是“ 9” ,则“ 9” 计数单元加 1

END0 : DJNZ R0,READ ;判是否全部统计完?

HERE : SJMP HERE

ERR :… ;非 0~ 9 ,出错

Page 41: 第 4 章 汇编语言程序设计

第 4 章 单片机汇编语言程序设计

Page 42: 第 4 章 汇编语言程序设计

第 4 章 单片机汇编语言程序设计

4.2.5 子程序和参数传递

一、 子程序的概念

通常把一些基本操作功能编制为程序段作为独立的子程

序 , 以供不同程序或同一程序反复调用。在程序中需要执行

这种操作的地方放置一条调用指令 , 当程序执行到调用指令 ,

就转到子程序中完成规定的操作 , 并返回到原来的程序继续

执行下去。

Page 43: 第 4 章 汇编语言程序设计

第 4 章 单片机汇编语言程序设计

二、 子程序的调用

调用子程序的指令有“ ACALL” 和“ LCALL”, 执行调

用指令时 , 先将程序地址指针 PC 改变(“ ACALL” 加 2,

“LCALL” 加 3 ) , 然后 PC值压入堆栈 , 用新的地址值代替。

执行返回指令时 , 再将 PC值弹出。

子程序调用中 , 主程序应先把有关的参数存入约定的位

置 , 子程序在执行时 , 可以从约定的位置取得参数 , 当子程

序执行完 , 将得到的结果再存入约定的位置 , 返回主程序后 ,

主程序可以从这些约定的位置上取得需要的结果 , 这就是参

数的传递。

Page 44: 第 4 章 汇编语言程序设计

第 4 章 单片机汇编语言程序设计

子程序调用与返回过程示意图

Page 45: 第 4 章 汇编语言程序设计

第 4 章 单片机汇编语言程序设计

在汇编语言源程序中使用子程序时,一般要注意两个问题:参数传递和现场保护。

1 、参数传递一般可采用以下方法:• 传递数据。将数据通过工作寄存器 R0~ R7 或累加器来传送。即主程序和子程序在交接处,上述寄存器和累加器存储的是同一参数。

• 传送地址。数据存放在数据寄存器中,参数传递时只通过 R0 、 R1 、 DPTR传递数据所存放的地址。

• 通过堆栈传递参数。在调用之前,先把要传送的参数压入堆栈,进入子程序之后,再将压入堆栈的参数弹出到工作寄存器或者其他内存单元。

Page 46: 第 4 章 汇编语言程序设计

第 4 章 单片机汇编语言程序设计

2 、 保护现场与恢复现场

在调用子程序时,单片微机只是自动保护断点地址,但由调用程序转入子程序执行时,往往会破坏主程序或调用程序的有关寄存器(如工作寄存器和累加器等)的内容,也很可能破坏程序状态字 PSW 中的标志位,从而在子程序返回后引起出错。因此,必要时应将这些单元内容保护起来,即保护现场。对于 PSW 、 A 、 B 等可通过压栈指令进栈保护。工作寄存器采用选择不同工作寄存器组的方式来达到保护的目的。一般主程序选用工作寄存器组 0 ,而子程序选用工作寄存器的其它组。

当子程序执行完后,即返回主程序时,应先将上述内容送回到来时的寄存器中去,这后一过程称为恢复现场。对于 PSW 、A 、 B 等内容可通过弹栈指令来恢复。

在编写子程序时,还应注意保护(压栈)和恢复(弹出)的顺序,即先压入者后弹出。

Page 47: 第 4 章 汇编语言程序设计

第 4 章 单片机汇编语言程序设计

【例 11】单字节二进制数据转换为 BCD 码子程序 SBTOD 。 功能:将单字节二进制数转换为三位 BCD 码。 入口: R2 中存放要转换的二进制数。 出口: (R0) 给出百位 BCD 码的存放地址。 (R0)+1 给出十位和个位 BCD 码的存放地址,高半字节放十位,低半字节放个位。 占用寄存器: A , B , R0 , R2 。A累加器的内容不受影响。

Page 48: 第 4 章 汇编语言程序设计

第 4 章 单片机汇编语言程序设计

 

 

 

 

   

SBTOD : MOV SP , #60H    PUSH ACC    MOV A , R2 ;取数  MOV B , #64H    DIV AB ;除以 100 , (A) 为百位数  MOV @R0 , A ;存人 (R0) 单元  MOV A , #0AH    XCH A , B ;余数 (B) 送 A  DIV A , B ;除以 10 ,得十位和个位  SWAP A ;十位数放于高半字节  ADD A , B ;个位数放于低半字节  INC R0    MOV @R0 , A ;个位存入 (R0)+1 单元  POP ACC    RET    

Page 49: 第 4 章 汇编语言程序设计

第 4 章 单片机汇编语言程序设计

【例 12】求两个无符号数据块中的最大值。数据块的首地址分别为 60H 和 70H ,每个数据块的第一个字节都存放数据块的长度,结果存入 5FH 单元。

解 本例可采用分别求出两个数据块的最大值,然后比较其大小的方法,求最大值的过程可采用子程序。

子程序名称: QMAX 。 子程序入口条件: R1 中存有数据块首地址。 出口条件:最大值在 A 中。 下面分别编写主程序和子程序。

Page 50: 第 4 章 汇编语言程序设计

第 4 章 单片机汇编语言程序设计

主程序:   ORG 2000H  

  MOV SP , #2FH ;设堆栈指针

  MOV R1 , #60H ;取第一数据块首地址送 R1 中

  ACALL QMAX ;第一次调用求最大值子程序

  MOV 40H , A ;第一个数据块的最大值暂存 40H

  MOV R1 , #70H ;取第二数据块首地址送 R1 中

  ACALL QMAX ;第二次调用求最大值子程序

  CJNE A , 40H , NEXT ;两个最大值进行比较

NEXT : JNC LP ; A 大,则转 LP

  MOV A , 40H ; A 小,则把 40H 中内容送人 A

LP : MOV 5FH , A  

  SJMP $  

Page 51: 第 4 章 汇编语言程序设计

第 4 章 单片机汇编语言程序设计 子程序:   ORG 2200H  

QMAX:

MOV A , @R1 ;取数据块长度

  MOV R2 , A ; R2做计数器

  CLR A ;清零,准备做比较

LP1 : INC R1 ;指向下一个数据地址

CLR C ;准备做减法

SUBB A , @R1 ;用减法做比较

  JNC LP3 ;若 A 大,则转 LP3

  MOV A , @R1 ; A 小,则将大数送 A 中

SJMP LP4 ;五条件转 LP4

LP3 : ADD A , @R1 ;恢复 A 中值

LP4 : DJNZ R2 , LP1 ;计数器减 1 ,不为零,转继续比较

  RET   ;比较完,子程序返回

Page 52: 第 4 章 汇编语言程序设计

第 4 章 单片机汇编语言程序设计

三、子程序设计三、子程序设计子程序的调用与返回子程序的调用与返回MCS-51MCS-51 单片机有两条子程序调用指令:单片机有两条子程序调用指令: ACALL addr11ACALL addr11 、 、

LCALL addr16LCALL addr16 ;一条子程序返回指令;一条子程序返回指令 RETRET 。 。 保存与恢复寄存器内容保存与恢复寄存器内容

例如:例如: SUB1: SUB1: PUSH PSW PUSH PSW PUSH APUSH A PUSH R6PUSH R6 ∶∶ (( 此处省略了子程序的内容此处省略了子程序的内容 ))

∶∶ POP R6POP R6 POP APOP A PUSH PSWPUSH PSW

Page 53: 第 4 章 汇编语言程序设计

第 4 章 单片机汇编语言程序设计

【例【例 13 13 】 编程计算 】 编程计算

编程说明:这个问题中,计算某数的平方可以用子程编程说明:这个问题中,计算某数的平方可以用子程序来实现,两次调用该子程序,并求和便得到所需序来实现,两次调用该子程序,并求和便得到所需结果。设结果。设 aa 、、 b b 分别存于内部分别存于内部 RAM RAM 的的 30H30H 、、 3131HH 单元,结果单元,结果 CC 存于内部存于内部 RAMRAM 的的 40H40H 单元。单元。

22 bac

Page 54: 第 4 章 汇编语言程序设计

第 4 章 单片机汇编语言程序设计

参数传递:主程序中,将某数存放到累参数传递:主程序中,将某数存放到累加器加器 AA 中,作为子程序的入口参数;子程序中,中,作为子程序的入口参数;子程序中,将所求数的平方值存放在累加器将所求数的平方值存放在累加器 AA 中,作为出中,作为出口参数(即主程序的返回值)。口参数(即主程序的返回值)。

子程序的入口参数:子程序的入口参数: AA 中存放某数的值。中存放某数的值。子程序的出口参数:子程序的出口参数: AA 中存放所求数的中存放所求数的

平方。平方。子程序如下:子程序如下:

SQR: SQR: INC AINC A MOVC A , @A+PC MOVC A , @A+PC ;查平方表;查平方表 RETRET

TABLE: TABLE: DB 0 , 1 , 4 , 9 , 16DB 0 , 1 , 4 , 9 , 16 DB 25 , 36 , 49 , 64 , 81DB 25 , 36 , 49 , 64 , 81

Page 55: 第 4 章 汇编语言程序设计

第 4 章 单片机汇编语言程序设计

Page 56: 第 4 章 汇编语言程序设计

第 4 章 单片机汇编语言程序设计

主程序如下:主程序如下:START: START: MOV A , 30HMOV A , 30H

ACALL SQR ACALL SQR ;调查表子程序;调查表子程序 MOV R1 , A MOV R1 , A ;; a2a2暂存暂存 R1R1 中中 MOV A , 31H MOV A , 31H

ACALL SQR ACALL SQR ;调查表子程序;调查表子程序 ADD A , R1ADD A , R1

MOV 40H , AMOV 40H , A

ENDEND

Page 57: 第 4 章 汇编语言程序设计

第 4 章 单片机汇编语言程序设计

4.2.6 查表程序设计

查表程序是一种常用程序 , 它广泛使用于 LED显示控制、 打印机打印控制、数据补偿、数值计算、转换等功能程序中 ,

这类程序具有简单、执行速度快等特点。

所谓查表法 , 就是预先将满足一定精度要求的表示变量与函数值之间关系的一张表求出 , 然后把这张表存于单片机的程序存储器中 , 这时自变量值为单元地址 , 相应的函数值为该地址单元中的内容。查表 , 就是根据变量 X 在表格中查找对应的函数值 Y, 使 Y=f(X) 。

Page 58: 第 4 章 汇编语言程序设计

第 4 章 单片机汇编语言程序设计

MCS - 51 指令系统中 , 有两条查表指令 :

MOVC A, @A+PC

MOVC A, @A+DPTR

Page 59: 第 4 章 汇编语言程序设计

第 4 章 单片机汇编语言程序设计

例 13 一个十六进制数存放在内部 RAM 的 HEX 单元的低 4 位中 , 将其转换成 ASCII 码并送回 HEX 单元。

Page 60: 第 4 章 汇编语言程序设计

第 4 章 单片机汇编语言程序设计

ORG 1000H HEXASC: MOV A, HEX ANL A, # 0FH ADD A, # 3; 修改指针 MOVC A, @A+PC MOV HEX, A RET

十六进制 0~ 9 的 ASCII 码为 30H~ 39H, A~ F 的ASCII 码为 41H~ 46H, ASCII 码表格的首地址为 ASCTAB 。编程如下 :

ASCTAB: DB 30H, 31H, 32H, 33H, 34H

DB 35H, 36H, 37H, 38H, 39H

DB 41H, 42H, 43H, 44H, 45H

DB 46H

在这个程序中 , 查表指令 MOVC A, @A+PC 到表格首地址有两条指令 , 占用 3 个字节地址空间 , 故修改指针应加 3 。

Page 61: 第 4 章 汇编语言程序设计

第 4 章 单片机汇编语言程序设计

例 14 设有一个巡回检测报警装置 , 需对 96 路输入进

行控制 , 每路有一个额定的最大值 , 是双字节数。当检测量

大于该路对应的最大值时 , 就越限报警。假设 R2 为保存检

测路数的寄存器 ,查找最大额定值,将其对应的最大额定值

存放于 31H 和 32H 单元中。 的程序如下 :

FMAX: MOV A, R2

ADD A, R2 ; 表中一个额定值为 2 个字节

MOV 31H, A

MOV DPTR, # TAB ; 表首址

Page 62: 第 4 章 汇编语言程序设计

第 4 章 单片机汇编语言程序设计

MOVC A, @A+DPTR; 查表读取第一个字节

XCH A, 31H ; 第一个字节内容存入 31H

INC DPTR

MOVC A, @A+DPTR; 查表读取第二个字节

MOV 32H, A ; 第二字节的内容存入 32H

TAB: DW 1230H, 1450H, ...

DW 2230H, 2440H, ...

DW 3120H, 3300H, ...

Page 63: 第 4 章 汇编语言程序设计

第 4 章 单片机汇编语言程序设计 4.2.7 数制转换

例 15 将一个字节二进制数转换成 3 位非压缩型 BCD

码。

设一个字节二进制数在内部 RAM 40H 单元 , 转换结果放入内部 RAM 50H, 51H, 52H 单元中(高位在前) , 程序如下 :

HEXBCD: MOV A, 40H

MOV B, # 100

DIV AB

MOV 50H, A

MOV A, # 10

XCH A, B

DIV AB

MOV 51H, A

MOV 52H, B

RET

Page 64: 第 4 章 汇编语言程序设计

第 4 章 单片机汇编语言程序设计

4.2.8 运算程序

一、 加、 减法程序

例 16 将 40H 开始存放的 10 个字节的数与 50H 开始存

放的 10 个字节的数相减(假设被减数大于减数)。

设被减数指针为 R0, 减数指针为 R1, 差数放回被减数单

元 , R5 存放字节个数 , 则程序如下 :

Page 65: 第 4 章 汇编语言程序设计

第 4 章 单片机汇编语言程序设计

SUB: MOV R0, # 40H

MOV R1, # 50H

MOV R5, # 10

CLR C

SUB1: MOV A, @R0

SUBB A, @R1

MOV @R0, A

INC R0

INC R1

DJNZ R5, SUB1

RET

Page 66: 第 4 章 汇编语言程序设计

第 4 章 单片机汇编语言程序设计 二、 乘法运算程序

在计算机中 , 常将乘法采用移位和加法来实现。

例 19 将( R2R3 )和( R6R7 )中双字节无符号数相乘 , 结果存入 R4R5R6R7 。

此乘法可以采用部分积右移的方法来实现 , 其程序框图如图 4.6 所示 , 程序如下 :

NMUL: MOV R4, # 0 ; 初始化

MOV R5, # 0

CLR C

MOV R0, # 16

Page 67: 第 4 章 汇编语言程序设计

第 4 章 单片机汇编语言程序设计 NMUL1: MOV A, R4 ; CyR4R5R6R7右移一位

RRC A

MOV R4, A

MOV A, R5

RRC A

MOV R5, A

MOV A, R6

RRC A

MOV R6, A

MOV A, R7

RRC

MOV R7, A

JNC NMUL2; C 为移出乘数的最低位

MOV A, R5 ; ( R4R5 ) + ( R6F7)→ ( R4R5 )

Page 68: 第 4 章 汇编语言程序设计

第 4 章 单片机汇编语言程序设计

ADD A, R3

MOV R5, A

MOV A, R4

ADDC A, R2

MOV R4, A

NMUL2: DJNZR0, NMUL1; 循环 16 位

MOV A, R4; 最后结果再移一位

RRC A

MOV R4, A

MOV A, R5

RRC A

MOV R5, A

MOV A, R6

Page 69: 第 4 章 汇编语言程序设计

第 4 章 单片机汇编语言程序设计

RRC A

MOV R6, A

MOV A, R7

RRC A

MOV R7, A

RET

Page 70: 第 4 章 汇编语言程序设计

第 4 章 单片机汇编语言程序设计

图4.6 NM

UL

程序框

Page 71: 第 4 章 汇编语言程序设计

第 4 章 单片机汇编语言程序设计

例 20 假定被乘数在( R4R3 )中 , 乘数放在 R2 中 , 乘

积放在 R7R6 和 R5 中。

MCS - 51 中有 8 位数的乘法指令 MUL, 用它来实现多字节

乘法时 , 可表示为

( R4R3 ) × ( R2 ) =[( R4 ) ×28+ ( R3 )] ×

( R2 )

= ( R4 ) × ( R2 ) ×28+ ( R3 ) × ( R2 )

其中( R4 ) × ( R2 )和( R3 ) × ( R2 )都是可直接用

MUL 指令来实现 , 而乘以 28意味着左移 8 位。由此可编写

如下程序 :

Page 72: 第 4 章 汇编语言程序设计

第 4 章 单片机汇编语言程序设计 NMUL1: MOV A, R2

MOV B, R3

MUL AB ; ( R3 ) × ( R2 )

MOV R5, A ; 积的低位送 R5

MOV R6, B ; 积的高位送 R6

MOV A, R2

MOV B, R4

MUL AB ; ( R4 ) × ( R2 )

ADD A, R6 ; ( R3 ) × ( R2 )的高位加 (R4)×(R2) 的低位

MOV A, B

ADDC A, # 00H ; ( R4 ) × ( R2 )的高位加 Cy

MOV R7, A ; 结果送 R7

RET

Page 73: 第 4 章 汇编语言程序设计

第 4 章 单片机汇编语言程序设计

三、 除法运算程序

除法是乘法的逆运算 , 用移位、 相减的方法来完成。 首先比较被除数的高位字与除数 , 如被除数高位大于除数 , 则商为 1, 并从被除数中减去除数 , 形成一个部分余数 ; 否则商位为 0, 不执行减法。 然后把新的部分余数左移一位 , 并与除数再次进行比较。循环此步骤 , 直到被除数的所有位都处理完为止 , 一般商的字长为 n, 则需循环 n次。 一般计算机中 ,

被除数均为双倍位 , 即如果除数和商为双字节 , 则被除数为四字节。如果在除法中发生商大于规定字节 , 称为溢出。 在进行除法前 , 应该检查是否会产生溢出。一般可在进行除法前 , 先比较被除数的高位与除数 , 如被除数高位大于除数 ,

则溢出 , 置溢出标志 , 不执行除法。

Page 74: 第 4 章 汇编语言程序设计

第 4 章 单片机汇编语言程序设计

图 4.7 除法程序的流程

Page 75: 第 4 章 汇编语言程序设计

第 4 章 单片机汇编语言程序设计

例 21 将( R4R5R6R7 )除以( R2R3 ) , 商放在( R6

R7 )中 , 余数放在( R4R5 )中。

NDIV: MOV A, R5 ; 判商是否产生溢出

CLR C

SUBB A, R3

MOV A, R4

SUBB A, R2

JNC NDIV1 ; 溢出 , 转溢出处理

MOV B, # 16; 无溢出 , 执行除法

Page 76: 第 4 章 汇编语言程序设计

第 4 章 单片机汇编语言程序设计

NDIV2: CLR C ; 被除数左移一位 , 低位送 0

MOV A, R7

RLC A

MOV R7, A

MOV A, R6

RLC A

MOV R6, A

MOV A, R5

RLC A

MOV R5, A

XCH A, R4

RLC A

XCH A, R4

Page 77: 第 4 章 汇编语言程序设计

第 4 章 单片机汇编语言程序设计 MOV F0, C ; 保护移出的最高位

CLR C

SUBB A, R3 ; 部分余数与除数比较

MOV R1, A

MOV A, R4

SUBB A, R2

JB F0, NDIV3; 移出的高位为 1, 肯定够减

JC NDIV4 ; 否则 , (Cy) = 0 才够减

NDIV3: MOV R4, A ; 回送减法结果

MOV A, R1

MOV R5, A

INC R7 ; 商上 1

Page 78: 第 4 章 汇编语言程序设计

第 4 章 单片机汇编语言程序设计

NDIV4: DJNZ B, NDIV2; 循环次数减 1 ,若不为零则循环

CLR F0 ; 正常执行无溢出 F0 = 0

RET

NDIV1: SETB F0 ; 溢出 F0=1

RET