单片机原理及应用(第2版)
上QQ阅读APP看书,第一时间看更新

4.4 数据传送类指令

数据传送类指令是使用频率最高的一类指令。主要用来给8051单片机系统的内部和外部资源赋值、进行堆栈的存取操作等。数据传送类指令执行前后,对程序状态字PSW一般不产生影响。按其操作方式,又可把它们分为3种:数据传送、数据交换和栈操作。

4.4.1 数据传送指令

1.通用传送指令——MOV

MOV指令的作用区间主要是内部数据存储器,它提供了丰富的传送操作,并有4种寻址方式:立即寻址、寄存器寻址、寄存器间接寻址和直接寻址。由于利用Rn可直接访问某工作寄存器,利用@Ri可间接寻址片内数据RAM的某一字节单元,而直接寻址则可遍访片内数据RAM(00H~7FH)和特殊功能寄存器空间,因而对于双操作数的数据传送指令允许在工作寄存器、片内数据RAM、累加器A和特殊功能寄存器SFR任意两个之间传送一个字节的数据,而且立即操作数能送入上述任何单元中。特别值得指出的是,直接地址到直接地址之间的数据传送,它能将一个并行I/O口中的内容直接传送到内部RAM单元中而不必经过任何工作寄存器或累加器A,从而提高了传送速度。此外,利用MOV指令还可以把16位的立即数直接送入数据指针DP TR中。

格式:MOV <目的字节>,<源字节>

功能:把第二操作数指定的字节变量传送到由第一操作数指定的单元中,不影响源字节,不影响任何别的寄存器,一般不影响标志位。这是最灵活的操作,允许15种源和目的寻址方式组合。

(1)立即数送累加器A和内部数据存储器(Rn、片内RAM、SFR)

共有4条指令:

@符号表示间接寻址,((Ri))表示把立即数送到由Ri寄存器的内容所指出的那个RAM单元中去。Ri中i=0或i=1。

利用直接寻址可把立即数送入片内RAM任意单元或任意特殊功能寄存器,如:

(2)内部数据存储器(Rn、片内RAM、SFR)与累加器A传送数据

共有6条指令:

间接寻址@Ri是以Ri的内容作为地址进行寻址,由于Ri为8位寄存器,所以其寻址范围可为00H~FFH。但由于特殊功能寄存器只能被直接寻址,对于8051单片机,在SFR地址范围(80H~FFH)中很多单元又无定义,若对之读写,将得不到确定的值,写入的数也将丢失。所以,对8051单片机内部数据存储器来说,间接寻址的真正作用范围实际上只有00H~7FH共127个单元的片内数据RAM地址。例如,指令序列:

上述指令对于8051单片机是不正确的,因为82H是特殊功能寄存器DPL的地址值,对特殊功能寄存器来说,这种间接寻址方式无效。但是,对于8052单片机而言则是正确的,其功能是将片内RAM的82H单元中的内容送到A中。并且,对于8052片内80H~FFH的RAM单元,只能使用这种间接寻址方式进行访问。

欲从DPL取数到累加器A,可用直接寻址方式:

(3)Rn、SFR和内部RAM之间的数据传送

共有5条指令:

该5条指令共有3种寻址方式:直接寻址,寄存器寻址,寄存器间接寻址。

对于直接寻址方式,8位直接地址可寻址0~255个单元,对于8051单片机而言,则可直接寻址片内RAM 00H~7FH地址空间的单元和所有特殊功能寄存器,对80H~FFH地址中无定义的单元访问是没有意义的。

若设PSW中标志位RS1、RS0为“11”,则选中第三组工作寄存器,此时,以下两条指令是等价的:

用立即寻址指令可直接给片内RAM中30H和P1口上置数:

执行后使(30H)=25H,(P1)=0CAH。

(4)目标地址传送

功能:把16位常数装入数据指针。只有一条指令:

表示把16位常数装入数据指针。执行后,DPTR=2050H,其中DPH=20H,DPL=50H。

2.外部数据存储器(或I/O口)与累加器A传送指令——MOVX

MOVX指令主要用于累加器A和外部扩充RAM或I/O口进行数据传送。这种传送只有一种寻址方式,就是寄存器间接寻址。有以下两种寄存器间接寻址。

(1)用R1或R0进行寄存器间接寻址

这种方式能访问外部数据存储器(或I/O口)256字节中的一个字节。若要访问更大的空间,需使用P2口输出高8位地址,此时需要先给P2和Ri赋值,然后执行MOVX指令。

(2)用16位的数据存储器地址指针DPTR进行寄存器间接寻址

这种方法能遍访64 KB的外部数据存储器(或扩展的I/O口)的任何单元。

指令格式:MOVX<目的字节>,<源字节>

共4条指令:

由于使用R1或R0寄存器间接寻址方式访问外部数据存储器时,寻址范围受到256个字节的限制,因此,在实际应用中,一般使用DPTR寄存器间接寻址方式访问外部数据存储器

