资源描述
第八节 汇编语言程序的格式和伪指令
一、 格式
标号区 操作码 操作数 注释
MOV R0, #data ;指向“源数据区”
MOV DPTR,#BUFFER ;指向“接收区”
MOV R1, #20H ;传送最大字节数
LOOP: MOV A, @R0 ;取一个字节
CJNE A, #24H,SEND ;是“$”?NO,转
SJMP RTN ;是,返回
SEND: MOVX @ DPTR,A ;传送一个字节
INC R0 ;指向下一个待传数据
INC DPTR ;指向下一个接收单元
DJNZ R1,LOOP ;32字节已经传完?
RTN: RET ;已经传完
;或找到“$”,返回
目的
源
R0 data DPTR BUFFER
程序功能:把内RAM中,起始地址为data的32个字节(“源”)传送到外RAM中,从BUFFER开始的区域(“目的”);在传送中,如果发现“$”(ASCII码24H),立刻停止传送。
以本程序为例,介绍汇编语言源程序的格式:
1.标号区
*符号地址
在数值地址不知道的情况下,使用符号地址;
使用有意义的符号地址
*可选项
*不可重复使用
*以字母打头
*长度规定
*保留字
2.操作码区
指令助记符
3.操作数
提供数据、地址信息
4.注释区
*提高程序的可读性
*“;” 打头
*必须有意义
指令或程序段在整个程序中的作用
*非执行部分,但是是重要的组成部分
二、 伪指令
指令——告诉CPU进行某种操作,由硬件完成具体操作。
伪指令——为汇编程序提供汇编信息,其功能由相应的软件来完成
汇编程序—— 一段特殊的程序,其功能就是把汇编程序“翻译”为机器代码。在“翻译”过程中,汇编程序需要了解若干信息才能顺利完成全部“翻译”工作,如:
*各个符号数据的数值是多少?
*各个符号地址怎么分配或预留存储器单元?
*如何在翻译的过程中,把常数存放在存储器的指定单元?
*已经“翻译”就绪的代码存放在存储器的什么地方?
*“翻译”工作怎么时候结束?
这一系列工作,主要是靠伪指令来完成的。
常用的伪指令。
1 ORG origin 起点命令
*规定目标程序的起始地址——第一条指令的 第一个字节存放在ROM区什么地方。
ORG 2000H ;以下程序代码从2000H开始存放
:
:
2.END 汇编终止命令
*汇编工作到此结束
3.EQU equate 赋值命令
*给符号地址、符号数据赋值
如: data EQU 30H
BUFFER EQU 2500H
4. DB DEFB define byte
定义数据字节命令
*功能:把字节数据送入指定的单元并给第一个单元分配一个名称
ORG 1000H
FIRST:DB 73H,01H,01H,90H,38H,00H,01H,00H
SECOND:DB 02H,00H
73
00
02
汇编后:
1000H
1000H的名称是FIRST
1008H的名称是SECOND
1007H
1008H
5. DW (EFW) define word
*高位字节在低位地址
*低位字节在高位地址
ORG 3000H
DW “A”
00
41
01
00
01
AC
D2
FC
DW` 100H,1ACH,-814
A
3000H
3001H
100H
1ACH
-814
汇编语言程序设计示例
例3-1 将一双字节数存入片内RAM。
设该待存双字节高字节在工作寄存器R2中,低字节在累加器A中,要求高字节存入片内RAM的36H单元,低字节存入35H单元。
则相应程序为
00B0 78 35 MOV R0,#35H
00B2 F6 MOV @R0, A
00B3 08 INC R0
00B4 CA XCH A, R2
00B5 F6 MOV @R0, A
00B6 CA XCH A, R2
⑥ R0 ③
R2 高 A低
36H 35H
R0
⑤
(R2) ①
④ (A) ②
例3-2 多字节无符号相加
设被加数与加数已别在以ADR1与ADR2为初址的片内数据存贮器区域中,自低字节起,由低到高依次存放;它们的字节数为L;要求加得的和放回原放被加数的单元。
程序的流程图如图3-5所示。
相应的程序如下:
0030 78 ADR1 MOV R0,#ADR1
0032 79 ADR2 MOV R1,#ADR2
0034 7A L MOV R2,#L
0036 C3 CLR C
0037 E6 LOOP: MOV A,@R0
0038 37 ADDC A,@R1
0039 F6 MOV @R0,A
003A 08 INC R0
003B 09 INC R1
003C DA F9 DJNZ R2,LOOP
003E DONE: ↙
例3-4
将R1、R2、R3、R4四个工作寄存器中的BCD码数据依次相加,要求各中间计算的和与最后的各都仍为BCD码,且放回片内RAM。
设4个工作寄存器中BCD码数据相加后其总和仍为二位BCD码,无溢出;
(R1)+(R2)后的和存于片内RAM的30H单元,再加(R3)后的和存于31H单元,总的和存于32H单元 ,则主程序为:
R0
BCD
BCD
BCD
BCD
.
+
R1 30H
R2 31H
R3 +(30H). 32H
R4 + (31H)
部分和存入30H、31H;总和存入32H
ORG 0050H
0050 73 30 MOV R0, #30H ;R0指向存和单元
0052 E9 MOV A, R1 ;取一个加数
0053 2A ADD A, R2 ;部分和
0054 31 A0 ACALL SUB ;完成十进制调整、存和
0056 2B ADD A,R3 ;求和
0057 31 A0 ACALL SUB ;完成十进制调整、存和
0059 2C ADD A,R4
005A 31 A0 ACALL SUB
┇
┇
子程序为:
ORG 01A0H ;十进制调整与存和子程序
01A1 D4 SUB: DA A ;十进制调整
01A2 F6 MOV @R0,A ;存和(BCD)
01A3 08 INC R0, ;指向下一个单元
01A4 22 RET ;
例3-8 统计自P1口输入的数串中正数、负数、零的个数。
设:R0、R1、R2三个工作寄存器分别为累计正数、负数、零的个数的计数器。
START: CLR A
MOV R0, A ;三个计数器清0
MOV R1, A
MOV R2, A
ENTER: MOV A, P1 ;从P1口取一个数据到A
JZ ZERO ;如果该数为0,转RERO
JB P1.7,NEG ;如果该数为负,转NEG(P1.7=1,转)
INC R0 ;为正,正数个数计数器加1
SJMP ENTER ;转,继续从P1口取数据、判断
ZERO: INC R2 ;为0,0个数计数器加1
SJMP ENTER
NEG: INC R1 ;为负,负数个数计数器加1
SJMP ENTER
本例所示的程序的问题;
(1)未考虑数串究竟有多少个数,输入不能结束;
(2)未考虑P1口上数据输入速度与计算机取数和分档处理速度间的协调配合。如已知:
数串的个数为L;送数的速度为每秒1个;
计算机取数、处理的速度极快,与1秒比较可忽略不计。
考虑程序应作怎样改动?
例3-10 将某8位二进制转换为BCD码(略)
设该8位二进制已在A中,转换后存贮于片内RAM的20H、21H单元。
转换方式:(A)÷100(01100100B) 商 (百位数之值)
余数÷10(1010) 商 (十位数之值)
余数 (个位数之值)
例:把01100110B(102D)转换为BCD
.. 1 百位
1100100 1100110
.. 1100100
10 余数
0 十位
1010 10
0
10 个位
1:0001 0:0000 10:0010
(0001 0000 0010)BCD
程序如下:
MOV B, #100 ;除数
DIV AB ;(A):商即百位数0000BCD;
;(B)余数
MOV R0, #21H ;
MOV @R0, A ;百位数存入21H
DEC R0 ;
MOV A, #10 ;除数
XCH A, B ;余数送入A,除数送入B
DIV AB ;(A):十位数 0000BCD
;(B):个位数 0000BCD
SWAP A ;BCD0000
ADD A、B ;BCDBCD
MOV @R0,A ;存入20H
21H 0000 BCD
29H BCD BCD
例3-12 将一串十六进制数转换为ASCⅡ码。
十六进制数串(5个字节)存于以ADR1为起始地址的内存区域中,转换后拟存到以ADR2为起始地址的内存区域去。编出的程序如下。
HEX ASCII
转换方法
0 30
1 31 加30H即可
: :
9 39
A 41
B 42
C 43 加37H即可
D 44
E 45
F 46
1)先判断在哪一个区(通过加246来判断)
2)0~9:加30H A~B:先加7,再加30H
MOV R0, #ADR1
MOV R1, #ADR2
MOV R2, #05H ;计数器
LOO MOV A, @R0 ;取一字节(2位)16进制数
ANL A,#0FH ;高位数清0,保留低位
ACALL SUB ;调子程序完成1位16
;进制数转换为ASCII
;存入ADR2开始的单元
MOV A,@R0 ;再取同一字节
ANL A,#0F0H ;保留高位,低位清0
SWAP A ;高、低互换
ACALL SUB ;
INC R0 ;指向下一字节
DJNZ R2,LOOP ;所有字节已经转换完?
;未完,继续。
;
SUB: MOV R3, A ;存一位16进制数
ADD A, #0F6H ;加246
;若(A)<=9,则和<=255,Cy=0
;若(A)>=10,则和>255,Cy=1
MOV A, R3 ;取回原一位16进制数
JNC AD30 ;<=9,转,加30H
ADD A, #07H ;>=10,先加7,再加30H
AD30: ADD A, #30H ;
MOV @R1,A ;ASCII存入R1所指单元
INC R1 ;指向下一个存ASCII的单元
RET
高 低
:
:
ASCII(低)
ASCII(高)
:
:
R0 ADR1
16进制数串
R1 ADR2
ASCII
多分支转移(散转)程序
例3-14 设计可多达128路分支出口的转移程序
设:1)控制转移的信息存放在R2中(00~7F)
2)128个出口分别转向128段程序,它们的初始址依次为addr00、addr01、addr02;addr03、…、addr7F;
3)把128条转移指令集中形成一个转移指令表
则散转程序为:
MOV DPTR, #TAB ;指向转移指令表
MOV A, R2 ;取控制转移的信息
RL A ;x2(每条指令占2个单元)
JMP @A+DPTR ;从表中取某一转移指令
TAB: AJMP addr00 ;以下是转移指令表
AJMP addr01
┇
┇
AJMP addr7F
*如果(R2)=01 “RL A”执行后 (A)=02
TAB+02 AJMP ADDR01 ADDR01
*如果(R2)=7FH “RL A”执行后 (A)=FEH
TAB+FE AJMP ADDR7F ADDR7F
要求:
程序0
JMP @A+DPTR
AJMP ADDR00
AJMP ADDR01
AJMP ADDR7F
R2=00 ADDR00
程序1
TAB+0 R2=01 ADDR01
转移指令表
+1
程序2
+2 ADDR03
+3
+4
+5
程序127
R2=7F ADDR7F
+FEH
+FFH
定时器/计数器应用程序
例3-18 要求利用单片机内部的定时器/计数器,达到1分钟延时。
1)单片机内部的一个定时器/计数器,按定时器方式工作,最长延时时间只有60ms左右(在12MHz晶振条件下)。
2)通过T/C0和T/C1配合使用,可以实现长延时
*T/C0作为定时器,定时时间1ms,在fosc=12M时,Tcy=1µs
计数初值=65536-1000=64536D=FC18H
每到1ms,用软件方式向T1提供一个计数脉冲
*T/C1作为计数器,对1ms脉冲串计数,每计满60000次,表明1分种到。
计数初值=65536-60000=5536D=15A0H
计数溢出时,发出中断请求,在T/C1的中断服务程序中,把用户标志位(F0)置1,于是每当F0=1时,就表明1分定时到。
3)按本例的方式延时,计算机仍可同时承担其它工作,不至完全降格为单纯的“电子钟”,这是此种延时方式的特点。
ORG 0000H
LJMP 0030H ;复位就进入主程序
ORG 001BH ;T/C1中断入口
SETB F0 ;建立用户标志(表明1分定时到)
RETI ;中断返回
ORG 0030H ;主程序
START: ┇
┇
MOV TMOD,#01010001B ;确定TC0,T/C1方式1,
;非门控;T/C1计数,T/C0定时
REPEAT:MOV TH1,#15H ;T/C1置初值
MOV TL1,#A0H ;计数60000次
MOV TH0,#FCH ;T/C0初值
MOV TL0,#18H ;定时1ms
CLR P3.5 ;T1设为低电平
MOV IE,#88H ;中断总允许,T/C1中断允许
SETB TR1 ;启动T/C1开始计数
SETB TR0 ;启动T/C0开始定时
LOOP: ┇ ;在接近1ms的时间内,CPU
┇ ;可以处理其它事务
JNB TF0,$ ;1ms到?尚未,继续执行本指令
CLR TF0 ;已到,清除T/C0溢出标志
JBC F0,ELSE ;1分定时到?已到,转
SETB P3.5 ;尚未,使T1变为高电平
;向T/C1提供一个计数脉冲上升边
MOV TH0,#FCH ;T/C0初值重新装载
MOV TL0,#18H ;
CLR P3.5 ;使T1出现低电平。到此,T/C1
;已经确认了一个计数脉冲。当
;确认了60000次时,TF1=1
;转入001BH
SJMP LOOP ;准备产生下一次计数脉冲并计数
ELSE: ┇ ;1分钟定时到,执行相关程序
┇
AJMP 04BH ;转REPEAT(04BH)
软件产生计数脉冲示意
8M 第60000个
1ms 1ms
SET P3.5
CLR P3.5 硬件置1
1分 硬件复位
TF=1转001BH
MOV TH0,#FCH ;3M
MOV TL0,#18H ;3M
CLR P3.5 ;2M
外部中断应用程序
例3-20 某工业监控系统,具有温度、压力、pH值、┅ 等多路监控功能。对于pH值在<7时将向CPU申请中断,CPU响应后令P3.0引脚输出高电平,经驱动,使加碱管道电磁阀接通1s,以调整pH值。
本例外部中断源较多。设pH<7时通过外部中断0申请中断。而由外部中断0提出中断请求的中断源有好几个,究竟是哪一项监控参数报警需用在检查P1口信息后判定,并转相应的中断服务程序入口地址,作出相应处理。
P3.2
即INT0
单
片
P1.0
机 P1.1
P1.2
P1.3
┇
P1.6
P3.0
Q D
R CLK
压力
中断撤除
R=0 Q=0
R=1 CLK Q=1
加碱电磁阀
驱动
01
F0
00
01
30
温1中断
处理程序
AJMP MAIN
0000H INT00
温2中断
处理程序
AJMP 030H
0003H INT01
PH<7中断
处理程序
中断查
询程序
0030H INT03
压力中断
处理程序
INT03
主程序
00F0H
程序段如下:
0000 01 F0 AJMP 0F0H ;转入主程序
0002 00 DB 00H
0003 01 30 AJMP 030H ;转入中断查询程序
ORG 0030H
;
;
0030 20 90 0D JB P1.0,INT00
0033 20 91 2A JB P1.1,INT01
0036 20 92 47 JB P1.2,INT02
0039 20 93 64 JB P1.3,INT03
ORG 0080H ;处理PH<7的程序
0080 C0 D0 INT02: PUSH PSW
0082 C0 E0 PUSH ACC
0084 D2 D3 SETB PSW.3 ;1区
0086 D2 B0 SETB P3.0 ;接通电磁阀
0088 51 00 ACALL DELAY ;延时1s
008A C2 B0 CLR P3.0 ;关断电磁阀
008C 53 90 BF ANL P1, #0BFH ;撤除中断请求
008F 43 90 40 ORL P1, #40H ;为下次申请中断做准备
0092 D0 E0 POP ACC ;恢复A
0094 D0 D0 POP PSW ;恢复PSW,0 区
0096 32 RETI
例3-21 利用外部中断实现各程序间的转换(略)
设有6个共阴极LED数码管,数码的笔划信息由单片机P1.0~P1.6送给,位选的选中信号自左到右依次由P3.1、P3.3、P3.4、P3.5、P3.6、P3.7提供,如图3-9所示。共阴极LED数码管的示意图与显示0、1、2、3、……、E、F的笔划信息编码表分别如图3-10与表3-10所示。
关于LED显示器及显示原理
a
f
e
b
c
1.显示原理 g
共阳极,段控制信号加在阴极上
共阴极,段控制信号加在阳极上 d 。h
=0,亮
=1,亮
段选开关
字符段码
段代码
反
向
驱
动
a
b
c
d
e
f
g
dp
:. :
:. :
:. 共阴 :
:. :
:. :
位选开关
显然,要控制LED显示器,有两个基本动作:
1) 根据待显字符的字符段码(笔划信息),闭合相应的段选开关
2) 闭合位选开关
注意在编程时如何体现这两点
2.字符与字符段码的关系:
以共阴极接连法为例: 显示“1”,应该使 b,c两段LED发光,
控制信号(字符段码)应该是:
D7 D6 D5 D4 D3 D2 D1 D0
dp g f e d c b a
0 0 0 0 0 1 1 0 字符段码:06H
显示“3”,a,b,c,d,g发光:
D7 D6 D5 D4 D3 D2 D1 D0
dp g f e d c b a
0 1 0 0 1 1 1 1 字符段码:4FH
P130 表3-10给出了对应关系。
本例中,以P1.0~P1.6,输出笔划信息(字符段码);
P3.1、P3.3、P3.4、P3.5、P3.6、P3.7给出位选信号
L6
L5
L4
L3
L2
L1
P1.0
:
P1.6
P3.1
P3.3
P3.4
P3.5
P3.6
P3.7
各程序段可分别使该6个数码管显示111222、121212、333444、343434、555666、565656、777888、……。
利用外部中断实现各程序段转换的程序如下:
0000 LJMP 0030H ;进入主程序
0003 AJMP 320H
;在INT0中断入口填写转移指令,实质性的中断服务程序
;存放在320H开始的单元
;主程序
0030 MOV IE, #81H ;INT0中断允许,总允许
0033 ROUTI: MOV P1, #06H ;“1”
0036 MOV P3, #E4H ;选中L1、L2、L3
0039 ACALL DELAY ;延时,显示“111”
003B MOV P1, #5BH ;“2”
003E MOV P3, #1EH ;选中L4、L5、L6
0041 ACALL DELAY ;延时,显示“222”
0043 JB F0, $+5 ;程序段转换?Y,转P2
0046 SJMP ROUTI ;N,继续显示111222
0048 P2 CLR F0
004A ROUT2:MOV P1,#06H ;“1”
004D MOV P3,#ACH ;L1、L3、L5
0050 ACALL DELAY ;
0052 MOV P1,#5BH ;“2”
0055 MOV P3,#56H ;L2、L4、L6
0058 ACALL DELAY
005A JB F0,$+5 ;程序段转换?Y,转P3
005D SJMP ROUT2 ;N,继续显示121212
005F P3 CLR F0
0061 ROUT3: MOV P1,#4FH ;“3”
0064 MOV P3,#E4H ;选中L1、L2、L3
0067 ACALL DELAY
0069 MOV P1,66H ;“4”
006C MOV P3,#1EH ;选中L4、L5、L6
006F ACALL DELAY
0071 JB F0,$+5 ;程序段转换?Y,转P4
0074 SJMP ROUT3 ;N,继续显示“333444”
0076 P4: CLR F0
0078 ROUT4: MOV P1,#4FH ;
007B MOV P3,#ACH ;
007E ACALL DELAY
0080 MOV P1,#66H ;
0083 MOV P3,#56H ;
0086 ACALL DELAY
0088 JB F0,$+5
008B SJMP ROUT4 ;“343434”
008
展开阅读全文