第 4章 汇编语言程序设计
4.1 汇编语言基本概念
4.2 汇编语言程序设计
4.1 汇编语言基本概念
4.1.1 程序设计语言
4.1.2 汇编语言的语句结构
4.1.3 伪指令返回本章首页
4.1.1 程序设计语言按照语言的结构及其功能可以分为三种:
1,机器语言,机器语言是用二进制代码 0和 1表示指令和数据的最原始的程序设计语言 。
2,汇编语言,在汇编语言中,指令用助记符表示,地址,操作数可用标号,符号地址及字符等形式来描述 。
3,高级语言,高级语言是接近于人的自然语言,
面向过程而独立于机器的通用语言 。
返回本节
4.1.2 汇编语言的语句结构
1,汇编语言的指令类型
MCS-51单片机汇编语言,包含两类不同性质的指令 。
( 1) 基本指令:即指令系统中的指令 。 它们都是机器能够执行的指令,每一条指令都有对应的机器码 。
( 2) 伪指令:汇编时用于控制汇编的指令 。 它们都是机器不执行的指令,无机器码 。
下一页
2,汇编语言的语句格式汇编语言源程序是由汇编语句 ( 即指令 ) 组成的 。 汇编语言一般由四部分组成 。
其典型的汇编语句格式如下:
标号,操作码 操作数 ;注释
START,MOV A,30H ; A←
( 30H)
返回本节
4.1.3 伪指令
1,ORG:汇编起始地址用来说明以下程序段在存储器中存放的起始地址 。
例如程序,ORG 1000H
START,MOVA,#20H
MOVB,#30H
┇
2,EQU:赋值给变量标号赋予一个确定的数值 。
下一页
3,DB:定义数据字节把数据以字节数的形式存放在存储器单元中。
4,DW:定义数据字按字的形式把数据存放在存储单元中 。
5,DS:定义存储区从指定的地址单元开始,保留一定数量存储单元。
6,BIT:位定义确定字符名为确定的位地址值。
7,END:汇编结束返回本节
4.2 汇编语言程序设计
4.2.1 汇编语言程序设计步骤
4.2.2 顺序程序
4.2.3 分支程序
4.2.4 循环程序
4.2.5 子程序
4.2.6 位操作程序返回本章首页
4.2.1 汇编语言程序设计步骤
1,分析问题
2,确定算法
3,设计程序流程图
4,分配内存单元
5,编写汇编语言源程序
6,调试程序返回本节
4.2.2 顺序程序顺序程序是一种最简单,最基本的程序。
特点:程序按编写的顺序依次往下执行每一条指令,直到最后一条。
【 例 4.1】 将 30H单元内的两位 BCD码拆开并转换成 ASCII码,存入 RAM两个单元中。程序流程 如图 4.1所示 。 参考程序 如下:
ORG 0100H
MOV A,30H ;取值
ANL A,#0FH ;取低 4位下一页
ADD A,#30H ;转换成 ASCII码
MOV32H,A ;保存结果
MOVA,30H ;取值
SWAP A ;高 4位与低 4位互换
ANL A,#0FH ;取低 4位 ( 原来的高 4位 )
ADD A,#30H ;转换成 ASCII码
MOV 31H,A ;保存结果
SJMP $
END
下一页结束取数据低 4位转换成 ASCII码存 ASCII码取数据高 4位转换成 ASCII码存 ASCII码开始图4.1
拆字程序流程图返回
【 例 4.2】 设 X,Y两个小于 10的整数分别存于片内 30H,31H单元,试求两数的平方和并将结果存于 32H单元 。
解:两数均小于 10,故两数的平方和小于 100,
可利用乘法指令求平方 。 程序流程 如图 4-2所示 。 参考程序 如下:
ORG 0100H
MOV A,30H ;取 30H单元数据
MOV B,A ;将 X送入 B寄存器下一页
MUL AB ;求 X2,结果在累加器中
MOV R1,A ;将结果暂存于 R1寄存器中
MOV A,31H ;取 31H单元数据
MOV B,A ;将 Y送入 B寄存器
MUL AB ;求 Y2,结果在累加器中
ADD A,R1 ;求 X2+ Y2
MOV 32H,A ;保存数据
SJMP $ ;暂停
END
返回本节结束取数据 X
求 X2
暂存 X2
取数据 Y
求 Y2
求 X2+Y2
开始保存平方和图4-
2
例4.2
程序流程图返回
4.2.3 分支程序
1,分支程序的基本形式分支程序有三种基本形式,如图 4-3所示 。
分支程序的设计要点如下:
( 1)先建立可供条件转移指令测试的条件。
( 2)选用合适的条件转移指令。
( 3)在转移的目的地址处设定标号。
下一页条件满足?
A
Y
N
( a)
条件满足?
A B
N
Y
( b)
( c)
A0 A1 An
K=0 K=1 … K=n
K=?
……
图 4-3 分支程序结构流程图返回
2,双向分支程序设计举例
【 例 4.3】 设 X存在 30H单元中,根据下式
X+2 X>0
Y = 100 X=0
∣ X∣ X<0
求出 Y值,将 Y值存入 31H单元 。
解:根据数据的符号位判别该数的正负,若最高位为 0,
再判别该数是否为 0。 程序流程 如图 4-4所示 。
参考程序 如下:
ORG 0100H
下一页
MOV A,30H ;取数
JB ACC.7,NEG;负数,转 NEG
JZ ZER0 ;为零,转 ZER0
ADD A,#02H ;为正数,求 X+2
AJMP SAVE ;转到 SAVE,保存数据
ZER0,MOV A,# 64H ;数据为零,Y=100
AJMP SAVE ;转到 SAVE,保存数据
NEG,DEC A ;
CPL A ;求 ∣ X∣
SAVE,MOV 31H,A ;保存数据
SJMP $ ;暂停下一页
A为负数?
取数,A← ( 30H)
开始结束
A=0?Y
N
N A← |X|A←64H
A← X+2
存数,( 31H) ← A( 30H)
图4-
4
例4.3
程序流程图返回
3,多向分支程序设计举例
【 例 4.4】 根据 R0的值转向 7个分支程序 。
R0<10,转向 SUB0;
R0<20,转向 SUB1;
R0<60,转向 SUB5;
R0>=60,转向 SUB6;
解:利用 JMP @A+DPTR 指令直接给 PC赋值,
使程序实现转移 。 程序流程 如图 4-5所示 。
下一页参考程序如下:
ORG 0100H
MOV DPTR,#TAB;转移指令表首地址
MOV A,R0 ;取数
CLR C
RLC A ; A← 2*A
JMP @A+DPTR; PC ← A+DPTR
TAB,AJMP SUB0 ;转移指令表
AJMP SUB1 AJMP SUB2
AJMP SUB5 AJMP SUB6
返回本节
K=?
转 SUB0 转 SUB1 转 SUB6
K=0 K=1 …… K=6
开始图 4-5 多向分支程序流程图返回
4.2.4 循环程序
1,循环程序的结构 ( 如图 4-6所示 )
☆ 循环程序一般包括如下四个部分:
( 1) 初始化 ( 2) 循环体
( 3) 循环控制 ( 4) 结束
☆ 循环程序按结构形式,有单重循环与多重循环 。
☆ 在多重循环中,只允许外重循环嵌套内重循环 。
☆ 不允许循环相互交叉,也不允许从循环程序的外部跳入循环程序的内部 ( 如图 4-7所示 ) 。
下一页
( a) 循环结构 1 ( b) 循环结构 2
循环结束?
循环体
Y
N
初始化修改循环参数结束部分开始结束循环结束?
循环体
Y
初始化修改循环参数结束部分开始
N
结束图 4-6 循环结构程序流程图返回外循环中循环内循环外循环内循环外循环内循环内循环
( a)嵌套正确 ( b)嵌套正确 ( c)交叉不正确图 4-7 多重循环示意图返回
2,循环程序设计举例
【 例 4.5】 有一数据块从片内 RAM的 30H单元开始存入,
设数据块长度为 10个单元 。 根据下式:
X+2 X>0
Y= 100 X=0
∣ X∣ X<0
求出 Y值,并将 Y值放回原处 。
解:设置一个计数器控制循环次数,每处理完一个数据,
计数器减 1。 程序流程 如图 4-8所示 。
下一页参考源程序如下:
ORG 0100H
MOV R0,#10
MOV R1,#30H
START,MOV A,@R1 ;取数
JB ACC.7,NEG ;若为负数,转 NEG
JZ ZER0 ;若为零,转 ZER0
ADD A,#02H ;若为正数,求 X+2
AJMP SAVE ;转到 SAVE,保存数据
ZER0,MOV A,# 64H ;数据为零,Y=100
下一页
AJMP SAVE ;转到 SAVE,保存数据
NEG,DEC A
CPL A ;求 ∣ X∣
SAVE,MOV @R1,A ;保存数据
INC R1 ;地址指针指向下一个地址
DJNZ R0,START ;数据未处理完,继续处理
SJMP $ ;暂停返回本节
A=0?Y
Y
N
N
Y
N
A为负数?
取数,A← (( R1))
开始结束
A← ∣ X∣A←64H
A←X+2
存数,(( R1)) ← A( 30H)
设置地址指针 R1、计数器 R0初值
R1←R1+1 ; R0←R0 -1
R0=0?
图4-
8
例4.5
的程序流程图返回
4.2.5 子程序
1,子程序概念所谓调用子程序,暂时中断主程序的执行,
而转到子程序的入口地址去执行子程序。 如图
4-10所示 。调用子程序应注意:
( 1) 子程序占用的存储单元和寄存器 。
( 2) 参数的传递 。
( 3) 子程序经过调用后得到的数据来完成程序之间的参数传递 。
( 4) 嵌套调用与递归调用 。 如图 4-11所示 。
下一页
RET
LCALL SUB
图 4-10 子程序的调用与返回返回
LCALL A
RETRET
LCALL B
图 4-11 子程序的嵌套调用与返回返回
2,子程序设计举例
【 例 4.8】 将 4.4节中的例 4.5改为子程序结构 。
解:数据块中的十个数都需要进行符号判断并作相应处理,可把一部分工作交给子程序完成,主程序只负责读取数据,调用判断处理子程序,保存数据,循环控制工作 。 源程序如下:
ORG 0100H
MOV R0,#10
MOV R1,#30H
下一页
START,MOV A,@R1 ;取数
ACALL DISPOSE ;调用判断,处理子程序
SAVE,MOV @R1,A ;保存数据
INC R1 ;修改地址指针,指向下一个地址
DJNZ R0,START ;数据未处理完,继续处理
SJMP $ ;暂停
ORG 0200H
DISPOSE,JB ACC.7,NEG ;若为负数,转 NEG
下一页
JZ ZER0 ;若为零,转 ZER0
ADD A,#02H ;若为正数,求 X+2
AJMP BACK ;转到 SAVE,保存数据
ZER0,MOV A,#64H ;数据为零,Y=100
AJMP BACK ;转到 SAVE,保存数据
NEG,DEC A
CPL A ;求 ∣ X∣
BACK,RET
返回本节
4.2.6 位操作程序
【 例 4.9】 编写一程序,实现 图 4-12中的逻辑运算电路 。 其中 P3.1,P1.1,P1.0分别是单片机端口线上的信息,RS0,RS1是 PSW寄存器中的两个标志位,30H,31H是两个位地址,运算结果由 P1.0输出 。
程序如下:
ORG 0000H
MOV C,P3.1
下一页
ANL C,P1.1
CPL C
MOV 20H,C ;暂存数据
MOV C,30H
ORL C,/31H
ANL C,RS1
ANL C,20H
ANL C,RS0
MOV P1.0,C ;输出结果
SJMP $
返回本节
P3.1
P1.1
30H
31H
RS1
RS0
&
≥ 1 &
& P
1.0
图 4-12 硬件逻辑硬件电路图返回
4.1 汇编语言基本概念
4.2 汇编语言程序设计
4.1 汇编语言基本概念
4.1.1 程序设计语言
4.1.2 汇编语言的语句结构
4.1.3 伪指令返回本章首页
4.1.1 程序设计语言按照语言的结构及其功能可以分为三种:
1,机器语言,机器语言是用二进制代码 0和 1表示指令和数据的最原始的程序设计语言 。
2,汇编语言,在汇编语言中,指令用助记符表示,地址,操作数可用标号,符号地址及字符等形式来描述 。
3,高级语言,高级语言是接近于人的自然语言,
面向过程而独立于机器的通用语言 。
返回本节
4.1.2 汇编语言的语句结构
1,汇编语言的指令类型
MCS-51单片机汇编语言,包含两类不同性质的指令 。
( 1) 基本指令:即指令系统中的指令 。 它们都是机器能够执行的指令,每一条指令都有对应的机器码 。
( 2) 伪指令:汇编时用于控制汇编的指令 。 它们都是机器不执行的指令,无机器码 。
下一页
2,汇编语言的语句格式汇编语言源程序是由汇编语句 ( 即指令 ) 组成的 。 汇编语言一般由四部分组成 。
其典型的汇编语句格式如下:
标号,操作码 操作数 ;注释
START,MOV A,30H ; A←
( 30H)
返回本节
4.1.3 伪指令
1,ORG:汇编起始地址用来说明以下程序段在存储器中存放的起始地址 。
例如程序,ORG 1000H
START,MOVA,#20H
MOVB,#30H
┇
2,EQU:赋值给变量标号赋予一个确定的数值 。
下一页
3,DB:定义数据字节把数据以字节数的形式存放在存储器单元中。
4,DW:定义数据字按字的形式把数据存放在存储单元中 。
5,DS:定义存储区从指定的地址单元开始,保留一定数量存储单元。
6,BIT:位定义确定字符名为确定的位地址值。
7,END:汇编结束返回本节
4.2 汇编语言程序设计
4.2.1 汇编语言程序设计步骤
4.2.2 顺序程序
4.2.3 分支程序
4.2.4 循环程序
4.2.5 子程序
4.2.6 位操作程序返回本章首页
4.2.1 汇编语言程序设计步骤
1,分析问题
2,确定算法
3,设计程序流程图
4,分配内存单元
5,编写汇编语言源程序
6,调试程序返回本节
4.2.2 顺序程序顺序程序是一种最简单,最基本的程序。
特点:程序按编写的顺序依次往下执行每一条指令,直到最后一条。
【 例 4.1】 将 30H单元内的两位 BCD码拆开并转换成 ASCII码,存入 RAM两个单元中。程序流程 如图 4.1所示 。 参考程序 如下:
ORG 0100H
MOV A,30H ;取值
ANL A,#0FH ;取低 4位下一页
ADD A,#30H ;转换成 ASCII码
MOV32H,A ;保存结果
MOVA,30H ;取值
SWAP A ;高 4位与低 4位互换
ANL A,#0FH ;取低 4位 ( 原来的高 4位 )
ADD A,#30H ;转换成 ASCII码
MOV 31H,A ;保存结果
SJMP $
END
下一页结束取数据低 4位转换成 ASCII码存 ASCII码取数据高 4位转换成 ASCII码存 ASCII码开始图4.1
拆字程序流程图返回
【 例 4.2】 设 X,Y两个小于 10的整数分别存于片内 30H,31H单元,试求两数的平方和并将结果存于 32H单元 。
解:两数均小于 10,故两数的平方和小于 100,
可利用乘法指令求平方 。 程序流程 如图 4-2所示 。 参考程序 如下:
ORG 0100H
MOV A,30H ;取 30H单元数据
MOV B,A ;将 X送入 B寄存器下一页
MUL AB ;求 X2,结果在累加器中
MOV R1,A ;将结果暂存于 R1寄存器中
MOV A,31H ;取 31H单元数据
MOV B,A ;将 Y送入 B寄存器
MUL AB ;求 Y2,结果在累加器中
ADD A,R1 ;求 X2+ Y2
MOV 32H,A ;保存数据
SJMP $ ;暂停
END
返回本节结束取数据 X
求 X2
暂存 X2
取数据 Y
求 Y2
求 X2+Y2
开始保存平方和图4-
2
例4.2
程序流程图返回
4.2.3 分支程序
1,分支程序的基本形式分支程序有三种基本形式,如图 4-3所示 。
分支程序的设计要点如下:
( 1)先建立可供条件转移指令测试的条件。
( 2)选用合适的条件转移指令。
( 3)在转移的目的地址处设定标号。
下一页条件满足?
A
Y
N
( a)
条件满足?
A B
N
Y
( b)
( c)
A0 A1 An
K=0 K=1 … K=n
K=?
……
图 4-3 分支程序结构流程图返回
2,双向分支程序设计举例
【 例 4.3】 设 X存在 30H单元中,根据下式
X+2 X>0
Y = 100 X=0
∣ X∣ X<0
求出 Y值,将 Y值存入 31H单元 。
解:根据数据的符号位判别该数的正负,若最高位为 0,
再判别该数是否为 0。 程序流程 如图 4-4所示 。
参考程序 如下:
ORG 0100H
下一页
MOV A,30H ;取数
JB ACC.7,NEG;负数,转 NEG
JZ ZER0 ;为零,转 ZER0
ADD A,#02H ;为正数,求 X+2
AJMP SAVE ;转到 SAVE,保存数据
ZER0,MOV A,# 64H ;数据为零,Y=100
AJMP SAVE ;转到 SAVE,保存数据
NEG,DEC A ;
CPL A ;求 ∣ X∣
SAVE,MOV 31H,A ;保存数据
SJMP $ ;暂停下一页
A为负数?
取数,A← ( 30H)
开始结束
A=0?Y
N
N A← |X|A←64H
A← X+2
存数,( 31H) ← A( 30H)
图4-
4
例4.3
程序流程图返回
3,多向分支程序设计举例
【 例 4.4】 根据 R0的值转向 7个分支程序 。
R0<10,转向 SUB0;
R0<20,转向 SUB1;
R0<60,转向 SUB5;
R0>=60,转向 SUB6;
解:利用 JMP @A+DPTR 指令直接给 PC赋值,
使程序实现转移 。 程序流程 如图 4-5所示 。
下一页参考程序如下:
ORG 0100H
MOV DPTR,#TAB;转移指令表首地址
MOV A,R0 ;取数
CLR C
RLC A ; A← 2*A
JMP @A+DPTR; PC ← A+DPTR
TAB,AJMP SUB0 ;转移指令表
AJMP SUB1 AJMP SUB2
AJMP SUB5 AJMP SUB6
返回本节
K=?
转 SUB0 转 SUB1 转 SUB6
K=0 K=1 …… K=6
开始图 4-5 多向分支程序流程图返回
4.2.4 循环程序
1,循环程序的结构 ( 如图 4-6所示 )
☆ 循环程序一般包括如下四个部分:
( 1) 初始化 ( 2) 循环体
( 3) 循环控制 ( 4) 结束
☆ 循环程序按结构形式,有单重循环与多重循环 。
☆ 在多重循环中,只允许外重循环嵌套内重循环 。
☆ 不允许循环相互交叉,也不允许从循环程序的外部跳入循环程序的内部 ( 如图 4-7所示 ) 。
下一页
( a) 循环结构 1 ( b) 循环结构 2
循环结束?
循环体
Y
N
初始化修改循环参数结束部分开始结束循环结束?
循环体
Y
初始化修改循环参数结束部分开始
N
结束图 4-6 循环结构程序流程图返回外循环中循环内循环外循环内循环外循环内循环内循环
( a)嵌套正确 ( b)嵌套正确 ( c)交叉不正确图 4-7 多重循环示意图返回
2,循环程序设计举例
【 例 4.5】 有一数据块从片内 RAM的 30H单元开始存入,
设数据块长度为 10个单元 。 根据下式:
X+2 X>0
Y= 100 X=0
∣ X∣ X<0
求出 Y值,并将 Y值放回原处 。
解:设置一个计数器控制循环次数,每处理完一个数据,
计数器减 1。 程序流程 如图 4-8所示 。
下一页参考源程序如下:
ORG 0100H
MOV R0,#10
MOV R1,#30H
START,MOV A,@R1 ;取数
JB ACC.7,NEG ;若为负数,转 NEG
JZ ZER0 ;若为零,转 ZER0
ADD A,#02H ;若为正数,求 X+2
AJMP SAVE ;转到 SAVE,保存数据
ZER0,MOV A,# 64H ;数据为零,Y=100
下一页
AJMP SAVE ;转到 SAVE,保存数据
NEG,DEC A
CPL A ;求 ∣ X∣
SAVE,MOV @R1,A ;保存数据
INC R1 ;地址指针指向下一个地址
DJNZ R0,START ;数据未处理完,继续处理
SJMP $ ;暂停返回本节
A=0?Y
Y
N
N
Y
N
A为负数?
取数,A← (( R1))
开始结束
A← ∣ X∣A←64H
A←X+2
存数,(( R1)) ← A( 30H)
设置地址指针 R1、计数器 R0初值
R1←R1+1 ; R0←R0 -1
R0=0?
图4-
8
例4.5
的程序流程图返回
4.2.5 子程序
1,子程序概念所谓调用子程序,暂时中断主程序的执行,
而转到子程序的入口地址去执行子程序。 如图
4-10所示 。调用子程序应注意:
( 1) 子程序占用的存储单元和寄存器 。
( 2) 参数的传递 。
( 3) 子程序经过调用后得到的数据来完成程序之间的参数传递 。
( 4) 嵌套调用与递归调用 。 如图 4-11所示 。
下一页
RET
LCALL SUB
图 4-10 子程序的调用与返回返回
LCALL A
RETRET
LCALL B
图 4-11 子程序的嵌套调用与返回返回
2,子程序设计举例
【 例 4.8】 将 4.4节中的例 4.5改为子程序结构 。
解:数据块中的十个数都需要进行符号判断并作相应处理,可把一部分工作交给子程序完成,主程序只负责读取数据,调用判断处理子程序,保存数据,循环控制工作 。 源程序如下:
ORG 0100H
MOV R0,#10
MOV R1,#30H
下一页
START,MOV A,@R1 ;取数
ACALL DISPOSE ;调用判断,处理子程序
SAVE,MOV @R1,A ;保存数据
INC R1 ;修改地址指针,指向下一个地址
DJNZ R0,START ;数据未处理完,继续处理
SJMP $ ;暂停
ORG 0200H
DISPOSE,JB ACC.7,NEG ;若为负数,转 NEG
下一页
JZ ZER0 ;若为零,转 ZER0
ADD A,#02H ;若为正数,求 X+2
AJMP BACK ;转到 SAVE,保存数据
ZER0,MOV A,#64H ;数据为零,Y=100
AJMP BACK ;转到 SAVE,保存数据
NEG,DEC A
CPL A ;求 ∣ X∣
BACK,RET
返回本节
4.2.6 位操作程序
【 例 4.9】 编写一程序,实现 图 4-12中的逻辑运算电路 。 其中 P3.1,P1.1,P1.0分别是单片机端口线上的信息,RS0,RS1是 PSW寄存器中的两个标志位,30H,31H是两个位地址,运算结果由 P1.0输出 。
程序如下:
ORG 0000H
MOV C,P3.1
下一页
ANL C,P1.1
CPL C
MOV 20H,C ;暂存数据
MOV C,30H
ORL C,/31H
ANL C,RS1
ANL C,20H
ANL C,RS0
MOV P1.0,C ;输出结果
SJMP $
返回本节
P3.1
P1.1
30H
31H
RS1
RS0
&
≥ 1 &
& P
1.0
图 4-12 硬件逻辑硬件电路图返回