若片外数据存储器单元中:(2100H)=(60H),(2101H)=(2FH),则执行:

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

对于程序存储器的访问,8051单片机提供了两条极其有用的查表指令。这两条指令采用变址寻址,以P C或DP TR为基址寄存器,以累加器A为变址寄存器,基址寄存器与变址寄存器内容相加得到程序存储器某单元的地址值,MOVC指令把该存储单元的内容传送到累加器A中。指令格式:

功能:把累加器A中内容与基址寄存器(PC、DPTR)中内容相加,求得程序存储器某单元地址,再把该地址单元中保存的内容送累加器A。指令执行后不改变基址寄存器内容,由于执行16位加法,从低8位产生的进位将传送到高位去,不影响任何标志位。

这两条指令主要用于查表,即完成从程序存储器读取数据的功能。但由于两条指令使用的基址寄存器不同,因此使用范围也不同。

前一条指令以PC作为基址寄存器,在CPU取完指令操作码时PC会自动加1,指向下一条指令的第一字节地址,所以这时作为基址寄存器的PC已不是原值,而是PC+1。因为累加器中的内容为8位无符号整数,这就使得本指令查表范围只能在以P C当前值开始后的256字节范围内,使表格地址空间分配受到限制,同时编程时还需要进行偏移量的计算,公式为

偏移量DIS=表首地址-(该指令所在地址+1)

例4-1】 根据累加器A的内容查表获得多个值中的一个。

:可用下列程序代码:

其中,DB是伪指令,其作用是将它后面的值(55H、66H等)存入由标号getval+4开始的连续单元中。若累加器A的原内容为02H,则执行上述程序后,返回时(执行RET指令),累加器的值将变为77H。

后一条指令基址寄存器为数据指针DPTR,由于可以给DPTR赋不同的值,使得该指令应用范围较为广泛,表格常数可设置在 64 KB程序存储器的任何地址空间,而不必像MOVC A,@A+P C指令只能设在P C值以下的256个单元中。其缺点是,若DP TR已有它用,在将表首地址赋给DP TR之前必须保护现场(使用P USH指令将DP TR压入堆栈保护),执行完查表后再予以恢复(使用POP指令从堆栈中弹出内容到DPTR)。

例4-2】 试编制根据累加器A中的数(0~9之间)查其平方表的子程序。

:程序代码如下:

其中,平方表使用DB伪指令定义。为了便于阅读,定义字节数据时,采用了十进制表示。

注:在实际应用中,由于DPTR可以根据需要进行灵活赋值,因此一般使用DPTR作为基址寄存器而不使用PC作为基址寄存器

4.4.2 数据交换指令

数据交换指令包括字节交换指令和半字节交换指令。

1.字节交换指令

上述指令把累加器A中内容与第二操作数所指定的工作寄存器、间接寻址或直接寻址的某单元内容互相交换。

设(R0)=20H,(A)=3FH,(20H)=75H,执行指令

2.半字节交换指令

该指令把累加器A的低4位和寄存器间接寻址的内部RAM单元的低4位交换,高4位内容不变,不影响标志位。

设R1的内容为30H,A的内容为69H,内部RAM中30H的内容为87H,执行指令

4.4.3 栈操作指令

上述两条指令完成两种基本堆栈操作,一种叫压入堆栈(PUSH),一种叫弹出堆栈(POP)。堆栈中的数据以“后进先出”的方式处理,这种“后进先出”的特点由堆栈指针SP来控制,SP用来自动跟踪栈顶地址。由于单片机堆栈编址采用向上生成方式,即栈底占用较低位地址,栈顶占用较高位地址,所以其过程如下。

入栈操作:先(SP)+1→(SP),指向栈顶的上一个空单元,然后把直接寻址单元的内容压入SP所指的单元中。

出栈操作:先弹出栈顶内容到直接寻址单元,然后(SP)-1→(SP),形成新的堆栈指针。

由此可见,P USH和P OP是两种逆传送指令,它们常被用在保护现场(即把寄存器的内容暂存在内存区)和恢复现场的程序中。

该程序执行后,累加器ACC和PSW寄存器中的内容可得到正确的恢复。

若为

则执行后,将使得ACC和PSW中的内容互换。

在数据传送类操作中应注意以下几点。

1)除了用POP或MOV指令将数据传送到PSW外,传送操作一般不影响标志位。当向累加器中传送数据时,会影响PSW中的P标志。

2)执行传送类指令时,把源地址单元的内容送到目的地址单元后,源地址单元中的内容不变。

3)对特殊功能寄存器SFR的操作必须使用直接寻址,也就是说,直接寻址是访问SFR的唯一方式。

4)对于8052单片机内部RAM的80H~FFH单元只能使用@Ri间接寻址方式访问。

5)将累加器A压入堆栈或弹出堆栈时,应使用PUSH ACC和POP ACC指令,不能使用P USH A和P OP A指令。否则,程序编译会出错。