返回主页 单片机教程XL2000开发板 单片机学习 自制编程器 单片机资料 软件下载 电子技术产品介绍如何购买 进入论坛

单片机教程第1课  教学资料单片机教程第18课  算术指令
单片机教程第2课  好书推荐单片机教程第19课  逻辑指令
单片机教程第3课  单片机不易掌握的概念单片机教程第20课  逻辑指令
单片机教程第4课  实战一:流水灯单片机教程第21课  转移指令
单片机教程第5课  实战二:唱歌单片机教程第22课  位操作
单片机教程第6课  测试一单片机教程第23课  计数定时器
单片机教程第7课  新教程前言单片机教程第24课  计数定时器
单片机教程第8课  总体规划单片机教程第25课  中断系统
单片机教程第9课  概述单片机教程第26课  中断练习
单片机教程第10课  单片机结构单片机教程第27课  定时计数实验2
单片机教程第11课  基本概念单片机教程第28课  串行口
单片机教程第12课  延时程序分析单片机教程第29课  串口实例
单片机教程第13课  延时程序分析单片机教程第30课  数码管编程
单片机教程第14课  并口结构单片机教程第31课  动态数码管编程
单片机教程第15课  结构分析单片机教程第32课  键盘接口编程
单片机教程第16课  寻址方式单片机教程第33课  键盘扫描编程
单片机教程第17课  上机练习 单片机教程第34课  指令介绍        平凡的单片机教程

单片机指令

2、累加器A与片外RAM之间的数据传递类指令

MOVX A,@Ri

MOVX @Ri,A

MOVX    A,@DPTR

MOVX @DPTR,A

说明:

1)在51中,与外部存储器RAM打交道的只可以是A累加器。所有需要送入外部RAM的数据必需要通过A送去,而所有要读入的外部RAM中的数据也必需通过A读入。在此我们可以看出内外部RAM的区别了,内部RAM间可以直接进行数据的传递,而外部则不行,比如,要将外部RAM中某一单元(设为0100H单元的数据)送入另一个单元(设为0200H单元),也必须先将0100H单元中的内容读入A,然后再送到0200H单元中去。

2.       要读或写外部的RAM,当然也必须要知道RAM的地址,在后两条指令中,地址是被直接放在DPTR中的。而前两条指令,由于Ri(即R0R1)只是一个8位的寄存器,所以只提供低8位地址。因为有时扩展的外部RAM的数量比较少,少于或等于256个,就只需要提供8位地址就够了。

3.       使用时应当首先将要读或写的地址送入DPTRRi中,然后再用读写命令。

例:将外部RAM100H单元中的内容送入外部RAM200H单元中。

MOV DPTR#0100H

MOVX A@DPTR

MOV DPTR,#0200H

MOVX @DPTR,A

3.       程序存储器向累加器A传送指令

MOVC A@A+DPTR

本指令是将ROM中的数送入A中。本指令也被称为查表指令,常用此指令来查一个已做好在ROM中的表格

说明:

1.       此条指令引出一个新的寻址方法:变址寻址。本指令是要在ROM的一个地址单元中找出数据,显然必须知道这个单元的地址,这个单元的地址是这样确定的:在执行本指令立脚点DPTR中有一个数,A中有一个数,执行指令时,将ADPTR中的数加起为,就成为要查找的单元的地址。

2.       查找到的结果被放在A中,因此,本条指令执行前后,A中的值不一定相同。

