第 4章 汇编语言程序设计
4.1 汇编语言基本概念
4.2 汇编语言程序设计
4.1 汇编语言基本概念
按照语言的结构及其功能可以分为三种:
1,机器语言:机器语言是用二进制代码 0和 1表
示指令和数据的最原始的程序设计语言 。
2,汇编语言:在汇编语言中, 指令用助记符表
示, 地址, 操作数可用标号, 符号地址及字
符等形式来描述 。
3,高级语言:高级语言是接近于人的自然语言,
面向过程而独立于机器的通用语言 。
汇编语言的语句结构
1,汇编语言的指令类型
MCS-51单片机汇编语言, 包含两类不同性质的
指令 。
( 1) 基本指令:即指令系统中的指令 。 它们
都是机器能够执行的指令, 每一条指令都有对
应的机器码 。
( 2) 伪指令:汇编时用于控制汇编的指令 。
它们都是机器不执行的指令, 无机器码 。
2,汇编语言的语句格式
汇编语言源程序是由汇编语句 ( 即指令 ) 组
成的 。 汇编语言一般由四部分组成 。
其典型的汇编语句格式如下:
[标号,]操作码 [目的操作数 ][,源操作数 ][;注释 ]
START,MOV A,30H ; A← ( 30H)
( 1) 标号
位于语句的开始, 代表该语句的地址;由 1~ 8个字母和
数字组成, 必须以字母打头, 以冒号结束, 不能使用指
令助记符, 伪指令或寄存器名 。
( 2) 操作码
即指令的助记符, 表示具体执行的操作, 不可省略 。
( 3) 操作数
操作数与操作码之间用空格分开 。 源操作数与目的操作
数之间用逗号分开, 必须满足寻址方式的规定 。
( 4) 注释
对程序的必要说明, 注释与操作数之间用分号隔开 。
√ 指令中以 A— F 开头的十六进制数前必须添一个, 0”。
√ 二进制数必须带后缀, B”或, b”;十六进制数必须带
后缀, H”或, h”;十进制数的后缀是, D”或, d”或 无 。
√ BCD码:用二进制数表达的十进制数。
( 0~ 9表示为,0000~ 1001B 后缀,B/b,H/h)
伪指令
汇编程序,汇编语言编写的程序借助 编译工具 编译
成为目标代码,计算机才能识别。这个编译工具称
为汇编程序。
?指令,告诉计算机 如何操作以及做何种操作 。
?伪指令:告诉汇编程序在翻译应用程序时 有何具
体约定 。伪指令不进行具体的操作,那是真指令的
事。
比如:从何处开始,何处结束,某些编程者自己规
定的表述代表什么意思 ……
汇编程序的常用伪指令
伪指令 DB,DW都只对程序存储器起作用,它们不能对数据
存储器初始化。可用 DB,DW在程序存储器定义数据表格,
DW还能定义一个地址表。
字符名称
4.2 汇编语言程序设计
4.2.1 汇编语言程序设计步骤
4.2.2 顺序程序
4.2.3 分支程序
4.2.4 循环程序
4.2.5 子程序
4.2.1 汇编语方程序设计步骤
1,分析问题
2,确定算法
3,设计程序流程图
4,分配内存单元
5,编写汇编语言源程序
6,调试程序
4.2.2 顺序程序
顺序程序是一种最简
单,最基本的程序。
特点:程序按编写的
顺序依次往下执行每
一条指令,直到最后
一条。
【 例 】 将 30H单元内的
两位 BCD码拆开并转换成
ASCII码,存入 RAM两个
单元中。程序流程如图
所示。参考程序如下,结束
取数据低 4位
转换成 ASCII码
存 ASCII码
取数据高 4位
转换成 ASCII码
存 ASCII码
开始
ORG 2000H
MOV A,30H ;取值
ANL A,#0FH ;取低 4位
ADD A,#30H ;转换成 ASCII码
MOV 32H,A ;保存结果
MOV A,30H ;取值
SWAP A ;高 4位与低 4位互换
ANL A,#0FH ;取低 4位 ( 原来的高 4位 )
ADD A,#30H ;转换成 ASCII码
MOV 31H,A ;保存结果
SJMP $
END
【 例 】 设 X,Y两个
小于 10的整数分别存
于片内 30H,31H单元,
试求两数的平方和并
将结果存于 32H单元。
? 解:两数均小于 10,
故两数的平方和小于
100,可利用乘法指
令求平方。程序流程
如图所示。参考程序
如下,结束
取数据 X
求 X2
暂存 X2
取数据 Y
求 Y2
求 X2+Y2
开始
保存平方和
ORG 2000H
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
4.2.3 分支程序
1,分支程序的基本形式
分支程序有三种基本形式,如图所示。
分支程序的设计要点如下:
( 1)先建立可供条件转移指令测试的条件。
( 2)选用合适的条件转移指令。
( 3)在转移的目的地址处设定标号。
条件满足?
A
Y
N
( a)
条件满足?
A B
N
Y
( b)
( c)
A0 A1 An
K=0 K=1 … K=n
K=?
……
分支程序结构流程图
2,双向分支程序设计举例
【 例 】 设 X存在 30H单元中, 根据下式
X+2 X>0
Y = 100 X=0 求出 Y值, 将 Y值存入 31H单元 。
∣ X∣ X<0
解:根据数据的符号位判别该数的正负, 若最高位
为 0,再判别该数是否为 0。 程序流程如图所示 。
A为负数?
取数,A← ( 30H)
开始
结束
A=0?Y
N
N A←|X|A←64H
A←X+2
存数,( 31H) ← A( 30H)
参考程序如下:
ORG 1000H
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 $ ;暂停
END
3,多向分支程序设计举例
【 例 】 根据 R0的值转向 7个分支程序 。
R0<10,转向 SUB0;
R0<20,转向 SUB1;
R0<60,转向 SUB5;
R0<70,转向 SUB6;
解:利用 JMP @A+DPTR 指令直接给 PC赋值,
使程序实现转移 。 程序流程如图所示 。
?
K=?
转 SUB0 转 SUB1 转 SUB6
K=0 K=1 …… K=6
开始
多向分支程序流程图
参考程序,ORG 2000H
MOV DPTR,#TAB ;转移指令表首地址
MOV A,R0 ;取数
MOV B,#10
DIV AB ; A/10,商在 A中
CLR C
RLC A ; A← 2A,A中的值为偏移量,
AJMP指令占 2个字节
JMP @A+DPTR ; PC ← A+DPTR
TAB:AJMP SUB0 ;转移指令表
AJMP SUB1
AJMP SUB2
…
AJMP SUB6
4.2.4 循环程序
1,循环程序的结构 ( 如图 4-6所示 )
循环程序一般包括如下四个部分:
( 1) 初始化 ( 2) 循环体
( 3) 循环控制 ( 4) 结束
☆ 循环程序按结构形式, 有单重循环与多重循环 。
☆ 在多重循环中, 只允许外重循环嵌套内重循环 。
☆ 不允许循环相互交叉, 也不允许从循环程序的
外部跳入循环程序的内部 ( 如图 4-7所示 ) 。
( a) 当型循环结构 ( b) 直到型循环结构
循环结束?
循环体
Y
N
初始化
修改循环参数
结束部分
开始
结束
循环结束?
循环体
Y
初始化
修改循环参数
结束部分
开始
N
结束
图 4-6 循环结构程序流程图
外循环
中循环
内循环
外循环
内循环
外循环
内循环
内循环
( a)嵌套正确 ( b)嵌套正确 ( c)交叉不正确
图 4-7 多重循环示意图
2,循环程序设计举例
【 例 】 有一数据块从片内 RAM的 30H单元开始存入,
设数据块长度为 10个单元 。 根据下式:
X+2 X>0
Y= 100 X=0 求出 Y值, 并将 Y值放回原处 。
∣ X∣ X<0
解:设置一个计数器控制循环次数, 每处理完一
个数据, 计数器减 1。 程序流程如图所示 。
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?
参考程序:
ORG 2000H
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 $ ;暂停
4.2.5 子程序
1,子程序概念
所谓调用子程序, 暂时中断主程序的执行, 而转
到子程序的入口地址去执行子程序 。 如图所示 。
RET
LCALL SUB
子程序的调用与返回
调用子程序应注意:
( 1)子程序占用的存储单元和寄存器。
( 2)参数的传递。
( 3)子程序经过调用后得到的数据来完成程序
之间的参数传递。
( 4)嵌套调用与递归调用。如图所示。
LCALL A
RETRET
LCALL B
子程序的嵌套调用与返回
2,子程序设计举例
【 例 】 有一数据块从片内 RAM的 30H单元开始存入,
设数据块长度为 10个单元 。 根据下式:
X+2 X>0
Y= 100 X=0 求出 Y值, 并将 Y值放回原处 。
∣ X∣ X<0
解:数据块中的十个数都需要进行符号判断并作相应
处理, 可把一部分工作交给子程序完成, 主程序只负
责读取数据, 调用判断处理子程序, 保存数据, 循环
控制工作 。 源程序如下:
ORG 0000H
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.1 汇编语言基本概念
4.2 汇编语言程序设计
4.1 汇编语言基本概念
按照语言的结构及其功能可以分为三种:
1,机器语言:机器语言是用二进制代码 0和 1表
示指令和数据的最原始的程序设计语言 。
2,汇编语言:在汇编语言中, 指令用助记符表
示, 地址, 操作数可用标号, 符号地址及字
符等形式来描述 。
3,高级语言:高级语言是接近于人的自然语言,
面向过程而独立于机器的通用语言 。
汇编语言的语句结构
1,汇编语言的指令类型
MCS-51单片机汇编语言, 包含两类不同性质的
指令 。
( 1) 基本指令:即指令系统中的指令 。 它们
都是机器能够执行的指令, 每一条指令都有对
应的机器码 。
( 2) 伪指令:汇编时用于控制汇编的指令 。
它们都是机器不执行的指令, 无机器码 。
2,汇编语言的语句格式
汇编语言源程序是由汇编语句 ( 即指令 ) 组
成的 。 汇编语言一般由四部分组成 。
其典型的汇编语句格式如下:
[标号,]操作码 [目的操作数 ][,源操作数 ][;注释 ]
START,MOV A,30H ; A← ( 30H)
( 1) 标号
位于语句的开始, 代表该语句的地址;由 1~ 8个字母和
数字组成, 必须以字母打头, 以冒号结束, 不能使用指
令助记符, 伪指令或寄存器名 。
( 2) 操作码
即指令的助记符, 表示具体执行的操作, 不可省略 。
( 3) 操作数
操作数与操作码之间用空格分开 。 源操作数与目的操作
数之间用逗号分开, 必须满足寻址方式的规定 。
( 4) 注释
对程序的必要说明, 注释与操作数之间用分号隔开 。
√ 指令中以 A— F 开头的十六进制数前必须添一个, 0”。
√ 二进制数必须带后缀, B”或, b”;十六进制数必须带
后缀, H”或, h”;十进制数的后缀是, D”或, d”或 无 。
√ BCD码:用二进制数表达的十进制数。
( 0~ 9表示为,0000~ 1001B 后缀,B/b,H/h)
伪指令
汇编程序,汇编语言编写的程序借助 编译工具 编译
成为目标代码,计算机才能识别。这个编译工具称
为汇编程序。
?指令,告诉计算机 如何操作以及做何种操作 。
?伪指令:告诉汇编程序在翻译应用程序时 有何具
体约定 。伪指令不进行具体的操作,那是真指令的
事。
比如:从何处开始,何处结束,某些编程者自己规
定的表述代表什么意思 ……
汇编程序的常用伪指令
伪指令 DB,DW都只对程序存储器起作用,它们不能对数据
存储器初始化。可用 DB,DW在程序存储器定义数据表格,
DW还能定义一个地址表。
字符名称
4.2 汇编语言程序设计
4.2.1 汇编语言程序设计步骤
4.2.2 顺序程序
4.2.3 分支程序
4.2.4 循环程序
4.2.5 子程序
4.2.1 汇编语方程序设计步骤
1,分析问题
2,确定算法
3,设计程序流程图
4,分配内存单元
5,编写汇编语言源程序
6,调试程序
4.2.2 顺序程序
顺序程序是一种最简
单,最基本的程序。
特点:程序按编写的
顺序依次往下执行每
一条指令,直到最后
一条。
【 例 】 将 30H单元内的
两位 BCD码拆开并转换成
ASCII码,存入 RAM两个
单元中。程序流程如图
所示。参考程序如下,结束
取数据低 4位
转换成 ASCII码
存 ASCII码
取数据高 4位
转换成 ASCII码
存 ASCII码
开始
ORG 2000H
MOV A,30H ;取值
ANL A,#0FH ;取低 4位
ADD A,#30H ;转换成 ASCII码
MOV 32H,A ;保存结果
MOV A,30H ;取值
SWAP A ;高 4位与低 4位互换
ANL A,#0FH ;取低 4位 ( 原来的高 4位 )
ADD A,#30H ;转换成 ASCII码
MOV 31H,A ;保存结果
SJMP $
END
【 例 】 设 X,Y两个
小于 10的整数分别存
于片内 30H,31H单元,
试求两数的平方和并
将结果存于 32H单元。
? 解:两数均小于 10,
故两数的平方和小于
100,可利用乘法指
令求平方。程序流程
如图所示。参考程序
如下,结束
取数据 X
求 X2
暂存 X2
取数据 Y
求 Y2
求 X2+Y2
开始
保存平方和
ORG 2000H
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
4.2.3 分支程序
1,分支程序的基本形式
分支程序有三种基本形式,如图所示。
分支程序的设计要点如下:
( 1)先建立可供条件转移指令测试的条件。
( 2)选用合适的条件转移指令。
( 3)在转移的目的地址处设定标号。
条件满足?
A
Y
N
( a)
条件满足?
A B
N
Y
( b)
( c)
A0 A1 An
K=0 K=1 … K=n
K=?
……
分支程序结构流程图
2,双向分支程序设计举例
【 例 】 设 X存在 30H单元中, 根据下式
X+2 X>0
Y = 100 X=0 求出 Y值, 将 Y值存入 31H单元 。
∣ X∣ X<0
解:根据数据的符号位判别该数的正负, 若最高位
为 0,再判别该数是否为 0。 程序流程如图所示 。
A为负数?
取数,A← ( 30H)
开始
结束
A=0?Y
N
N A←|X|A←64H
A←X+2
存数,( 31H) ← A( 30H)
参考程序如下:
ORG 1000H
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 $ ;暂停
END
3,多向分支程序设计举例
【 例 】 根据 R0的值转向 7个分支程序 。
R0<10,转向 SUB0;
R0<20,转向 SUB1;
R0<60,转向 SUB5;
R0<70,转向 SUB6;
解:利用 JMP @A+DPTR 指令直接给 PC赋值,
使程序实现转移 。 程序流程如图所示 。
?
K=?
转 SUB0 转 SUB1 转 SUB6
K=0 K=1 …… K=6
开始
多向分支程序流程图
参考程序,ORG 2000H
MOV DPTR,#TAB ;转移指令表首地址
MOV A,R0 ;取数
MOV B,#10
DIV AB ; A/10,商在 A中
CLR C
RLC A ; A← 2A,A中的值为偏移量,
AJMP指令占 2个字节
JMP @A+DPTR ; PC ← A+DPTR
TAB:AJMP SUB0 ;转移指令表
AJMP SUB1
AJMP SUB2
…
AJMP SUB6
4.2.4 循环程序
1,循环程序的结构 ( 如图 4-6所示 )
循环程序一般包括如下四个部分:
( 1) 初始化 ( 2) 循环体
( 3) 循环控制 ( 4) 结束
☆ 循环程序按结构形式, 有单重循环与多重循环 。
☆ 在多重循环中, 只允许外重循环嵌套内重循环 。
☆ 不允许循环相互交叉, 也不允许从循环程序的
外部跳入循环程序的内部 ( 如图 4-7所示 ) 。
( a) 当型循环结构 ( b) 直到型循环结构
循环结束?
循环体
Y
N
初始化
修改循环参数
结束部分
开始
结束
循环结束?
循环体
Y
初始化
修改循环参数
结束部分
开始
N
结束
图 4-6 循环结构程序流程图
外循环
中循环
内循环
外循环
内循环
外循环
内循环
内循环
( a)嵌套正确 ( b)嵌套正确 ( c)交叉不正确
图 4-7 多重循环示意图
2,循环程序设计举例
【 例 】 有一数据块从片内 RAM的 30H单元开始存入,
设数据块长度为 10个单元 。 根据下式:
X+2 X>0
Y= 100 X=0 求出 Y值, 并将 Y值放回原处 。
∣ X∣ X<0
解:设置一个计数器控制循环次数, 每处理完一
个数据, 计数器减 1。 程序流程如图所示 。
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?
参考程序:
ORG 2000H
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 $ ;暂停
4.2.5 子程序
1,子程序概念
所谓调用子程序, 暂时中断主程序的执行, 而转
到子程序的入口地址去执行子程序 。 如图所示 。
RET
LCALL SUB
子程序的调用与返回
调用子程序应注意:
( 1)子程序占用的存储单元和寄存器。
( 2)参数的传递。
( 3)子程序经过调用后得到的数据来完成程序
之间的参数传递。
( 4)嵌套调用与递归调用。如图所示。
LCALL A
RETRET
LCALL B
子程序的嵌套调用与返回
2,子程序设计举例
【 例 】 有一数据块从片内 RAM的 30H单元开始存入,
设数据块长度为 10个单元 。 根据下式:
X+2 X>0
Y= 100 X=0 求出 Y值, 并将 Y值放回原处 。
∣ X∣ X<0
解:数据块中的十个数都需要进行符号判断并作相应
处理, 可把一部分工作交给子程序完成, 主程序只负
责读取数据, 调用判断处理子程序, 保存数据, 循环
控制工作 。 源程序如下:
ORG 0000H
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