例:有一个数在R0中,要求用查表的方法确定它的平方值(此数的取值范围是0-5

MOV DPTR#TABLE

MOV AR0

MOVC A@A+DPTR

.

.

TABLE:     DB 0,1,4,9,16,25

R0中的值为2,送入A中,而DPTR中的值则为TABLE,则最终确定的ROM单元的地址就是TABLE+2,也就是到这个单元中去取数,取到的是4,显然它正是2的平方。其它数据也可以类推。




标号的真实含义:从这个地方也可以看到另一个问题,我们使用了标号来替代具体的单元地址。事实上,标号的真实含义就是地址数值。在这里它代表了,01491625这几个数据在ROM中存放的起点位置。而在以前我们学过的如LCALL DELAY指令中,DELAY 则代表了以DELAY为标号的那段程序在ROM中存放的起始地址。事实上,CPU正是通过这个地址才找到这段程序的。


可以通过以下的例子再来看一看标号的含义:


MOV DPTR#100H


MOV AR0


MOVC A@A+DPTR


.

ORG 0100H.

  DB0,1,4,9,16,25

如果R0中的值为2,则最终地址为100H+2102H,到102H单元中找到的是4。这个可以看懂了吧?

那为什么不这样写程序,要用标号呢?不是增加疑惑吗?

如果这样写程序的话,在写程序时,我们就必须确定这张表格在ROM中的具体的位置,如果写完程序后,又想在这段程序前插入一段程序,那么这张表格的位置就又要变了,要改ORG 100H这句话了,我们是经常需要修改程序的,那多麻烦,所以就用标号来替代,只要一编译程序,位置就自动发生变化,我们把这个麻烦事交给计算机指PC机去做了。

堆栈操作

PUSH direct

POP direct

第一条指令称之为推入,就是将direct中的内容送入堆栈中,第二条指令称之为弹出,就是将堆栈中的内容送回到direct中。推入指令的执行过程是,首先将SP中的值加1,然后把SP中的值当作地址,将direct中的值送进以SP中的值为地址的RAM单元中。例:

MOV      SP#5FH

MOV      A#100

MOV      B#20

PUSH      ACC

PUSH      B

则执行第一条PUSH ACC指令是这样的:将SP中的值加1,即变为60H,然后将A中的值送到60H单元中,因此执行完本条指令后,内存60H单元的值就是100,同样,执行PUSH B时,是将SP+1,即变为61H,然后将B中的值送入到61H单元中,即执行完本条指令后,61H单元中的值变为20

POP指令的执行是这样的,首先将SP中的值作为地址,并将此地址中的数送到POP指令后面的那个direct中,然后SP1

接上例:

POP B

POP ACC

则执行过程是:将SP中的值(现在是61H)作为地址,取61H单元中的数值(现在是20),送到B中,所以执行完本条指令后B中的值是20,然后将SP1,因此本条指令执行完后,SP的值变为60H,然后执行POP ACC,将SP中的值(60H)作为地址,从该地址中取数(现在是100),并送到ACC中,所以执行完本条指令后,ACC中的值是100

这有什么意义呢?ACC中的值本来就是100B中的值本来就是20,是的,在本例中,的确没有意义,但在实际工作中,则在PUSH B后往往要执行其他指令,而且这些指令会把A中的值,B中的值改掉,所以在程序的结束,如果我们要把AB中的值恢复原值,那么这些指令就有意义了。

还有一个问题,如果我不用堆栈,比如说在PUSH ACC指令处用MOV 60HA,在PUSH B处用指令MOV 61HB,然后用MOV A60HMOV B61H来替代两条POP指令,不是也一样吗?是的,从结果上看是一样的,但是从过程看是不一样的,PUSHPOP指令都是单字节,单周期指令,而MOV指令则是双字节,双周期指令。更何况,堆栈的作用不止于此,所以一般的计算机上都设有堆栈,而我们在编写子程序,需要保存数据时,通常也不采用后面的方法,而是用堆栈的方法来实现。

例:写出以下程序的运行结果

MOV      30H#12

MOV      31H#23

PUSH      30H

PUSH      31H

POP 30H

POP 31H

结果是30H中的值变为23,而31H中的值则变为12。也就两者进行了数据交换。从这个例子可以看出:使用堆栈时,入栈的书写顺序和出栈的书写顺序必须相反,才能保证数据被送回原位,否则就要出错了。

作业:在MCS51下执行上面的例程,注意观察内存窗口和堆栈的变化。